Message ID | 20190425125740.238036-1-andre.przywara@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: arm/arm64: Don't emulate virtual timers on userspace ioctls | expand |
On Thu, 25 Apr 2019 13:57:40 +0100, Andre Przywara <andre.przywara@arm.com> wrote: > > From: Christoffer Dall <christoffer.dall@arm.com> > > 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. > > 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> Fixes: bee038a674875 ("KVM: arm/arm64: Rework the timer code to use a timer_map") Applied to -master. Thanks, M.
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 3417f2dbc366..3538bc39a87a 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -507,6 +507,14 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu) { struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); + /* + * Update the timer output so that it is likely to match the + * state we're about to restore. If the timer expires between + * this point and the register restoration, we'll take the + * interrupt anyway. + */ + kvm_timer_update_irq(vcpu, kvm_timer_should_fire(vtimer), vtimer); + /* * When using a userspace irqchip with the architected timers and a * host interrupt controller that doesn't support an active state, we @@ -730,7 +738,6 @@ static void kvm_timer_init_interrupt(void *info) int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) { struct arch_timer_context *timer; - bool level; switch (regid) { case KVM_REG_ARM_TIMER_CTL: @@ -758,10 +765,6 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) return -1; } - level = kvm_timer_should_fire(timer); - kvm_timer_update_irq(vcpu, level, timer); - timer_emulate(timer); - return 0; }