[PATCH kvm-unit-tests 1/2] svm: introduce prepare_gif_clear callback

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

 



Generalize the set_host_if flag that was added recently, by introducing
a new callback that is called with GIF=0 && IF=1.  This is useful to
inject events that will trigger right after VMRUN.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 x86/svm.c | 124 ++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 81 insertions(+), 43 deletions(-)

diff --git a/x86/svm.c b/x86/svm.c
index 99b1d71..63fda65 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -192,6 +192,7 @@ struct test {
     const char *name;
     bool (*supported)(void);
     void (*prepare)(struct test *test);
+    void (*prepare_gif_clear)(struct test *test);
     void (*guest_func)(struct test *test);
     bool (*finished)(struct test *test);
     bool (*succeeded)(struct test *test);
@@ -266,31 +267,37 @@ static void test_run(struct test *test, struct vmcb *vmcb)
     vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
     regs.rdi = (ulong)test;
     do {
+        struct test *the_test = test;
+        u64 the_vmcb = vmcb_phys;
         tsc_start = rdtsc();
         asm volatile (
             "clgi;\n\t" // semi-colon needed for LLVM compatibility
-            "cmpb $0, set_host_if\n\t"
-            "jz 1f\n\t"
             "sti \n\t"
-            "1: \n\t"
+            "call *%c[PREPARE_GIF_CLEAR](%[test]) \n \t"
+            "mov %[vmcb_phys], %%rax \n\t"
             "vmload \n\t"
             "vmload %0\n\t"
             "mov regs+0x80, %%r15\n\t"  // rflags
-            "mov %%r15, 0x170(%0)\n\t"
+            "mov %%r15, 0x170(%%rax)\n\t"
             "mov regs, %%r15\n\t"       // rax
-            "mov %%r15, 0x1f8(%0)\n\t"
+            "mov %%r15, 0x1f8(%%rax)\n\t"
             LOAD_GPR_C
             "vmrun %0\n\t"
             SAVE_GPR_C
-            "mov 0x170(%0), %%r15\n\t"  // rflags
+            "mov 0x170(%%rax), %%r15\n\t"  // rflags
             "mov %%r15, regs+0x80\n\t"
-            "mov 0x1f8(%0), %%r15\n\t"  // rax
+            "mov 0x1f8(%%rax), %%r15\n\t"  // rax
             "mov %%r15, regs\n\t"
             "vmsave %0\n\t"
             "cli \n\t"
             "stgi"
-            : : "a"(vmcb_phys)
-            : "rbx", "rcx", "rdx", "rsi",
+            : // inputs clobbered by the guest:
+	      "+D" (the_test),            // first argument register
+	      "+b" (the_vmcb)             // callee save register!
+            : [test] "0" (the_test),
+	      [vmcb_phys] "1"(the_vmcb),
+	      [PREPARE_GIF_CLEAR] "i" (offsetof(struct test, prepare_gif_clear))
+            : "rax", "rcx", "rdx", "rsi",
               "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15",
               "memory");
 	tsc_end = rdtsc();
@@ -316,6 +323,12 @@ static void default_prepare(struct test *test)
     vmcb_ident(test->vmcb);
 }
 
+static void default_prepare_gif_clear(struct test *test)
+{
+    if (!set_host_if)
+        asm("cli");
+}
+
 static bool default_finished(struct test *test)
 {
     return true; /* one vmexit */
@@ -1486,58 +1499,83 @@ static bool pending_event_check_vmask(struct test *test)
 }
 
 static struct test tests[] = {
-    { "null", default_supported, default_prepare, null_test,
+    { "null", default_supported, default_prepare,
+      default_prepare_gif_clear, null_test,
       default_finished, null_check },
-    { "vmrun", default_supported, default_prepare, test_vmrun,
+    { "vmrun", default_supported, default_prepare,
+      default_prepare_gif_clear, test_vmrun,
        default_finished, check_vmrun },
-    { "ioio", default_supported, prepare_ioio, test_ioio,
+    { "ioio", default_supported, prepare_ioio,
+       default_prepare_gif_clear, test_ioio,
        ioio_finished, check_ioio },
     { "vmrun intercept check", default_supported, prepare_no_vmrun_int,
-      null_test, default_finished, check_no_vmrun_int },
-    { "cr3 read intercept", default_supported, prepare_cr3_intercept,
+      default_prepare_gif_clear, null_test, default_finished,
+      check_no_vmrun_int },
+    { "cr3 read intercept", default_supported,
+      prepare_cr3_intercept, default_prepare_gif_clear,
       test_cr3_intercept, default_finished, check_cr3_intercept },
     { "cr3 read nointercept", default_supported, default_prepare,
-      test_cr3_intercept, default_finished, check_cr3_nointercept },
+      default_prepare_gif_clear, test_cr3_intercept, default_finished,
+      check_cr3_nointercept },
     { "cr3 read intercept emulate", smp_supported,
-      prepare_cr3_intercept_bypass, test_cr3_intercept_bypass,
-      default_finished, check_cr3_intercept },
+      prepare_cr3_intercept_bypass, default_prepare_gif_clear,
+      test_cr3_intercept_bypass, default_finished, check_cr3_intercept },
     { "dr intercept check", default_supported, prepare_dr_intercept,
-      test_dr_intercept, dr_intercept_finished, check_dr_intercept },
-    { "next_rip", next_rip_supported, prepare_next_rip, test_next_rip,
+      default_prepare_gif_clear, test_dr_intercept, dr_intercept_finished,
+      check_dr_intercept },
+    { "next_rip", next_rip_supported, prepare_next_rip,
+      default_prepare_gif_clear, test_next_rip,
       default_finished, check_next_rip },
     { "msr intercept check", default_supported, prepare_msr_intercept,
-       test_msr_intercept, msr_intercept_finished, check_msr_intercept },
-    { "mode_switch", default_supported, prepare_mode_switch, test_mode_switch,
+      default_prepare_gif_clear, test_msr_intercept,
+      msr_intercept_finished, check_msr_intercept },
+    { "mode_switch", default_supported, prepare_mode_switch,
+      default_prepare_gif_clear, test_mode_switch,
        mode_switch_finished, check_mode_switch },
-    { "asid_zero", default_supported, prepare_asid_zero, test_asid_zero,
+    { "asid_zero", default_supported, prepare_asid_zero,
+      default_prepare_gif_clear, test_asid_zero,
        default_finished, check_asid_zero },
-    { "sel_cr0_bug", default_supported, sel_cr0_bug_prepare, sel_cr0_bug_test,
+    { "sel_cr0_bug", default_supported, sel_cr0_bug_prepare,
+      default_prepare_gif_clear, sel_cr0_bug_test,
        sel_cr0_bug_finished, sel_cr0_bug_check },
-    { "npt_nx", npt_supported, npt_nx_prepare, null_test,
-	    default_finished, npt_nx_check },
-    { "npt_us", npt_supported, npt_us_prepare, npt_us_test,
-	    default_finished, npt_us_check },
-    { "npt_rsvd", npt_supported, npt_rsvd_prepare, null_test,
-	    default_finished, npt_rsvd_check },
-    { "npt_rw", npt_supported, npt_rw_prepare, npt_rw_test,
-	    default_finished, npt_rw_check },
-    { "npt_rsvd_pfwalk", npt_supported, npt_rsvd_pfwalk_prepare, null_test,
-	    default_finished, npt_rsvd_pfwalk_check },
-    { "npt_rw_pfwalk", npt_supported, npt_rw_pfwalk_prepare, null_test,
-	    default_finished, npt_rw_pfwalk_check },
-    { "npt_l1mmio", npt_supported, npt_l1mmio_prepare, npt_l1mmio_test,
-	    default_finished, npt_l1mmio_check },
-    { "npt_rw_l1mmio", npt_supported, npt_rw_l1mmio_prepare, npt_rw_l1mmio_test,
-	    default_finished, npt_rw_l1mmio_check },
-    { "tsc_adjust", default_supported, tsc_adjust_prepare, tsc_adjust_test,
-       default_finished, tsc_adjust_check },
-    { "latency_run_exit", default_supported, latency_prepare, latency_test,
+    { "npt_nx", npt_supported, npt_nx_prepare,
+      default_prepare_gif_clear, null_test,
+      default_finished, npt_nx_check },
+    { "npt_us", npt_supported, npt_us_prepare,
+      default_prepare_gif_clear, npt_us_test,
+      default_finished, npt_us_check },
+    { "npt_rsvd", npt_supported, npt_rsvd_prepare,
+      default_prepare_gif_clear, null_test,
+      default_finished, npt_rsvd_check },
+    { "npt_rw", npt_supported, npt_rw_prepare,
+      default_prepare_gif_clear, npt_rw_test,
+      default_finished, npt_rw_check },
+    { "npt_rsvd_pfwalk", npt_supported, npt_rsvd_pfwalk_prepare,
+      default_prepare_gif_clear, null_test,
+      default_finished, npt_rsvd_pfwalk_check },
+    { "npt_rw_pfwalk", npt_supported, npt_rw_pfwalk_prepare,
+      default_prepare_gif_clear, null_test,
+      default_finished, npt_rw_pfwalk_check },
+    { "npt_l1mmio", npt_supported, npt_l1mmio_prepare,
+      default_prepare_gif_clear, npt_l1mmio_test,
+      default_finished, npt_l1mmio_check },
+    { "npt_rw_l1mmio", npt_supported, npt_rw_l1mmio_prepare,
+      default_prepare_gif_clear, npt_rw_l1mmio_test,
+      default_finished, npt_rw_l1mmio_check },
+    { "tsc_adjust", default_supported, tsc_adjust_prepare,
+      default_prepare_gif_clear, tsc_adjust_test,
+      default_finished, tsc_adjust_check },
+    { "latency_run_exit", default_supported, latency_prepare,
+      default_prepare_gif_clear, latency_test,
       latency_finished, latency_check },
-    { "latency_svm_insn", default_supported, lat_svm_insn_prepare, null_test,
+    { "latency_svm_insn", default_supported, lat_svm_insn_prepare,
+      default_prepare_gif_clear, null_test,
       lat_svm_insn_finished, lat_svm_insn_check },
     { "pending_event", default_supported, pending_event_prepare,
+      default_prepare_gif_clear,
       pending_event_test, pending_event_finished, pending_event_check },
     { "pending_event_vmask", default_supported, pending_event_prepare_vmask,
+      default_prepare_gif_clear,
       pending_event_test_vmask, pending_event_finished_vmask,
       pending_event_check_vmask },
 };
-- 
1.8.3.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