[kvm-unit-tests PATCH] nSVM: Added test for VGIF feature

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

 



When VGIF is enabled STGI executed in guest mode
sets bit 9, while CLGI clears bit 9 in the int_ctl (offset 60h)
of the VMCB.

Signed-off-by: Lara Lazier <laramglazier@xxxxxxxxx>
---
 lib/x86/processor.h |  1 +
 x86/svm.c           |  5 ++++
 x86/svm.h           |  7 +++++
 x86/svm_tests.c     | 70 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+)

diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 173520f..f4d1757 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -187,6 +187,7 @@ static inline bool is_intel(void)
 #define	X86_FEATURE_AMD_IBPB		(CPUID(0x80000008, 0, EBX, 12))
 #define	X86_FEATURE_NPT			(CPUID(0x8000000A, 0, EDX, 0))
 #define	X86_FEATURE_NRIPS		(CPUID(0x8000000A, 0, EDX, 3))
+#define	X86_FEATURE_VGIF		(CPUID(0x8000000A, 0, EDX, 16))
 
 
 static inline bool this_cpu_has(u64 feature)
diff --git a/x86/svm.c b/x86/svm.c
index 4eaa97e..b0096a9 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -65,6 +65,11 @@ bool default_supported(void)
     return true;
 }
 
+bool vgif_supported(void)
+{
+	return this_cpu_has(X86_FEATURE_VGIF);
+}
+
 void default_prepare(struct svm_test *test)
 {
 	vmcb_ident(vmcb);
diff --git a/x86/svm.h b/x86/svm.h
index 995b0f8..339b9f7 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -115,6 +115,12 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define V_IRQ_SHIFT 8
 #define V_IRQ_MASK (1 << V_IRQ_SHIFT)
 
+#define V_GIF_ENABLED_SHIFT 25
+#define V_GIF_ENABLED_MASK (1 << V_GIF_ENABLED_SHIFT)
+
+#define V_GIF_SHIFT 9
+#define V_GIF_MASK (1 << V_GIF_SHIFT)
+
 #define V_INTR_PRIO_SHIFT 16
 #define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
 
@@ -398,6 +404,7 @@ u64 *npt_get_pdpe(void);
 u64 *npt_get_pml4e(void);
 bool smp_supported(void);
 bool default_supported(void);
+bool vgif_supported(void);
 void default_prepare(struct svm_test *test);
 void default_prepare_gif_clear(struct svm_test *test);
 bool default_finished(struct svm_test *test);
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 3777208..7c7b19d 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -2772,6 +2772,73 @@ static void svm_vmload_vmsave(void)
 	vmcb->control.intercept = intercept_saved;
 }
 
+static void prepare_vgif_enabled(struct svm_test *test)
+{
+    default_prepare(test);
+}
+
+static void test_vgif(struct svm_test *test)
+{
+    asm volatile ("vmmcall\n\tstgi\n\tvmmcall\n\tclgi\n\tvmmcall\n\t");
+
+}
+
+static bool vgif_finished(struct svm_test *test)
+{
+    switch (get_test_stage(test))
+    {
+    case 0:
+        if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+            report(false, "VMEXIT not due to vmmcall.");
+            return true;
+        }
+        vmcb->control.int_ctl |= V_GIF_ENABLED_MASK;
+        vmcb->save.rip += 3;
+        inc_test_stage(test);
+        break;
+    case 1:
+        if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+            report(false, "VMEXIT not due to vmmcall.");
+            return true;
+        }
+        if (!(vmcb->control.int_ctl & V_GIF_MASK)) {
+            report(false, "Failed to set VGIF when executing STGI.");
+            vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+            return true;
+        }
+        report(true, "STGI set VGIF bit.");
+        vmcb->save.rip += 3;
+        inc_test_stage(test);
+        break;
+    case 2:
+        if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+            report(false, "VMEXIT not due to vmmcall.");
+            return true;
+        }
+        if (vmcb->control.int_ctl & V_GIF_MASK) {
+            report(false, "Failed to clear VGIF when executing CLGI.");
+            vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+            return true;
+        }
+        report(true, "CLGI cleared VGIF bit.");
+        vmcb->save.rip += 3;
+        inc_test_stage(test);
+        vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK;
+        break;
+    default:
+        return true;
+        break;
+    }
+
+    return get_test_stage(test) == 3;
+}
+
+static bool vgif_check(struct svm_test *test)
+{
+    return get_test_stage(test) == 3;
+}
+
+
 struct svm_test svm_tests[] = {
     { "null", default_supported, default_prepare,
       default_prepare_gif_clear, null_test,
@@ -2882,6 +2949,9 @@ struct svm_test svm_tests[] = {
     { "host_rflags", default_supported, host_rflags_prepare,
       host_rflags_prepare_gif_clear, host_rflags_test,
       host_rflags_finished, host_rflags_check },
+    { "vgif", vgif_supported, prepare_vgif_enabled,
+      default_prepare_gif_clear, test_vgif, vgif_finished,
+      vgif_check },
     TEST(svm_cr4_osxsave_test),
     TEST(svm_guest_state_test),
     TEST(svm_npt_rsvd_bits_test),
-- 
2.25.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