]> xenbits.xensource.com Git - xtf.git/commitdiff
CPUID Faulting tests
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 14 Oct 2016 12:32:36 +0000 (13:32 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 18 Oct 2016 13:29:44 +0000 (14:29 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/extable.c
docs/all-tests.dox
include/arch/x86/msr-index.h
tests/cpuid-faulting/Makefile [new file with mode: 0644]
tests/cpuid-faulting/main.c [new file with mode: 0644]

index f3bb461779a3b63f386dbc709c5e9e8d4483f4bd..39230146c438103cff45325150ba6f2b9dba5ef6 100644 (file)
@@ -26,6 +26,24 @@ bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
     return true;
 }
 
+/**
+ * Record the current fault in @%edi
+ *
+ * Sample usage:
+ * <pre>
+ *   asm volatile ("1: $INSN; 2:"
+ *                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+ *                 : "=D" (fault) : "0" (0));
+ * </pre>
+ */
+bool ex_record_fault_edi(struct cpu_regs *regs, const struct extable_entry *ex)
+{
+    regs->di = (uint32_t)(regs->entry_vector << 16) | regs->error_code;
+    regs->ip = ex->fixup;
+
+    return true;
+}
+
 /**
  * Fixup from a rdmsr fault
  *
index 79e09e79e5107ae04478a8722b0ec3bb343e64fe..4f861825f9376474ac0862a9d8976e22f92ca774 100644 (file)
@@ -16,6 +16,8 @@ and functionality.
 
 @section index-functional Functional tests
 
+@subpage test-cpuid-faulting - Guest CPUID Faulting support.
+
 @subpage test-fpu-exception-emulation - FPU Exception Emulation.  Covers XSA-190.
 
 @subpage test-invlpg - `invlpg` instruction behaviour.
index 73a1e00358d7f2119a796d9b4cc78e6c75d3a653..d479239e87ea8205bf9bf1dfe50e1e46d6739d10 100644 (file)
@@ -3,6 +3,14 @@
 
 #include <xtf/numbers.h>
 
+#define MSR_INTEL_PLATFORM_INFO         0x000000ce
+#define _MSR_PLATFORM_INFO_CPUID_FAULTING       31
+#define MSR_PLATFORM_INFO_CPUID_FAULTING        (1ULL << _MSR_PLATFORM_INFO_CPUID_FAULTING)
+
+#define MSR_INTEL_MISC_FEATURES_ENABLES 0x00000140
+#define _MSR_MISC_FEATURES_CPUID_FAULTING        0
+#define MSR_MISC_FEATURES_CPUID_FAULTING         (1ULL << _MSR_MISC_FEATURES_CPUID_FAULTING)
+
 #define MSR_EFER                        0xc0000080 /* Extended Feature register. */
 #define _EFER_SCE                       0  /* SYSCALL Enable. */
 #define EFER_SCE                        (_AC(1, L) << _EFER_SCE)
diff --git a/tests/cpuid-faulting/Makefile b/tests/cpuid-faulting/Makefile
new file mode 100644 (file)
index 0000000..574408c
--- /dev/null
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := cpuid-faulting
+CATEGORY  := functional
+TEST-ENVS := $(ALL_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/cpuid-faulting/main.c b/tests/cpuid-faulting/main.c
new file mode 100644 (file)
index 0000000..e30ff87
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * @file tests/cpuid-faulting/main.c
+ * @ref test-cpuid-faulting
+ *
+ * @page test-cpuid-faulting CPUID Faulting support
+ *
+ * CPUID Faulting is a feature available natively on Intel IvyBridge and newer
+ * processors, which allows a kernel or hypervisor to trap userspace `CPUID`
+ * instructions.
+ *
+ * Xen provides this support to guests, and for HVM guests is the the position
+ * to offer CPUID Faulting even on hardware which lacks it natively.
+ *
+ * The native definition of CPUID Faulting is that when enabled, `CPUID`
+ * instructions suffer @#GP[0] when executed at CPL > 0.  This behaviour is
+ * honoured exactly for HVM guests.  PV guests kernels however execute in ring
+ * 1 (32bit PV) or ring 3 (64bit PV).  For PV guests, the implemented
+ * behaviour will cause a @#GP[0] fault when executed in guest userspace.
+ *
+ * @see tests/cpuid-faulting/main.c
+ */
+#include <xtf.h>
+
+#include <arch/x86/msr-index.h>
+#include <arch/x86/processor.h>
+
+bool test_wants_user_mappings = true;
+
+#define EXC_SYM(vec, ec) ((X86_EXC_ ## vec) << 16 | ec)
+
+unsigned long stub_cpuid(void)
+{
+    unsigned int fault = 0, tmp;
+
+    asm volatile("1: cpuid; 2:"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=a" (tmp), "+D" (fault)
+                 : "a" (0)
+                 : "ebx", "ecx", "edx");
+
+    return fault;
+}
+
+unsigned long stub_fep_cpuid(void)
+{
+    unsigned int fault = 0, tmp;
+
+    asm volatile(_ASM_XEN_FEP
+                 "1: cpuid; 2:"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=a" (tmp), "+D" (fault)
+                 : "a" (0)
+                 : "ebx", "ecx", "edx");
+
+    return fault;
+}
+
+static void test_cpuid(bool exp_faulting)
+{
+    /*
+     * Kernel cpuids should never fault
+     */
+    if ( stub_cpuid() )
+        xtf_failure("Fail: kernel cpuid faulted\n");
+
+    if ( IS_DEFINED(CONFIG_PV) && stub_fep_cpuid() )
+        xtf_failure("Fail: kernel pv cpuid faulted\n");
+
+    if ( xtf_has_fep && stub_fep_cpuid() )
+        xtf_failure("Fail: kernel emulated cpuid faulted\n");
+
+    /*
+     * User cpuids should raise #GP[0] if faulting is enabled.
+     */
+    unsigned long exp = exp_faulting ? EXC_SYM(GP, 0) : 0;
+    const char *exp_fail_str = exp_faulting ? "didn't fault" : "faulted";
+
+    if ( exec_user(stub_cpuid) != exp )
+        xtf_failure("Fail: user cpuid %s\n", exp_fail_str);
+
+    if ( IS_DEFINED(CONFIG_PV) && exec_user(stub_fep_cpuid) != exp )
+        xtf_failure("Fail: user pv cpuid %s\n", exp_fail_str);
+
+    if ( xtf_has_fep && exec_user(stub_fep_cpuid) != exp )
+        xtf_failure("Fail: user emulated cpuid %s\n", exp_fail_str);
+}
+
+void test_main(void)
+{
+    uint64_t platform_info, features_enable;
+
+    printk("Guest CPUID Faulting support\n");
+
+    if ( IS_DEFINED(CONFIG_HVM) && !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+
+    /* No faulting.  CPUID should work without faulting anywhere. */
+    printk("Testing CPUID without faulting enabled\n");
+    test_cpuid(false);
+
+    /* Probe for CPUID Faulting support. */
+    if ( rdmsr_safe(MSR_INTEL_PLATFORM_INFO, &platform_info) ||
+         !(platform_info & MSR_PLATFORM_INFO_CPUID_FAULTING) )
+        return xtf_skip("Skip: CPUID Faulting unavailable\n");
+
+    if ( rdmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES, &features_enable) )
+        return xtf_error("Error: Fault accessing MISC_FEATURES_ENABLES\n");
+
+    /* Attempt to enable CPUID Faulting. */
+    if ( wrmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES,
+                    features_enable | MSR_MISC_FEATURES_CPUID_FAULTING) )
+        return xtf_failure("Fail: Unable to enable CPUID Faulting\n");
+
+    /* Faulting active.  CPUID should fault ouside of the kernel. */
+    printk("Testing CPUID with faulting enabled\n");
+    test_cpuid(true);
+
+    /* Try disabling faulting. */
+    if ( wrmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES, features_enable) )
+        return xtf_failure("Fail: Unable to disable CPUID Faulting\n");
+
+    /* Double check that CPUID no longer faults. */
+    printk("Retesting CPUID without faulting enabled\n");
+    test_cpuid(false);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */