[PATCH kvm-unit-tests] svm: add a test for exception injection

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

 



Cover VMRUN's testing whether EVENTINJ.TYPE = 3 (exception) has been specified with
a vector that does not correspond to an exception.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 x86/svm.h       |  7 +++++
 x86/svm_tests.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/x86/svm.h b/x86/svm.h
index 645deb7..bb5c552 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -324,6 +324,13 @@ struct __attribute__ ((__packed__)) vmcb {
 
 #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
 
+#define SVM_EVENT_INJ_HWINT	(0 << 8)
+#define SVM_EVENT_INJ_NMI	(2 << 8)
+#define SVM_EVENT_INJ_EXC	(3 << 8)
+#define SVM_EVENT_INJ_SWINT	(4 << 8)
+#define SVM_EVENT_INJ_ERRCODE	(1 << 11)
+#define SVM_EVENT_INJ_VALID	(1 << 31)
+
 #define MSR_BITMAP_SIZE 8192
 
 struct svm_test {
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 16b9dfd..6292e68 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1340,6 +1340,73 @@ static bool interrupt_check(struct svm_test *test)
     return get_test_stage(test) == 5;
 }
 
+static volatile int count_exc = 0;
+
+static void my_isr(struct ex_regs *r)
+{
+        count_exc++;
+}
+
+static void exc_inject_prepare(struct svm_test *test)
+{
+	handle_exception(DE_VECTOR, my_isr);
+	handle_exception(NMI_VECTOR, my_isr);
+}
+
+
+static void exc_inject_test(struct svm_test *test)
+{
+    asm volatile ("vmmcall\n\tvmmcall\n\t");
+}
+
+static bool exc_inject_finished(struct svm_test *test)
+{
+    vmcb->save.rip += 3;
+
+    switch (get_test_stage(test)) {
+    case 0:
+        if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+            report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x",
+                   vmcb->control.exit_code);
+            return true;
+        }
+        vmcb->control.event_inj = NMI_VECTOR | SVM_EVENT_INJ_EXC | SVM_EVENT_INJ_VALID;
+        break;
+
+    case 1:
+        if (vmcb->control.exit_code != SVM_EXIT_ERR) {
+            report(false, "VMEXIT not due to error. Exit reason 0x%x",
+                   vmcb->control.exit_code);
+            return true;
+        }
+        report(count_exc == 0, "exception with vector 2 not injected");
+        vmcb->control.event_inj = DE_VECTOR | SVM_EVENT_INJ_EXC | SVM_EVENT_INJ_VALID;
+	break;
+
+    case 2:
+        if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+            report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x",
+                   vmcb->control.exit_code);
+            return true;
+        }
+        report(count_exc == 1, "divide overflow exception injected");
+	report(!(vmcb->control.event_inj & SVM_EVENT_INJ_VALID), "eventinj.VALID cleared");
+        break;
+
+    default:
+        return true;
+    }
+
+    inc_test_stage(test);
+
+    return get_test_stage(test) == 3;
+}
+
+static bool exc_inject_check(struct svm_test *test)
+{
+    return count_exc == 1 && get_test_stage(test) == 3;
+}
+
 #define TEST(name) { #name, .v2 = name }
 
 /*
@@ -1446,6 +1513,9 @@ struct svm_test svm_tests[] = {
     { "interrupt", default_supported, interrupt_prepare,
       default_prepare_gif_clear, interrupt_test,
       interrupt_finished, interrupt_check },
+    { "exc_inject", default_supported, exc_inject_prepare,
+      default_prepare_gif_clear, exc_inject_test,
+      exc_inject_finished, exc_inject_check },
     TEST(svm_guest_state_test),
     { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
-- 
2.18.2




[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