* [PATCH v3 0/2] kvm: arm/arm64: Fix emulated physical timer IRQ injection
@ 2018-07-25 9:21 Andre Przywara
2018-07-25 9:21 ` [PATCH v3 1/2] KVM: arm/arm64: Fix potential loss of ptimer interrupts Andre Przywara
2018-07-25 9:21 ` [PATCH v3 2/2] KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when blocked Andre Przywara
0 siblings, 2 replies; 3+ messages in thread
From: Andre Przywara @ 2018-07-25 9:21 UTC (permalink / raw)
To: Marc Zyngier, Christoffer Dall; +Cc: kvmarm, linux-arm-kernel
Hi,
those two patches fix the (physical EL1) arch timer emulation in KVM,
which missed to inject the timer IRQ if the vCPU was asleep when the
timer expired. This can be checked by a new kvm-unit-tests test [1].
I am now taking Christoffer's approach, which keeps phys_timer_emulate()
mostly as it is, and adds the explicit IRQ injection check in the caller.
This turned out to fit better into the upcoming arch timer rework.
Cheers,
Andre.
[1] https://lists.cs.columbia.edu/pipermail/kvmarm/2018-July/032220.html
Christoffer Dall (2):
KVM: arm/arm64: Fix potential loss of ptimer interrupts
KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when
blocked
virt/kvm/arm/arch_timer.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--
2.14.4
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v3 1/2] KVM: arm/arm64: Fix potential loss of ptimer interrupts
2018-07-25 9:21 [PATCH v3 0/2] kvm: arm/arm64: Fix emulated physical timer IRQ injection Andre Przywara
@ 2018-07-25 9:21 ` Andre Przywara
2018-07-25 9:21 ` [PATCH v3 2/2] KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when blocked Andre Przywara
1 sibling, 0 replies; 3+ messages in thread
From: Andre Przywara @ 2018-07-25 9:21 UTC (permalink / raw)
To: Marc Zyngier, Christoffer Dall; +Cc: kvmarm, linux-arm-kernel, Stable
From: Christoffer Dall <christoffer.dall@arm.com>
kvm_timer_update_state() is called when changing the phys timer
configuration registers, either via vcpu reset, as a result of a trap
from the guest, or when userspace programs the registers.
phys_timer_emulate() is in turn called by kvm_timer_update_state() to
either cancel an existing software timer, or program a new software
timer, to emulate the behavior of a real phys timer, based on the change
in configuration registers.
Unfortunately, the interaction between these two functions left a small
race; if the conceptual emulated phys timer should actually fire, but
the soft timer hasn't executed its callback yet, we cancel the timer in
phys_timer_emulate without injecting an irq. This only happens if the
check in kvm_timer_update_state is called before the timer should fire,
which is relatively unlikely, but possible.
The solution is to update the state of the phys timer after calling
phys_timer_emulate, which will pick up the pending timer state and
update the interrupt value.
Note that this leaves the opportunity of raising the interrupt twice,
once in the just-programmed soft timer, and once in
kvm_timer_update_state. Since this always happens synchronously with
the VCPU execution, there is no harm in this, and the guest ever only
sees a single timer interrupt.
Cc: Stable <stable@vger.kernel.org> # 4.15+
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
---
virt/kvm/arm/arch_timer.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index bd3d57f40f1b..18ff6203079d 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -295,9 +295,9 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu)
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
/*
- * If the timer can fire now we have just raised the IRQ line and we
- * don't need to have a soft timer scheduled for the future. If the
- * timer cannot fire at all, then we also don't need a soft timer.
+ * If the timer can fire now, we don't need to have a soft timer
+ * scheduled for the future. If the timer cannot fire at all,
+ * then we also don't need a soft timer.
*/
if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
soft_timer_cancel(&timer->phys_timer, NULL);
@@ -332,10 +332,10 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
level = kvm_timer_should_fire(vtimer);
kvm_timer_update_irq(vcpu, level, vtimer);
+ phys_timer_emulate(vcpu);
+
if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
-
- phys_timer_emulate(vcpu);
}
static void vtimer_save_state(struct kvm_vcpu *vcpu)
--
2.14.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v3 2/2] KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when blocked
2018-07-25 9:21 [PATCH v3 0/2] kvm: arm/arm64: Fix emulated physical timer IRQ injection Andre Przywara
2018-07-25 9:21 ` [PATCH v3 1/2] KVM: arm/arm64: Fix potential loss of ptimer interrupts Andre Przywara
@ 2018-07-25 9:21 ` Andre Przywara
1 sibling, 0 replies; 3+ messages in thread
From: Andre Przywara @ 2018-07-25 9:21 UTC (permalink / raw)
To: Marc Zyngier, Christoffer Dall; +Cc: kvmarm, linux-arm-kernel, Stable
From: Christoffer Dall <christoffer.dall@arm.com>
When the VCPU is blocked (for example from WFI) we don't inject the
physical timer interrupt if it should fire while the CPU is blocked, but
instead we just wake up the VCPU and expect kvm_timer_vcpu_load to take
care of injecting the interrupt.
Unfortunately, kvm_timer_vcpu_load() doesn't actually do that, it only
has support to schedule a soft timer if the emulated phys timer is
expected to fire in the future.
Follow the same pattern as kvm_timer_update_state() and update the irq
state after potentially scheduling a soft timer.
Reported-by: Andre Przywara <andre.przywara@arm.com>
Cc: Stable <stable@vger.kernel.org> # 4.15+
Fixes: bbdd52cfcba29 ("KVM: arm/arm64: Avoid phys timer emulation in vcpu entry/exit")
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
---
virt/kvm/arm/arch_timer.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 18ff6203079d..17cecc96f735 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -487,6 +487,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
{
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
if (unlikely(!timer->enabled))
return;
@@ -502,6 +503,10 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
/* Set the background timer for the physical timer emulation. */
phys_timer_emulate(vcpu);
+
+ /* If the timer fired while we weren't running, inject it now */
+ if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
+ kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
}
bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
--
2.14.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-07-25 9:21 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-25 9:21 [PATCH v3 0/2] kvm: arm/arm64: Fix emulated physical timer IRQ injection Andre Przywara
2018-07-25 9:21 ` [PATCH v3 1/2] KVM: arm/arm64: Fix potential loss of ptimer interrupts Andre Przywara
2018-07-25 9:21 ` [PATCH v3 2/2] KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when blocked Andre Przywara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox