summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorJintack Lim <jintack@cs.columbia.edu>2017-02-03 10:20:00 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2017-02-08 10:13:33 -0500
commit90de943a430028ee389b22bf4a7ae5867c32ce0c (patch)
tree80c64f76f1be349523dd346933858ed9c730fb1f /virt
parentfbb4aeec5fc2ab47615b2a0cbabc503e1eef4c60 (diff)
KVM: arm/arm64: Move cntvoff to each timer context
Make cntvoff per each timer context. This is helpful to abstract kvm timer functions to work with timer context without considering timer types (e.g. physical timer or virtual timer). This also would pave the way for ever doing adjustments of the cntvoff on a per-CPU basis if that should ever make sense. Signed-off-by: Jintack Lim <jintack@cs.columbia.edu> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/arch_timer.c38
-rw-r--r--virt/kvm/arm/hyp/timer-sr.c3
2 files changed, 29 insertions, 12 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index d3556b3ca694..5004a679b125 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -101,9 +101,10 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
101static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu) 101static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu)
102{ 102{
103 u64 cval, now; 103 u64 cval, now;
104 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
104 105
105 cval = vcpu_vtimer(vcpu)->cnt_cval; 106 cval = vtimer->cnt_cval;
106 now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; 107 now = kvm_phys_timer_read() - vtimer->cntvoff;
107 108
108 if (now < cval) { 109 if (now < cval) {
109 u64 ns; 110 u64 ns;
@@ -159,7 +160,7 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
159 return false; 160 return false;
160 161
161 cval = vtimer->cnt_cval; 162 cval = vtimer->cnt_cval;
162 now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; 163 now = kvm_phys_timer_read() - vtimer->cntvoff;
163 164
164 return cval <= now; 165 return cval <= now;
165} 166}
@@ -354,10 +355,32 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
354 return 0; 355 return 0;
355} 356}
356 357
358/* Make the updates of cntvoff for all vtimer contexts atomic */
359static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
360{
361 int i;
362 struct kvm *kvm = vcpu->kvm;
363 struct kvm_vcpu *tmp;
364
365 mutex_lock(&kvm->lock);
366 kvm_for_each_vcpu(i, tmp, kvm)
367 vcpu_vtimer(tmp)->cntvoff = cntvoff;
368
369 /*
370 * When called from the vcpu create path, the CPU being created is not
371 * included in the loop above, so we just set it here as well.
372 */
373 vcpu_vtimer(vcpu)->cntvoff = cntvoff;
374 mutex_unlock(&kvm->lock);
375}
376
357void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) 377void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
358{ 378{
359 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 379 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
360 380
381 /* Synchronize cntvoff across all vtimers of a VM. */
382 update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
383
361 INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); 384 INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
362 hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 385 hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
363 timer->timer.function = kvm_timer_expire; 386 timer->timer.function = kvm_timer_expire;
@@ -377,7 +400,7 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
377 vtimer->cnt_ctl = value; 400 vtimer->cnt_ctl = value;
378 break; 401 break;
379 case KVM_REG_ARM_TIMER_CNT: 402 case KVM_REG_ARM_TIMER_CNT:
380 vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value; 403 update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
381 break; 404 break;
382 case KVM_REG_ARM_TIMER_CVAL: 405 case KVM_REG_ARM_TIMER_CVAL:
383 vtimer->cnt_cval = value; 406 vtimer->cnt_cval = value;
@@ -398,7 +421,7 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
398 case KVM_REG_ARM_TIMER_CTL: 421 case KVM_REG_ARM_TIMER_CTL:
399 return vtimer->cnt_ctl; 422 return vtimer->cnt_ctl;
400 case KVM_REG_ARM_TIMER_CNT: 423 case KVM_REG_ARM_TIMER_CNT:
401 return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; 424 return kvm_phys_timer_read() - vtimer->cntvoff;
402 case KVM_REG_ARM_TIMER_CVAL: 425 case KVM_REG_ARM_TIMER_CVAL:
403 return vtimer->cnt_cval; 426 return vtimer->cnt_cval;
404 } 427 }
@@ -510,11 +533,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
510 return 0; 533 return 0;
511} 534}
512 535
513void kvm_timer_init(struct kvm *kvm)
514{
515 kvm->arch.timer.cntvoff = kvm_phys_timer_read();
516}
517
518/* 536/*
519 * On VHE system, we only need to configure trap on physical timer and counter 537 * On VHE system, we only need to configure trap on physical timer and counter
520 * accesses in EL0 and EL1 once, not for every world switch. 538 * accesses in EL0 and EL1 once, not for every world switch.
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index 0cf08953e81c..4734915ab71f 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -53,7 +53,6 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
53 53
54void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) 54void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
55{ 55{
56 struct kvm *kvm = kern_hyp_va(vcpu->kvm);
57 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 56 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
58 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); 57 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
59 u64 val; 58 u64 val;
@@ -71,7 +70,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
71 } 70 }
72 71
73 if (timer->enabled) { 72 if (timer->enabled) {
74 write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); 73 write_sysreg(vtimer->cntvoff, cntvoff_el2);
75 write_sysreg_el0(vtimer->cnt_cval, cntv_cval); 74 write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
76 isb(); 75 isb();
77 write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl); 76 write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);