]> xenbits.xensource.com Git - xtf.git/commitdiff
Rename the vvmx test to nested-vmx
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 12 Feb 2018 13:38:06 +0000 (13:38 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 12 Feb 2018 13:38:06 +0000 (13:38 +0000)
In preparation for introducing nested-svm as well.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
15 files changed:
docs/all-tests.dox
tests/nested-vmx/Makefile [new file with mode: 0644]
tests/nested-vmx/extra.cfg.in [new file with mode: 0644]
tests/nested-vmx/main.c [new file with mode: 0644]
tests/nested-vmx/msr.c [new file with mode: 0644]
tests/nested-vmx/test.h [new file with mode: 0644]
tests/nested-vmx/util.c [new file with mode: 0644]
tests/nested-vmx/vmxon.c [new file with mode: 0644]
tests/vvmx/Makefile [deleted file]
tests/vvmx/extra.cfg.in [deleted file]
tests/vvmx/main.c [deleted file]
tests/vvmx/msr.c [deleted file]
tests/vvmx/test.h [deleted file]
tests/vvmx/util.c [deleted file]
tests/vvmx/vmxon.c [deleted file]

index f9ea7c55fefd53f872b08303e151f3bdd3dcf4dc..78588c5a6404347249647a7c33cb9b905cfe4671 100644 (file)
@@ -122,5 +122,5 @@ guest breakout.
 
 @section index-in-development In Development
 
-@subpage test-vvmx - Nested VT-x tests.
+@subpage test-nested-vmx - Nested VT-x tests.
 */
diff --git a/tests/nested-vmx/Makefile b/tests/nested-vmx/Makefile
new file mode 100644 (file)
index 0000000..1ce0d1d
--- /dev/null
@@ -0,0 +1,11 @@
+include $(ROOT)/build/common.mk
+
+NAME      := nested-vmx
+CATEGORY  := in-development
+TEST-ENVS := $(HVM_ENVIRONMENTS)
+
+TEST-EXTRA-CFG := extra.cfg.in
+
+obj-perenv += main.o msr.o util.o vmxon.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/nested-vmx/extra.cfg.in b/tests/nested-vmx/extra.cfg.in
new file mode 100644 (file)
index 0000000..ae494f8
--- /dev/null
@@ -0,0 +1 @@
+nestedhvm = 1
diff --git a/tests/nested-vmx/main.c b/tests/nested-vmx/main.c
new file mode 100644 (file)
index 0000000..6d46642
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * @file tests/nested-vmx/main.c
+ * @ref test-nested-vmx
+ *
+ * @page test-nested-vmx Nested VT-x
+ *
+ * Functional testing of the VMX features in a nested-virt environment.
+ *
+ * @see tests/nested-vmx/main.c
+ */
+#include "test.h"
+
+const char test_title[] = "Nested VT-x testing";
+
+void test_main(void)
+{
+    if ( !cpu_has_vmx )
+        return xtf_skip("Skip: VT-x not available\n");
+
+    if ( !vendor_is_intel )
+        xtf_warning("Warning: VT-x found on non-Intel processor\n");
+
+    test_msr_vmx();
+
+    if ( xtf_status_reported() )
+        return; /* No point continuing if the basic MSRs aren't working. */
+
+    vmx_collect_data();
+
+    test_vmxon();
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/nested-vmx/msr.c b/tests/nested-vmx/msr.c
new file mode 100644 (file)
index 0000000..0c82160
--- /dev/null
@@ -0,0 +1,70 @@
+#include "test.h"
+
+/*
+ * Guest MSR_FEATURE_CONTROL is set by Xen hypervisor instead by guest
+ * firmware or hvmloader, so this test checks whether bits in
+ * MSR_FEATURE_CONTROL are set correctly and does not require they are all
+ * zero.
+ */
+static void test_msr_feature_control(void)
+{
+    msr_feature_control_t feat;
+
+    if ( rdmsr_safe(MSR_FEATURE_CONTROL, &feat.raw) )
+        return xtf_failure("Fail: Fault when reading MSR_FEATURE_CONTROL\n");
+
+    if ( !cpu_has_smx && feat.vmxon_inside_smx )
+        xtf_failure("Fail: FEATURE_CONTROL.VMXON_INSIDE_SMX is set but SMX is not supported\n");
+
+    if ( !feat.vmxon_outside_smx )
+        xtf_failure("Fail: FEATURE_CONTROL.VMXON_OUTSIDE_SMX is not set\n");
+
+    /* VMXON should be unusable if LOCK isn't set. */
+    if ( !feat.lock )
+        xtf_failure("Fail: FEATURE_CONTROL.LOCK is not set\n");
+
+    /* Because LOCK is set, the MSR should be read-only. */
+    if ( !wrmsr_safe(MSR_FEATURE_CONTROL, feat.raw) )
+        xtf_failure("Fail: Successfully wrote to MSR_FEATURE_CONTROL\n");
+}
+
+static void test_msr_vmx_basic(void)
+{
+    msr_vmx_basic_t basic;
+
+    if ( rdmsr_safe(MSR_VMX_BASIC, &basic.raw) )
+        return xtf_failure("Fail: Fault when reading MSR_VMX_BASIC\n");
+
+    if ( basic.mbz )
+        xtf_failure("Fail: MSR_VMX_BASIC[31] is not 0\n");
+
+    if ( basic.vmcs_size == 0 )
+        xtf_failure("Fail: VMCS size reported as 0\n");
+    else if ( basic.vmcs_size > 4096 )
+        xtf_failure("Fail: VMCS size (%u) exceeds 4096 limit\n",
+                    basic.vmcs_size);
+
+    if ( cpu_has_lm && basic.paddr_32bit )
+        xtf_failure("Fail: Physical address width limited to 32 bits\n");
+
+    if ( !wrmsr_safe(MSR_VMX_BASIC, basic.raw) )
+        xtf_failure("Fail: Successfully wrote to MSR_VMX_BASIC\n");
+}
+
+void test_msr_vmx(void)
+{
+    printk("Test: MSRs\n");
+
+    test_msr_feature_control();
+    test_msr_vmx_basic();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/nested-vmx/test.h b/tests/nested-vmx/test.h
new file mode 100644 (file)
index 0000000..5d9664f
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef VVMX_TEST_H
+#define VVMX_TEST_H
+
+#include <xtf.h>
+
+#include <arch/vmx.h>
+
+/*
+ * Extentions on top of regular EXINFO.
+ *
+ * Use EXINFO_AVAIL{0,1} for VMFail{Invalid,Valid}.  (ab)use the fact that
+ * VMFailValid means no exception occured to stash the VMX Instruction Error
+ * code in the low bits, normally used for vector/error_code information.
+ */
+#define VMERR_SUCCESS      0
+#define VMERR_INVALID      (EXINFO_EXPECTED | EXINFO_AVAIL0)
+#define VMERR_VALID(x)     (EXINFO_EXPECTED | EXINFO_AVAIL1 | ((x) & 0xffff))
+
+/**
+ * Compare an expectation against what really happenend, printing
+ * human-readable information in case of a mismatch.
+ */
+void check(const char *func, exinfo_t got, exinfo_t exp);
+
+extern uint32_t vmcs_revid; /**< Hardware VMCS Revision ID. */
+
+/**
+ * Collect real information about the VT-x environment, for use by test.
+ */
+void vmx_collect_data(void);
+
+/* Clear a VMCS, and set a specific revision id. */
+static inline void clear_vmcs(void *_vmcs, uint32_t rev)
+{
+    uint32_t *vmcs = _vmcs;
+
+    memset(vmcs, 0, PAGE_SIZE);
+    vmcs[0] = rev;
+}
+
+/* VMX instruction stubs, wrapped to return exinfo_t information. */
+exinfo_t stub_vmxon(uint64_t paddr);
+exinfo_t stub_vmptrld(uint64_t paddr);
+exinfo_t stub_vmxon_user(uint64_t paddr);
+
+/* Test routines. */
+void test_msr_vmx(void);
+void test_vmxon(void);
+
+#endif /* VVMX_TEST_H */
diff --git a/tests/nested-vmx/util.c b/tests/nested-vmx/util.c
new file mode 100644 (file)
index 0000000..5cf16c3
--- /dev/null
@@ -0,0 +1,159 @@
+#include "test.h"
+
+#include <arch/decode.h>
+
+static void decode_test_exinfo(char *str, size_t n, exinfo_t ex)
+{
+    if ( ex == VMERR_SUCCESS )
+    {
+        strcpy(str, "VMsucceed");
+        return;
+    }
+
+    if ( ex == VMERR_INVALID )
+    {
+        strcpy(str, "VMfailInvalid");
+        return;
+    }
+
+    unsigned int high = ex & ~0xffffff;
+
+    if ( high == VMERR_VALID(0) )
+    {
+        unsigned int low = ex & 0xffffff;
+
+        snprintf(str, n, "VMfailValid(%u) %s",
+                 low, vmx_insn_err_strerror(low));
+        return;
+    }
+
+    if ( high == EXINFO_EXPECTED )
+    {
+        snprintf(str, n, "%pe", _p(ex));
+        return;
+    }
+
+    strcpy(str, "<bad>");
+}
+
+void check(const char *func, exinfo_t got, exinfo_t exp)
+{
+    char gotstr[48], expstr[48];
+
+    if ( got == exp )
+        return;
+
+    decode_test_exinfo(gotstr, ARRAY_SIZE(gotstr), got);
+    decode_test_exinfo(expstr, ARRAY_SIZE(expstr), exp);
+
+    xtf_failure("Failure in %s()\n"
+                "  Expected 0x%08x: %s\n"
+                "       Got 0x%08x: %s\n",
+                func, exp, expstr, got, gotstr);
+}
+
+uint32_t vmcs_revid;
+
+void vmx_collect_data(void)
+{
+    msr_vmx_basic_t basic = { rdmsr(MSR_VMX_BASIC) };
+
+    vmcs_revid = basic.vmcs_rev_id;
+}
+
+/*
+ * Read the VM Instruction Error code from the VMCS.  It is the callers
+ * responsibility to ensure that the VMCS is valid in context.
+ */
+static exinfo_t get_vmx_insn_err(void)
+{
+    unsigned long err;
+
+    asm ("vmread %[field], %[value]"
+         : [value] "=rm" (err)
+         : [field] "r" (VMCS_VM_INSN_ERR + 0ul));
+
+    return VMERR_VALID(err);
+}
+
+exinfo_t stub_vmxon(uint64_t paddr)
+{
+    exinfo_t ex = 0;
+    bool fail_valid = false, fail_invalid = false;
+
+    asm volatile ("1: vmxon %[paddr];"
+                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
+                  ASM_FLAG_OUT(, "setz %[fail_valid];")
+                  "2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                  : "+D" (ex),
+                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
+                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
+                  : [paddr] "m" (paddr),
+                    "X" (ex_record_fault_edi));
+
+    if ( fail_invalid )
+        return VMERR_INVALID;
+    else if ( fail_valid )
+        return get_vmx_insn_err();
+    else
+        return ex;
+}
+
+exinfo_t stub_vmptrld(uint64_t paddr)
+{
+    exinfo_t ex = 0;
+    bool fail_valid = false, fail_invalid = false;
+
+    asm volatile ("1: vmptrld %[paddr];"
+                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
+                  ASM_FLAG_OUT(, "setz %[fail_valid];")
+                  "2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                  : "+D" (ex),
+                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
+                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
+                  : [paddr] "m" (paddr),
+                    "X" (ex_record_fault_edi));
+
+    if ( fail_invalid )
+        return VMERR_INVALID;
+    else if ( fail_valid )
+        return get_vmx_insn_err();
+    else
+        return ex;
+}
+
+exinfo_t __user_text stub_vmxon_user(uint64_t paddr)
+{
+    exinfo_t ex = 0;
+    bool fail_valid = false, fail_invalid = false;
+
+    asm volatile ("1: vmxon %[paddr];"
+                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
+                  ASM_FLAG_OUT(, "setz %[fail_valid];")
+                  "2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                  : "+D" (ex),
+                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
+                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
+                  : [paddr] "m" (paddr),
+                    "X" (ex_record_fault_edi));
+
+    if ( fail_invalid )
+        return VMERR_INVALID;
+    else if ( fail_valid )
+        return get_vmx_insn_err();
+    else
+        return ex;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/nested-vmx/vmxon.c b/tests/nested-vmx/vmxon.c
new file mode 100644 (file)
index 0000000..74b1182
--- /dev/null
@@ -0,0 +1,216 @@
+#include "test.h"
+
+/* vmxon region which shouldn't be latched in the hardware vmxon pointer. */
+static uint8_t vmxon_region_unused[PAGE_SIZE] __page_aligned_bss;
+
+/* vmxon region which gets latched in hardware. */
+static uint8_t vmxon_region_real[PAGE_SIZE] __page_aligned_bss;
+
+/* Loaded VMCS, to recover VM Instruction Errors. */
+static uint8_t vmcs[PAGE_SIZE] __page_aligned_bss;
+
+/**
+ * vmxon with CR4.VMXE cleared
+ *
+ * Expect: @#UD
+ */
+static void test_vmxon_novmxe(void)
+{
+    check(__func__, stub_vmxon(0), EXINFO_SYM(UD, 0));
+}
+
+/*
+ * Wrapper around stub_vmxon_user(), This stub should always fault for control
+ * or permission reasons, but pointing at a supervisor frame is useful to
+ * check that Xen doesn't dereference the instructions parameter.
+ */
+static unsigned long __user_text vmxon_in_user(void)
+{
+    return stub_vmxon_user(_u(vmxon_region_unused));
+}
+
+/**
+ * vmxon in CPL=3 outside of VMX operation
+ *
+ * Expect: @#GP(0)
+ */
+static void test_vmxon_novmxe_in_user(void)
+{
+    exinfo_t ex = exec_user(vmxon_in_user);
+
+    check(__func__, ex, EXINFO_SYM(UD, 0));
+}
+
+/**
+ * vmxon in CPL=3 in VMX operation
+ *
+ * Expect: @#UD
+ */
+static void test_vmxon_in_user(void)
+{
+    exinfo_t ex = exec_user(vmxon_in_user);
+
+    check(__func__, ex, EXINFO_SYM(GP, 0));
+}
+
+/**
+ * vmxon with a physical address that exceeds the maximum address width
+ *
+ * Expect: VMfailInvalid
+ */
+static void test_vmxon_overly_wide_paddr(void)
+{
+    exinfo_t ex = stub_vmxon(1ULL << maxphysaddr);
+
+    check(__func__, ex, VMERR_INVALID);
+}
+
+/**
+ * vmxon with an unaligned physical address
+ *
+ * Expect: VMfailInvalid
+ */
+static void test_vmxon_unaligned_paddr(void)
+{
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused) | 0xff);
+
+    check(__func__, ex, VMERR_INVALID);
+}
+
+/**
+ * vmxon with VMCS revision ID mismatched with MSR_IA32_VMX_BASIC
+ *
+ * Expect: VMfailInvalid
+ */
+static void test_vmxon_mismatched_revid(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid ^ 2);
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
+
+    check(__func__, ex, VMERR_INVALID);
+}
+
+/**
+ * vmxon with VMCS revision ID[31] set
+ *
+ * Expect: VMfailInvalid
+ */
+static void test_vmxon_revid_bit31(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid | (1UL << 31));
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
+
+    check(__func__, ex, VMERR_INVALID);
+}
+
+/**
+ * vmxon expected to succeed
+ *
+ * Expect: Success
+ */
+static void test_vmxon_correct(void)
+{
+    clear_vmcs(vmxon_region_real, vmcs_revid);
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_real));
+
+    check(__func__, ex, VMERR_SUCCESS);
+}
+
+/**
+ * vmxon in VMX root w/ CPL = 0 and w/o current VMCS
+ *
+ * Expect: VMfailInvalid
+ */
+static void test_vmxon_novmcs_in_root_cpl0(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid);
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
+
+    check(__func__, ex, VMERR_INVALID);
+}
+
+/**
+ * vmxon in VMX root w/ CPL = 3 and w/o current VMCS
+ *
+ * Expect: @#GP(0)
+ */
+static void test_vmxon_novmcs_in_root_user(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid);
+    exinfo_t ex = exec_user(vmxon_in_user);
+
+    check(__func__, ex, EXINFO_SYM(GP, 0));
+}
+
+/**
+ * vmxon in VMX root w/ CPL = 0 and w/ current VMCS
+ *
+ * Expect: VMfailvalid()
+ */
+static void test_vmxon_in_root_cpl0(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid);
+    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
+
+    check(__func__, ex, VMERR_VALID(VMERR_VMXON_IN_ROOT));
+}
+
+/**
+ * vmxon in VMX root w/ CPL = 3 and w/ current VMCS
+ *
+ * Expect: @#GP(0)
+ */
+static void test_vmxon_in_root_user(void)
+{
+    clear_vmcs(vmxon_region_unused, vmcs_revid);
+    exinfo_t ex = exec_user(vmxon_in_user);
+
+    check(__func__, ex, EXINFO_SYM(GP, 0));
+}
+
+void test_vmxon(void)
+{
+    unsigned long cr4 = read_cr4();
+    exinfo_t ex;
+
+    if ( cr4 & X86_CR4_VMXE )
+        write_cr4(cr4 &= ~X86_CR4_VMXE);
+
+    printk("Test: vmxon\n");
+
+    test_vmxon_novmxe();
+    test_vmxon_novmxe_in_user();
+
+    write_cr4(cr4 |= X86_CR4_VMXE);
+
+    test_vmxon_in_user();
+    test_vmxon_overly_wide_paddr();
+    test_vmxon_unaligned_paddr();
+    test_vmxon_mismatched_revid();
+    test_vmxon_revid_bit31();
+    test_vmxon_correct();
+
+    /* Test should now be operating in VMX Root mode. */
+
+    test_vmxon_novmcs_in_root_cpl0();
+    test_vmxon_novmcs_in_root_user();
+
+    /* Load a real VMCS to recover VM Instruction Errors. */
+    clear_vmcs(vmcs, vmcs_revid);
+    ex = stub_vmptrld(_u(vmcs));
+    if ( ex )
+        return xtf_failure("Fail: unexpected vmptrld failure %08x\n", ex);
+
+    test_vmxon_in_root_cpl0();
+    test_vmxon_in_root_user();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/Makefile b/tests/vvmx/Makefile
deleted file mode 100644 (file)
index 2fc67c1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-include $(ROOT)/build/common.mk
-
-NAME      := vvmx
-CATEGORY  := in-development
-TEST-ENVS := $(HVM_ENVIRONMENTS)
-
-TEST-EXTRA-CFG := extra.cfg.in
-
-obj-perenv += main.o msr.o util.o vmxon.o
-
-include $(ROOT)/build/gen.mk
diff --git a/tests/vvmx/extra.cfg.in b/tests/vvmx/extra.cfg.in
deleted file mode 100644 (file)
index ae494f8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-nestedhvm = 1
diff --git a/tests/vvmx/main.c b/tests/vvmx/main.c
deleted file mode 100644 (file)
index 9e21337..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * @file tests/vvmx/main.c
- * @ref test-vvmx
- *
- * @page test-vvmx vvmx
- *
- * Functional testing of the VMX features in a nested-virt environment.
- *
- * @see tests/vvmx/main.c
- */
-#include "test.h"
-
-const char test_title[] = "Nested VT-x testing";
-
-void test_main(void)
-{
-    if ( !cpu_has_vmx )
-        return xtf_skip("Skip: VT-x not available\n");
-
-    if ( !vendor_is_intel )
-        xtf_warning("Warning: VT-x found on non-Intel processor\n");
-
-    test_msr_vmx();
-
-    if ( xtf_status_reported() )
-        return; /* No point continuing if the basic MSRs aren't working. */
-
-    vmx_collect_data();
-
-    test_vmxon();
-
-    xtf_success(NULL);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tests/vvmx/msr.c b/tests/vvmx/msr.c
deleted file mode 100644 (file)
index 0c82160..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "test.h"
-
-/*
- * Guest MSR_FEATURE_CONTROL is set by Xen hypervisor instead by guest
- * firmware or hvmloader, so this test checks whether bits in
- * MSR_FEATURE_CONTROL are set correctly and does not require they are all
- * zero.
- */
-static void test_msr_feature_control(void)
-{
-    msr_feature_control_t feat;
-
-    if ( rdmsr_safe(MSR_FEATURE_CONTROL, &feat.raw) )
-        return xtf_failure("Fail: Fault when reading MSR_FEATURE_CONTROL\n");
-
-    if ( !cpu_has_smx && feat.vmxon_inside_smx )
-        xtf_failure("Fail: FEATURE_CONTROL.VMXON_INSIDE_SMX is set but SMX is not supported\n");
-
-    if ( !feat.vmxon_outside_smx )
-        xtf_failure("Fail: FEATURE_CONTROL.VMXON_OUTSIDE_SMX is not set\n");
-
-    /* VMXON should be unusable if LOCK isn't set. */
-    if ( !feat.lock )
-        xtf_failure("Fail: FEATURE_CONTROL.LOCK is not set\n");
-
-    /* Because LOCK is set, the MSR should be read-only. */
-    if ( !wrmsr_safe(MSR_FEATURE_CONTROL, feat.raw) )
-        xtf_failure("Fail: Successfully wrote to MSR_FEATURE_CONTROL\n");
-}
-
-static void test_msr_vmx_basic(void)
-{
-    msr_vmx_basic_t basic;
-
-    if ( rdmsr_safe(MSR_VMX_BASIC, &basic.raw) )
-        return xtf_failure("Fail: Fault when reading MSR_VMX_BASIC\n");
-
-    if ( basic.mbz )
-        xtf_failure("Fail: MSR_VMX_BASIC[31] is not 0\n");
-
-    if ( basic.vmcs_size == 0 )
-        xtf_failure("Fail: VMCS size reported as 0\n");
-    else if ( basic.vmcs_size > 4096 )
-        xtf_failure("Fail: VMCS size (%u) exceeds 4096 limit\n",
-                    basic.vmcs_size);
-
-    if ( cpu_has_lm && basic.paddr_32bit )
-        xtf_failure("Fail: Physical address width limited to 32 bits\n");
-
-    if ( !wrmsr_safe(MSR_VMX_BASIC, basic.raw) )
-        xtf_failure("Fail: Successfully wrote to MSR_VMX_BASIC\n");
-}
-
-void test_msr_vmx(void)
-{
-    printk("Test: MSRs\n");
-
-    test_msr_feature_control();
-    test_msr_vmx_basic();
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tests/vvmx/test.h b/tests/vvmx/test.h
deleted file mode 100644 (file)
index 5d9664f..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef VVMX_TEST_H
-#define VVMX_TEST_H
-
-#include <xtf.h>
-
-#include <arch/vmx.h>
-
-/*
- * Extentions on top of regular EXINFO.
- *
- * Use EXINFO_AVAIL{0,1} for VMFail{Invalid,Valid}.  (ab)use the fact that
- * VMFailValid means no exception occured to stash the VMX Instruction Error
- * code in the low bits, normally used for vector/error_code information.
- */
-#define VMERR_SUCCESS      0
-#define VMERR_INVALID      (EXINFO_EXPECTED | EXINFO_AVAIL0)
-#define VMERR_VALID(x)     (EXINFO_EXPECTED | EXINFO_AVAIL1 | ((x) & 0xffff))
-
-/**
- * Compare an expectation against what really happenend, printing
- * human-readable information in case of a mismatch.
- */
-void check(const char *func, exinfo_t got, exinfo_t exp);
-
-extern uint32_t vmcs_revid; /**< Hardware VMCS Revision ID. */
-
-/**
- * Collect real information about the VT-x environment, for use by test.
- */
-void vmx_collect_data(void);
-
-/* Clear a VMCS, and set a specific revision id. */
-static inline void clear_vmcs(void *_vmcs, uint32_t rev)
-{
-    uint32_t *vmcs = _vmcs;
-
-    memset(vmcs, 0, PAGE_SIZE);
-    vmcs[0] = rev;
-}
-
-/* VMX instruction stubs, wrapped to return exinfo_t information. */
-exinfo_t stub_vmxon(uint64_t paddr);
-exinfo_t stub_vmptrld(uint64_t paddr);
-exinfo_t stub_vmxon_user(uint64_t paddr);
-
-/* Test routines. */
-void test_msr_vmx(void);
-void test_vmxon(void);
-
-#endif /* VVMX_TEST_H */
diff --git a/tests/vvmx/util.c b/tests/vvmx/util.c
deleted file mode 100644 (file)
index 5cf16c3..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-#include "test.h"
-
-#include <arch/decode.h>
-
-static void decode_test_exinfo(char *str, size_t n, exinfo_t ex)
-{
-    if ( ex == VMERR_SUCCESS )
-    {
-        strcpy(str, "VMsucceed");
-        return;
-    }
-
-    if ( ex == VMERR_INVALID )
-    {
-        strcpy(str, "VMfailInvalid");
-        return;
-    }
-
-    unsigned int high = ex & ~0xffffff;
-
-    if ( high == VMERR_VALID(0) )
-    {
-        unsigned int low = ex & 0xffffff;
-
-        snprintf(str, n, "VMfailValid(%u) %s",
-                 low, vmx_insn_err_strerror(low));
-        return;
-    }
-
-    if ( high == EXINFO_EXPECTED )
-    {
-        snprintf(str, n, "%pe", _p(ex));
-        return;
-    }
-
-    strcpy(str, "<bad>");
-}
-
-void check(const char *func, exinfo_t got, exinfo_t exp)
-{
-    char gotstr[48], expstr[48];
-
-    if ( got == exp )
-        return;
-
-    decode_test_exinfo(gotstr, ARRAY_SIZE(gotstr), got);
-    decode_test_exinfo(expstr, ARRAY_SIZE(expstr), exp);
-
-    xtf_failure("Failure in %s()\n"
-                "  Expected 0x%08x: %s\n"
-                "       Got 0x%08x: %s\n",
-                func, exp, expstr, got, gotstr);
-}
-
-uint32_t vmcs_revid;
-
-void vmx_collect_data(void)
-{
-    msr_vmx_basic_t basic = { rdmsr(MSR_VMX_BASIC) };
-
-    vmcs_revid = basic.vmcs_rev_id;
-}
-
-/*
- * Read the VM Instruction Error code from the VMCS.  It is the callers
- * responsibility to ensure that the VMCS is valid in context.
- */
-static exinfo_t get_vmx_insn_err(void)
-{
-    unsigned long err;
-
-    asm ("vmread %[field], %[value]"
-         : [value] "=rm" (err)
-         : [field] "r" (VMCS_VM_INSN_ERR + 0ul));
-
-    return VMERR_VALID(err);
-}
-
-exinfo_t stub_vmxon(uint64_t paddr)
-{
-    exinfo_t ex = 0;
-    bool fail_valid = false, fail_invalid = false;
-
-    asm volatile ("1: vmxon %[paddr];"
-                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
-                  ASM_FLAG_OUT(, "setz %[fail_valid];")
-                  "2:"
-                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
-                  : "+D" (ex),
-                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
-                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
-                  : [paddr] "m" (paddr),
-                    "X" (ex_record_fault_edi));
-
-    if ( fail_invalid )
-        return VMERR_INVALID;
-    else if ( fail_valid )
-        return get_vmx_insn_err();
-    else
-        return ex;
-}
-
-exinfo_t stub_vmptrld(uint64_t paddr)
-{
-    exinfo_t ex = 0;
-    bool fail_valid = false, fail_invalid = false;
-
-    asm volatile ("1: vmptrld %[paddr];"
-                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
-                  ASM_FLAG_OUT(, "setz %[fail_valid];")
-                  "2:"
-                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
-                  : "+D" (ex),
-                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
-                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
-                  : [paddr] "m" (paddr),
-                    "X" (ex_record_fault_edi));
-
-    if ( fail_invalid )
-        return VMERR_INVALID;
-    else if ( fail_valid )
-        return get_vmx_insn_err();
-    else
-        return ex;
-}
-
-exinfo_t __user_text stub_vmxon_user(uint64_t paddr)
-{
-    exinfo_t ex = 0;
-    bool fail_valid = false, fail_invalid = false;
-
-    asm volatile ("1: vmxon %[paddr];"
-                  ASM_FLAG_OUT(, "setc %[fail_invalid];")
-                  ASM_FLAG_OUT(, "setz %[fail_valid];")
-                  "2:"
-                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
-                  : "+D" (ex),
-                    ASM_FLAG_OUT("=@ccc", [fail_invalid] "+rm") (fail_invalid),
-                    ASM_FLAG_OUT("=@ccz", [fail_valid]   "+rm") (fail_valid)
-                  : [paddr] "m" (paddr),
-                    "X" (ex_record_fault_edi));
-
-    if ( fail_invalid )
-        return VMERR_INVALID;
-    else if ( fail_valid )
-        return get_vmx_insn_err();
-    else
-        return ex;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tests/vvmx/vmxon.c b/tests/vvmx/vmxon.c
deleted file mode 100644 (file)
index 74b1182..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-#include "test.h"
-
-/* vmxon region which shouldn't be latched in the hardware vmxon pointer. */
-static uint8_t vmxon_region_unused[PAGE_SIZE] __page_aligned_bss;
-
-/* vmxon region which gets latched in hardware. */
-static uint8_t vmxon_region_real[PAGE_SIZE] __page_aligned_bss;
-
-/* Loaded VMCS, to recover VM Instruction Errors. */
-static uint8_t vmcs[PAGE_SIZE] __page_aligned_bss;
-
-/**
- * vmxon with CR4.VMXE cleared
- *
- * Expect: @#UD
- */
-static void test_vmxon_novmxe(void)
-{
-    check(__func__, stub_vmxon(0), EXINFO_SYM(UD, 0));
-}
-
-/*
- * Wrapper around stub_vmxon_user(), This stub should always fault for control
- * or permission reasons, but pointing at a supervisor frame is useful to
- * check that Xen doesn't dereference the instructions parameter.
- */
-static unsigned long __user_text vmxon_in_user(void)
-{
-    return stub_vmxon_user(_u(vmxon_region_unused));
-}
-
-/**
- * vmxon in CPL=3 outside of VMX operation
- *
- * Expect: @#GP(0)
- */
-static void test_vmxon_novmxe_in_user(void)
-{
-    exinfo_t ex = exec_user(vmxon_in_user);
-
-    check(__func__, ex, EXINFO_SYM(UD, 0));
-}
-
-/**
- * vmxon in CPL=3 in VMX operation
- *
- * Expect: @#UD
- */
-static void test_vmxon_in_user(void)
-{
-    exinfo_t ex = exec_user(vmxon_in_user);
-
-    check(__func__, ex, EXINFO_SYM(GP, 0));
-}
-
-/**
- * vmxon with a physical address that exceeds the maximum address width
- *
- * Expect: VMfailInvalid
- */
-static void test_vmxon_overly_wide_paddr(void)
-{
-    exinfo_t ex = stub_vmxon(1ULL << maxphysaddr);
-
-    check(__func__, ex, VMERR_INVALID);
-}
-
-/**
- * vmxon with an unaligned physical address
- *
- * Expect: VMfailInvalid
- */
-static void test_vmxon_unaligned_paddr(void)
-{
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused) | 0xff);
-
-    check(__func__, ex, VMERR_INVALID);
-}
-
-/**
- * vmxon with VMCS revision ID mismatched with MSR_IA32_VMX_BASIC
- *
- * Expect: VMfailInvalid
- */
-static void test_vmxon_mismatched_revid(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid ^ 2);
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
-
-    check(__func__, ex, VMERR_INVALID);
-}
-
-/**
- * vmxon with VMCS revision ID[31] set
- *
- * Expect: VMfailInvalid
- */
-static void test_vmxon_revid_bit31(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid | (1UL << 31));
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
-
-    check(__func__, ex, VMERR_INVALID);
-}
-
-/**
- * vmxon expected to succeed
- *
- * Expect: Success
- */
-static void test_vmxon_correct(void)
-{
-    clear_vmcs(vmxon_region_real, vmcs_revid);
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_real));
-
-    check(__func__, ex, VMERR_SUCCESS);
-}
-
-/**
- * vmxon in VMX root w/ CPL = 0 and w/o current VMCS
- *
- * Expect: VMfailInvalid
- */
-static void test_vmxon_novmcs_in_root_cpl0(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid);
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
-
-    check(__func__, ex, VMERR_INVALID);
-}
-
-/**
- * vmxon in VMX root w/ CPL = 3 and w/o current VMCS
- *
- * Expect: @#GP(0)
- */
-static void test_vmxon_novmcs_in_root_user(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid);
-    exinfo_t ex = exec_user(vmxon_in_user);
-
-    check(__func__, ex, EXINFO_SYM(GP, 0));
-}
-
-/**
- * vmxon in VMX root w/ CPL = 0 and w/ current VMCS
- *
- * Expect: VMfailvalid()
- */
-static void test_vmxon_in_root_cpl0(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid);
-    exinfo_t ex = stub_vmxon(_u(vmxon_region_unused));
-
-    check(__func__, ex, VMERR_VALID(VMERR_VMXON_IN_ROOT));
-}
-
-/**
- * vmxon in VMX root w/ CPL = 3 and w/ current VMCS
- *
- * Expect: @#GP(0)
- */
-static void test_vmxon_in_root_user(void)
-{
-    clear_vmcs(vmxon_region_unused, vmcs_revid);
-    exinfo_t ex = exec_user(vmxon_in_user);
-
-    check(__func__, ex, EXINFO_SYM(GP, 0));
-}
-
-void test_vmxon(void)
-{
-    unsigned long cr4 = read_cr4();
-    exinfo_t ex;
-
-    if ( cr4 & X86_CR4_VMXE )
-        write_cr4(cr4 &= ~X86_CR4_VMXE);
-
-    printk("Test: vmxon\n");
-
-    test_vmxon_novmxe();
-    test_vmxon_novmxe_in_user();
-
-    write_cr4(cr4 |= X86_CR4_VMXE);
-
-    test_vmxon_in_user();
-    test_vmxon_overly_wide_paddr();
-    test_vmxon_unaligned_paddr();
-    test_vmxon_mismatched_revid();
-    test_vmxon_revid_bit31();
-    test_vmxon_correct();
-
-    /* Test should now be operating in VMX Root mode. */
-
-    test_vmxon_novmcs_in_root_cpl0();
-    test_vmxon_novmcs_in_root_user();
-
-    /* Load a real VMCS to recover VM Instruction Errors. */
-    clear_vmcs(vmcs, vmcs_revid);
-    ex = stub_vmptrld(_u(vmcs));
-    if ( ex )
-        return xtf_failure("Fail: unexpected vmptrld failure %08x\n", ex);
-
-    test_vmxon_in_root_cpl0();
-    test_vmxon_in_root_user();
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */