aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoffer Dall <christoffer.dall@arm.com>2019-04-25 08:57:40 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2019-04-25 09:13:31 -0400
commit6bc210003dff7b789efae5bb02a0320dc24dd416 (patch)
tree0960f6a4c5f15cb7fd454ac05a9bceba5c84951a
parent2e8010bb71b39ff18aac9fb209b3c3093f4c4783 (diff)
KVM: arm/arm64: Don't emulate virtual timers on userspace ioctls
When a VCPU never runs before a guest exists, but we set timer registers up via ioctls, the associated hrtimer might never get cancelled. Since we moved vcpu_load/put into the arch-specific implementations and only have load/put for KVM_RUN, we won't ever have a scheduled hrtimer for emulating a timer when modifying the timer state via an ioctl from user space. All we need to do is make sure that we pick up the right state when we load the timer state next time userspace calls KVM_RUN again. We also do not need to worry about this interacting with the bg_timer, because if we were in WFI from the guest, and somehow ended up in a kvm_arm_timer_set_reg, it means that: 1. the VCPU thread has received a signal, 2. we have called vcpu_load when being scheduled in again, 3. we have called vcpu_put when we returned to userspace for it to issue another ioctl And therefore will not have a bg_timer programmed and the event is treated as a spurious wakeup from WFI if userspace decides to run the vcpu again even if there are not virtual interrupts. This fixes stray virtual timer interrupts triggered by an expiring hrtimer, which happens after a failed live migration, for instance. Fixes: bee038a674875 ("KVM: arm/arm64: Rework the timer code to use a timer_map") Signed-off-by: Christoffer Dall <christoffer.dall@arm.com> Reported-by: Andre Przywara <andre.przywara@arm.com> Tested-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--virt/kvm/arm/arch_timer.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index d43308dc3617..7fc272ecae16 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -508,6 +508,14 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
508 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); 508 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
509 509
510 /* 510 /*
511 * Update the timer output so that it is likely to match the
512 * state we're about to restore. If the timer expires between
513 * this point and the register restoration, we'll take the
514 * interrupt anyway.
515 */
516 kvm_timer_update_irq(vcpu, kvm_timer_should_fire(vtimer), vtimer);
517
518 /*
511 * When using a userspace irqchip with the architected timers and a 519 * When using a userspace irqchip with the architected timers and a
512 * host interrupt controller that doesn't support an active state, we 520 * host interrupt controller that doesn't support an active state, we
513 * must still prevent continuously exiting from the guest, and 521 * must still prevent continuously exiting from the guest, and
@@ -730,7 +738,6 @@ static void kvm_timer_init_interrupt(void *info)
730int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) 738int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
731{ 739{
732 struct arch_timer_context *timer; 740 struct arch_timer_context *timer;
733 bool level;
734 741
735 switch (regid) { 742 switch (regid) {
736 case KVM_REG_ARM_TIMER_CTL: 743 case KVM_REG_ARM_TIMER_CTL:
@@ -758,10 +765,6 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
758 return -1; 765 return -1;
759 } 766 }
760 767
761 level = kvm_timer_should_fire(timer);
762 kvm_timer_update_irq(vcpu, level, timer);
763 timer_emulate(timer);
764
765 return 0; 768 return 0;
766} 769}
767 770