diff options
| -rw-r--r-- | include/kvm/arm_arch_timer.h | 27 | ||||
| -rw-r--r-- | virt/kvm/arm/arch_timer.c | 69 | ||||
| -rw-r--r-- | virt/kvm/arm/hyp/timer-sr.c | 10 |
3 files changed, 56 insertions, 50 deletions
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 5c970ce67949..daad3c133b9f 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h | |||
| @@ -28,15 +28,20 @@ struct arch_timer_kvm { | |||
| 28 | u64 cntvoff; | 28 | u64 cntvoff; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | struct arch_timer_cpu { | 31 | struct arch_timer_context { |
| 32 | /* Registers: control register, timer value */ | 32 | /* Registers: control register, timer value */ |
| 33 | u32 cntv_ctl; /* Saved/restored */ | 33 | u32 cnt_ctl; |
| 34 | u64 cntv_cval; /* Saved/restored */ | 34 | u64 cnt_cval; |
| 35 | |||
| 36 | /* Timer IRQ */ | ||
| 37 | struct kvm_irq_level irq; | ||
| 38 | |||
| 39 | /* Active IRQ state caching */ | ||
| 40 | bool active_cleared_last; | ||
| 41 | }; | ||
| 35 | 42 | ||
| 36 | /* | 43 | struct arch_timer_cpu { |
| 37 | * Anything that is not used directly from assembly code goes | 44 | struct arch_timer_context vtimer; |
| 38 | * here. | ||
| 39 | */ | ||
| 40 | 45 | ||
| 41 | /* Background timer used when the guest is not running */ | 46 | /* Background timer used when the guest is not running */ |
| 42 | struct hrtimer timer; | 47 | struct hrtimer timer; |
| @@ -47,12 +52,6 @@ struct arch_timer_cpu { | |||
| 47 | /* Background timer active */ | 52 | /* Background timer active */ |
| 48 | bool armed; | 53 | bool armed; |
| 49 | 54 | ||
| 50 | /* Timer IRQ */ | ||
| 51 | struct kvm_irq_level irq; | ||
| 52 | |||
| 53 | /* Active IRQ state caching */ | ||
| 54 | bool active_cleared_last; | ||
| 55 | |||
| 56 | /* Is the timer enabled */ | 55 | /* Is the timer enabled */ |
| 57 | bool enabled; | 56 | bool enabled; |
| 58 | }; | 57 | }; |
| @@ -77,4 +76,6 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu); | |||
| 77 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); | 76 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); |
| 78 | 77 | ||
| 79 | void kvm_timer_init_vhe(void); | 78 | void kvm_timer_init_vhe(void); |
| 79 | |||
| 80 | #define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer) | ||
| 80 | #endif | 81 | #endif |
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 91ecf48f7fe2..d3556b3ca694 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
| @@ -37,7 +37,7 @@ static u32 host_vtimer_irq_flags; | |||
| 37 | 37 | ||
| 38 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) | 38 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) |
| 39 | { | 39 | { |
| 40 | vcpu->arch.timer_cpu.active_cleared_last = false; | 40 | vcpu_vtimer(vcpu)->active_cleared_last = false; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static u64 kvm_phys_timer_read(void) | 43 | static u64 kvm_phys_timer_read(void) |
| @@ -102,7 +102,7 @@ static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu) | |||
| 102 | { | 102 | { |
| 103 | u64 cval, now; | 103 | u64 cval, now; |
| 104 | 104 | ||
| 105 | cval = vcpu->arch.timer_cpu.cntv_cval; | 105 | cval = vcpu_vtimer(vcpu)->cnt_cval; |
| 106 | now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; | 106 | now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; |
| 107 | 107 | ||
| 108 | if (now < cval) { | 108 | if (now < cval) { |
| @@ -144,21 +144,21 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt) | |||
| 144 | 144 | ||
| 145 | static bool kvm_timer_irq_can_fire(struct kvm_vcpu *vcpu) | 145 | static bool kvm_timer_irq_can_fire(struct kvm_vcpu *vcpu) |
| 146 | { | 146 | { |
| 147 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 147 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 148 | 148 | ||
| 149 | return !(timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) && | 149 | return !(vtimer->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) && |
| 150 | (timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE); | 150 | (vtimer->cnt_ctl & ARCH_TIMER_CTRL_ENABLE); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | bool kvm_timer_should_fire(struct kvm_vcpu *vcpu) | 153 | bool kvm_timer_should_fire(struct kvm_vcpu *vcpu) |
| 154 | { | 154 | { |
| 155 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 155 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 156 | u64 cval, now; | 156 | u64 cval, now; |
| 157 | 157 | ||
| 158 | if (!kvm_timer_irq_can_fire(vcpu)) | 158 | if (!kvm_timer_irq_can_fire(vcpu)) |
| 159 | return false; | 159 | return false; |
| 160 | 160 | ||
| 161 | cval = timer->cntv_cval; | 161 | cval = vtimer->cnt_cval; |
| 162 | now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; | 162 | now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; |
| 163 | 163 | ||
| 164 | return cval <= now; | 164 | return cval <= now; |
| @@ -167,18 +167,18 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu) | |||
| 167 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level) | 167 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level) |
| 168 | { | 168 | { |
| 169 | int ret; | 169 | int ret; |
| 170 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 170 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 171 | 171 | ||
| 172 | BUG_ON(!vgic_initialized(vcpu->kvm)); | 172 | BUG_ON(!vgic_initialized(vcpu->kvm)); |
| 173 | 173 | ||
| 174 | timer->active_cleared_last = false; | 174 | vtimer->active_cleared_last = false; |
| 175 | timer->irq.level = new_level; | 175 | vtimer->irq.level = new_level; |
| 176 | trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq, | 176 | trace_kvm_timer_update_irq(vcpu->vcpu_id, vtimer->irq.irq, |
| 177 | timer->irq.level); | 177 | vtimer->irq.level); |
| 178 | 178 | ||
| 179 | ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, | 179 | ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, |
| 180 | timer->irq.irq, | 180 | vtimer->irq.irq, |
| 181 | timer->irq.level); | 181 | vtimer->irq.level); |
| 182 | WARN_ON(ret); | 182 | WARN_ON(ret); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| @@ -189,18 +189,19 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level) | |||
| 189 | static int kvm_timer_update_state(struct kvm_vcpu *vcpu) | 189 | static int kvm_timer_update_state(struct kvm_vcpu *vcpu) |
| 190 | { | 190 | { |
| 191 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 191 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
| 192 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
| 192 | 193 | ||
| 193 | /* | 194 | /* |
| 194 | * If userspace modified the timer registers via SET_ONE_REG before | 195 | * If userspace modified the timer registers via SET_ONE_REG before |
| 195 | * the vgic was initialized, we mustn't set the timer->irq.level value | 196 | * the vgic was initialized, we mustn't set the vtimer->irq.level value |
| 196 | * because the guest would never see the interrupt. Instead wait | 197 | * because the guest would never see the interrupt. Instead wait |
| 197 | * until we call this function from kvm_timer_flush_hwstate. | 198 | * until we call this function from kvm_timer_flush_hwstate. |
| 198 | */ | 199 | */ |
| 199 | if (!vgic_initialized(vcpu->kvm) || !timer->enabled) | 200 | if (!vgic_initialized(vcpu->kvm) || !timer->enabled) |
| 200 | return -ENODEV; | 201 | return -ENODEV; |
| 201 | 202 | ||
| 202 | if (kvm_timer_should_fire(vcpu) != timer->irq.level) | 203 | if (kvm_timer_should_fire(vcpu) != vtimer->irq.level) |
| 203 | kvm_timer_update_irq(vcpu, !timer->irq.level); | 204 | kvm_timer_update_irq(vcpu, !vtimer->irq.level); |
| 204 | 205 | ||
| 205 | return 0; | 206 | return 0; |
| 206 | } | 207 | } |
| @@ -250,7 +251,7 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu) | |||
| 250 | */ | 251 | */ |
| 251 | void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | 252 | void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) |
| 252 | { | 253 | { |
| 253 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 254 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 254 | bool phys_active; | 255 | bool phys_active; |
| 255 | int ret; | 256 | int ret; |
| 256 | 257 | ||
| @@ -274,8 +275,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | |||
| 274 | * to ensure that hardware interrupts from the timer triggers a guest | 275 | * to ensure that hardware interrupts from the timer triggers a guest |
| 275 | * exit. | 276 | * exit. |
| 276 | */ | 277 | */ |
| 277 | phys_active = timer->irq.level || | 278 | phys_active = vtimer->irq.level || |
| 278 | kvm_vgic_map_is_active(vcpu, timer->irq.irq); | 279 | kvm_vgic_map_is_active(vcpu, vtimer->irq.irq); |
| 279 | 280 | ||
| 280 | /* | 281 | /* |
| 281 | * We want to avoid hitting the (re)distributor as much as | 282 | * We want to avoid hitting the (re)distributor as much as |
| @@ -297,7 +298,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | |||
| 297 | * - cached value is "active clear" | 298 | * - cached value is "active clear" |
| 298 | * - value to be programmed is "active clear" | 299 | * - value to be programmed is "active clear" |
| 299 | */ | 300 | */ |
| 300 | if (timer->active_cleared_last && !phys_active) | 301 | if (vtimer->active_cleared_last && !phys_active) |
| 301 | return; | 302 | return; |
| 302 | 303 | ||
| 303 | ret = irq_set_irqchip_state(host_vtimer_irq, | 304 | ret = irq_set_irqchip_state(host_vtimer_irq, |
| @@ -305,7 +306,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) | |||
| 305 | phys_active); | 306 | phys_active); |
| 306 | WARN_ON(ret); | 307 | WARN_ON(ret); |
| 307 | 308 | ||
| 308 | timer->active_cleared_last = !phys_active; | 309 | vtimer->active_cleared_last = !phys_active; |
| 309 | } | 310 | } |
| 310 | 311 | ||
| 311 | /** | 312 | /** |
| @@ -331,7 +332,7 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) | |||
| 331 | int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | 332 | int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, |
| 332 | const struct kvm_irq_level *irq) | 333 | const struct kvm_irq_level *irq) |
| 333 | { | 334 | { |
| 334 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 335 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 335 | 336 | ||
| 336 | /* | 337 | /* |
| 337 | * The vcpu timer irq number cannot be determined in | 338 | * The vcpu timer irq number cannot be determined in |
| @@ -339,7 +340,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | |||
| 339 | * kvm_vcpu_set_target(). To handle this, we determine | 340 | * kvm_vcpu_set_target(). To handle this, we determine |
| 340 | * vcpu timer irq number when the vcpu is reset. | 341 | * vcpu timer irq number when the vcpu is reset. |
| 341 | */ | 342 | */ |
| 342 | timer->irq.irq = irq->irq; | 343 | vtimer->irq.irq = irq->irq; |
| 343 | 344 | ||
| 344 | /* | 345 | /* |
| 345 | * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8 | 346 | * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8 |
| @@ -347,7 +348,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | |||
| 347 | * resets the timer to be disabled and unmasked and is compliant with | 348 | * resets the timer to be disabled and unmasked and is compliant with |
| 348 | * the ARMv7 architecture. | 349 | * the ARMv7 architecture. |
| 349 | */ | 350 | */ |
| 350 | timer->cntv_ctl = 0; | 351 | vtimer->cnt_ctl = 0; |
| 351 | kvm_timer_update_state(vcpu); | 352 | kvm_timer_update_state(vcpu); |
| 352 | 353 | ||
| 353 | return 0; | 354 | return 0; |
| @@ -369,17 +370,17 @@ static void kvm_timer_init_interrupt(void *info) | |||
| 369 | 370 | ||
| 370 | int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) | 371 | int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) |
| 371 | { | 372 | { |
| 372 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 373 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 373 | 374 | ||
| 374 | switch (regid) { | 375 | switch (regid) { |
| 375 | case KVM_REG_ARM_TIMER_CTL: | 376 | case KVM_REG_ARM_TIMER_CTL: |
| 376 | timer->cntv_ctl = value; | 377 | vtimer->cnt_ctl = value; |
| 377 | break; | 378 | break; |
| 378 | case KVM_REG_ARM_TIMER_CNT: | 379 | case KVM_REG_ARM_TIMER_CNT: |
| 379 | vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value; | 380 | vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value; |
| 380 | break; | 381 | break; |
| 381 | case KVM_REG_ARM_TIMER_CVAL: | 382 | case KVM_REG_ARM_TIMER_CVAL: |
| 382 | timer->cntv_cval = value; | 383 | vtimer->cnt_cval = value; |
| 383 | break; | 384 | break; |
| 384 | default: | 385 | default: |
| 385 | return -1; | 386 | return -1; |
| @@ -391,15 +392,15 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) | |||
| 391 | 392 | ||
| 392 | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) | 393 | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) |
| 393 | { | 394 | { |
| 394 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 395 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
| 395 | 396 | ||
| 396 | switch (regid) { | 397 | switch (regid) { |
| 397 | case KVM_REG_ARM_TIMER_CTL: | 398 | case KVM_REG_ARM_TIMER_CTL: |
| 398 | return timer->cntv_ctl; | 399 | return vtimer->cnt_ctl; |
| 399 | case KVM_REG_ARM_TIMER_CNT: | 400 | case KVM_REG_ARM_TIMER_CNT: |
| 400 | return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; | 401 | return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; |
| 401 | case KVM_REG_ARM_TIMER_CVAL: | 402 | case KVM_REG_ARM_TIMER_CVAL: |
| 402 | return timer->cntv_cval; | 403 | return vtimer->cnt_cval; |
| 403 | } | 404 | } |
| 404 | return (u64)-1; | 405 | return (u64)-1; |
| 405 | } | 406 | } |
| @@ -463,14 +464,16 @@ int kvm_timer_hyp_init(void) | |||
| 463 | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) | 464 | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) |
| 464 | { | 465 | { |
| 465 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 466 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
| 467 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
| 466 | 468 | ||
| 467 | timer_disarm(timer); | 469 | timer_disarm(timer); |
| 468 | kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq); | 470 | kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq); |
| 469 | } | 471 | } |
| 470 | 472 | ||
| 471 | int kvm_timer_enable(struct kvm_vcpu *vcpu) | 473 | int kvm_timer_enable(struct kvm_vcpu *vcpu) |
| 472 | { | 474 | { |
| 473 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 475 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
| 476 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
| 474 | struct irq_desc *desc; | 477 | struct irq_desc *desc; |
| 475 | struct irq_data *data; | 478 | struct irq_data *data; |
| 476 | int phys_irq; | 479 | int phys_irq; |
| @@ -498,7 +501,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) | |||
| 498 | * Tell the VGIC that the virtual interrupt is tied to a | 501 | * Tell the VGIC that the virtual interrupt is tied to a |
| 499 | * physical interrupt. We do that once per VCPU. | 502 | * physical interrupt. We do that once per VCPU. |
| 500 | */ | 503 | */ |
| 501 | ret = kvm_vgic_map_phys_irq(vcpu, timer->irq.irq, phys_irq); | 504 | ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq); |
| 502 | if (ret) | 505 | if (ret) |
| 503 | return ret; | 506 | return ret; |
| 504 | 507 | ||
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c index 63e28dd18bb0..0cf08953e81c 100644 --- a/virt/kvm/arm/hyp/timer-sr.c +++ b/virt/kvm/arm/hyp/timer-sr.c | |||
| @@ -25,11 +25,12 @@ | |||
| 25 | void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) | 25 | void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) |
| 26 | { | 26 | { |
| 27 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 27 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
| 28 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
| 28 | u64 val; | 29 | u64 val; |
| 29 | 30 | ||
| 30 | if (timer->enabled) { | 31 | if (timer->enabled) { |
| 31 | timer->cntv_ctl = read_sysreg_el0(cntv_ctl); | 32 | vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl); |
| 32 | timer->cntv_cval = read_sysreg_el0(cntv_cval); | 33 | vtimer->cnt_cval = read_sysreg_el0(cntv_cval); |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | /* Disable the virtual timer */ | 36 | /* Disable the virtual timer */ |
| @@ -54,6 +55,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) | |||
| 54 | { | 55 | { |
| 55 | struct kvm *kvm = kern_hyp_va(vcpu->kvm); | 56 | struct kvm *kvm = kern_hyp_va(vcpu->kvm); |
| 56 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 57 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
| 58 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
| 57 | u64 val; | 59 | u64 val; |
| 58 | 60 | ||
| 59 | /* Those bits are already configured at boot on VHE-system */ | 61 | /* Those bits are already configured at boot on VHE-system */ |
| @@ -70,8 +72,8 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) | |||
| 70 | 72 | ||
| 71 | if (timer->enabled) { | 73 | if (timer->enabled) { |
| 72 | write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); | 74 | write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); |
| 73 | write_sysreg_el0(timer->cntv_cval, cntv_cval); | 75 | write_sysreg_el0(vtimer->cnt_cval, cntv_cval); |
| 74 | isb(); | 76 | isb(); |
| 75 | write_sysreg_el0(timer->cntv_ctl, cntv_ctl); | 77 | write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl); |
| 76 | } | 78 | } |
| 77 | } | 79 | } |
