[PATCH kvm-unit-tests] svm: Verify a pending interrupt queued before entering the guest is not lost

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

 



This patch is based on Liran Aloni <liran.alon@xxxxxxxxxx>
commit fd056f5b89ac for vmx.

The test configures VMCB to intercept external-interrupts and then
queues an interrupt by disabling interrupts and issue a self-IPI.
At this point, we enter guest and we expect CPU to immediately exit
guest on external-interrupt. To complete the test, we then re-enable
interrupts, verify interrupt is dispatched and re-enter guest to verify
it completes execution.

Signed-off-by: Cathy Avery <cavery@xxxxxxxxxx>
---
 x86/svm.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/x86/svm.c b/x86/svm.c
index 4ddfaa4..6d2ab98 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -7,6 +7,8 @@
 #include "smp.h"
 #include "types.h"
 #include "alloc_page.h"
+#include "isr.h"
+#include "apic.h"
 
 #define SVM_EXIT_MAX_DR_INTERCEPT 0x3f
 
@@ -774,6 +776,13 @@ static int get_test_stage(struct test *test)
     return test->scratch;
 }
 
+static void set_test_stage(struct test *test, int s)
+{
+    barrier();
+    test->scratch = s;
+    barrier();
+}
+
 static void inc_test_stage(struct test *test)
 {
     barrier();
@@ -1292,6 +1301,88 @@ static bool lat_svm_insn_check(struct test *test)
             latclgi_min, clgi_sum / LATENCY_RUNS);
     return true;
 }
+
+bool pending_event_ipi_fired;
+bool pending_event_guest_run;
+
+static void pending_event_ipi_isr(isr_regs_t *regs)
+{
+    pending_event_ipi_fired = true;
+    eoi();
+}
+
+static void pending_event_prepare(struct test *test)
+{
+    int ipi_vector = 0xf1;
+
+    default_prepare(test);
+
+    pending_event_ipi_fired = false;
+
+    handle_irq(ipi_vector, pending_event_ipi_isr);
+
+    pending_event_guest_run = false;
+
+    test->vmcb->control.intercept |= (1ULL << INTERCEPT_INTR);
+    test->vmcb->control.int_ctl |= V_INTR_MASKING_MASK;
+
+    apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL |
+                  APIC_DM_FIXED | ipi_vector, 0);
+
+    set_test_stage(test, 0);
+}
+
+static void pending_event_test(struct test *test)
+{
+    pending_event_guest_run = true;
+}
+
+static bool pending_event_finished(struct test *test)
+{
+    switch (get_test_stage(test)) {
+    case 0:
+        if (test->vmcb->control.exit_code != SVM_EXIT_INTR) {
+            report("VMEXIT not due to pending interrupt. Exit reason 0x%x",
+            false, test->vmcb->control.exit_code);
+            return true;
+        }
+
+        test->vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR);
+        test->vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK;
+
+        if (pending_event_guest_run) {
+            report("Guest ran before host received IPI\n", false);
+            return true;
+        }
+
+        irq_enable();
+        asm volatile ("nop");
+        irq_disable();
+
+        if (!pending_event_ipi_fired) {
+            report("Pending interrupt not dispatched after IRQ enabled\n", false);
+            return true;
+        }
+        break;
+
+    case 1:
+        if (!pending_event_guest_run) {
+            report("Guest did not resume when no interrupt\n", false);
+            return true;
+        }
+        break;
+    }
+
+    inc_test_stage(test);
+
+    return get_test_stage(test) == 2;
+}
+
+static bool pending_event_check(struct test *test)
+{
+    return get_test_stage(test) == 2;
+}
+
 static struct test tests[] = {
     { "null", default_supported, default_prepare, null_test,
       default_finished, null_check },
@@ -1342,6 +1433,8 @@ static struct test tests[] = {
       latency_finished, latency_check },
     { "latency_svm_insn", default_supported, lat_svm_insn_prepare, null_test,
       lat_svm_insn_finished, lat_svm_insn_check },
+    { "pending_event", default_supported, pending_event_prepare,
+      pending_event_test, pending_event_finished, pending_event_check },
 };
 
 int main(int ac, char **av)
-- 
2.20.1





[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