[kvm-unit-tests PATCH] x86: hyperv_stimer: add test for busy message slot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a SynIC timer expires it attempts to deliver a message to the
corresponding slot, which may be busy (e.g. because the guest hasn't yet
processed the previous message).

KVM used to livelock here, endlessly retrying message delivery without
letting the guest to run and release the slot (a patch fixing that has
been posted to KVM ml).

Add a testcase for this scenario.

Signed-off-by: Roman Kagan <rkagan@xxxxxxxxxxxxx>
---
 x86/hyperv_stimer.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index 9fcb0f3..bd7f966 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -271,6 +271,35 @@ static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer)
     stimer_shutdown(timer);
 }
 
+static void stimer_test_one_shot_busy(int vcpu, struct stimer *timer)
+{
+    struct hv_message_page *msg_page = g_synic_vcpu[vcpu].msg_page;
+    struct hv_message *msg = &msg_page->sint_message[timer->sint];
+
+    msg->header.message_type = HVMSG_TIMER_EXPIRED;
+    wmb();
+
+    stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM);
+
+    do
+        rmb();
+    while (!msg->header.message_flags.msg_pending);
+
+    report("no timer fired while msg slot busy: vcpu %d",
+           !atomic_read(&timer->fire_count), vcpu);
+
+    msg->header.message_type = HVMSG_NONE;
+    wmb();
+    wrmsr(HV_X64_MSR_EOM, 0);
+
+    while (atomic_read(&timer->fire_count) < 1) {
+        pause();
+    }
+    report("timer resumed when msg slot released: vcpu %d", true, vcpu);
+
+    stimer_shutdown(timer);
+}
+
 static void stimer_test(void *ctx)
 {
     int vcpu = smp_id();
@@ -286,6 +315,7 @@ static void stimer_test(void *ctx)
     stimer_test_one_shot(vcpu, timer1);
     stimer_test_auto_enable_one_shot(vcpu, timer2);
     stimer_test_auto_enable_periodic(vcpu, timer1);
+    stimer_test_one_shot_busy(vcpu, timer1);
 
     irq_disable();
 }
-- 
2.13.3




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux