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

[Xen-devel] [PATCH XTF v2] Functional: Add a UMIP test



Add a "umip" test for the User-Model Instruction Prevention. The test
simply tries to run sgdt/sidt/sldt/str/smsw in guest user-mode with
CR4_UMIP = 1.

Signed-off-by: Boqun Feng (Intel) <boqun.feng@xxxxxxxxx>
---
v1 --> v2:
        * add a new write_cr4_safe()
        * use %pe for exception print
        * refactor the code based on Andrew's guide and advice

Test results:

* With UMIP patch:
** boot with hvm_fep: SUCCESS
** boot without hvm_fep: SKIP, due to "FEP support not detected.."

* Without UMIP patch:
** boot with hvm_fep: SKIP, due to "UMIP is not supported.."
** boot without hvm_fep: SKIP, due to "UMIP is not supported.."

* With UMIP cpuid exposed but CR4 invalid:
** boot with hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."
** boot without hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."


 arch/x86/include/arch/lib.h |  13 +++
 docs/all-tests.dox          |   2 +
 tests/umip/Makefile         |   9 ++
 tests/umip/main.c           | 219 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 243 insertions(+)
 create mode 100644 tests/umip/Makefile
 create mode 100644 tests/umip/main.c

diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h
index f608af9996f0..4f0d85290cf0 100644
--- a/arch/x86/include/arch/lib.h
+++ b/arch/x86/include/arch/lib.h
@@ -340,6 +340,19 @@ static inline void write_cr4(unsigned long cr4)
     asm volatile ("mov %0, %%cr4" :: "r" (cr4));
 }
 
+static inline bool write_cr4_safe(unsigned long cr4)
+{
+    exinfo_t fault = 0;
+
+    asm volatile ("1: mov %1, %%cr4; 2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                  : "+D" (fault)
+                  : "r" (cr4),
+                    "X" (ex_record_fault_edi));
+
+    return !fault;
+}
+
 static inline void write_cr8(unsigned long cr8)
 {
     asm volatile ("mov %0, %%cr8" :: "r" (cr8));
diff --git a/docs/all-tests.dox b/docs/all-tests.dox
index c1b163a926cb..ef011007cf68 100644
--- a/docs/all-tests.dox
+++ b/docs/all-tests.dox
@@ -111,4 +111,6 @@ guest breakout.
 @section index-in-development In Development
 
 @subpage test-vvmx - Nested VT-x tests.
+
+@subpage test-umip - User-Mode Instruction Prevention
 */
diff --git a/tests/umip/Makefile b/tests/umip/Makefile
new file mode 100644
index 000000000000..0248c8b247a0
--- /dev/null
+++ b/tests/umip/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := umip
+CATEGORY  := functional
+TEST-ENVS := hvm32 hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/umip/main.c b/tests/umip/main.c
new file mode 100644
index 000000000000..fcaba4e34570
--- /dev/null
+++ b/tests/umip/main.c
@@ -0,0 +1,219 @@
+/**
+ * @file tests/umip/main.c
+ * @ref test-umip
+ *
+ * @page test-umip umip
+ *
+ * @todo Docs for test-umip
+ *
+ * @see tests/umip/main.c
+ */
+#include <xtf.h>
+#include <arch/exinfo.h>
+#include <arch/processor.h>
+
+const char test_title[] = "User-Mode Instruction Prevention Test";
+bool test_wants_user_mappings = true;
+
+static unsigned long stub_sgdt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    desc_ptr tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sgdt %[tmp]; 2:"
+                _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+               : "+D" (fault), [tmp] "=m" (tmp)
+                : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+static unsigned long stub_sidt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    desc_ptr tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sidt %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                : "+D" (fault), [tmp] "=m" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_sldt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sldt %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_str(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: str %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_smsw(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: smsw %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static const struct stub {
+    unsigned long (*fn)(unsigned long);
+    const char *name;
+} stubs[] = {
+    { stub_sgdt, "SGDT" },
+    { stub_sidt, "SIDT" },
+    { stub_sldt, "SLDT" },
+    { stub_str,  "STR" },
+    { stub_smsw, "SMSW" },
+};
+
+void test_umip(bool umip_active, bool force)
+{
+    unsigned int i;
+    bool user;
+
+    for ( user = false; ; user = true )
+    {
+        exinfo_t exp = user && umip_active ? EXINFO_SYM(GP, 0) : 0;
+
+        for ( i = 0; i < ARRAY_SIZE(stubs); i++)
+        {
+            const struct stub *s = &stubs[i];
+            exinfo_t ret;
+
+            ret = user ? exec_user_param(s->fn, force) : s->fn(force);
+
+            /*
+             * Tolerate the instruction emulator not understanding these
+             * instructions in older releases of Xen.
+             */
+
+            if ( force && ret == EXINFO_SYM(UD, 0) )
+            {
+                static bool once;
+
+                if ( !once )
+                {
+                    xtf_skip("Skip: Emulator doesn't implement %s\n", s->name);
+                    once = true;
+                }
+
+                continue;
+            }
+
+            if ( ret != exp )
+                xtf_failure("Fail: %s %s\n"
+                            "  expected %pe\n"
+                            "       got %pe\n",
+                            user ? "user" : "supervisor", s->name,
+                            _p(exp), _p(ret));
+        }
+
+        if ( user )
+            break;
+    }
+}
+
+void test_main(void)
+{
+    unsigned long cr4;
+
+    /* run with UMIP inactive */
+    test_umip(false, false);
+
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+    else
+        test_umip(false, true);
+
+    if ( !cpu_has_umip )
+    {
+        xtf_skip("UMIP is not supported, skip the rest of test\n");
+        return;
+    }
+
+    cr4 = read_cr4();
+
+    if ( !write_cr4_safe(cr4 | X86_CR4_UMIP) )
+    {
+        xtf_failure("Fail: Unable to activate UMIP\n");
+        return;
+    }
+
+    /* run with UMIP active */
+    test_umip(true, false);
+
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+    else
+        test_umip(true, true);
+
+    if ( !write_cr4_safe(cr4) )
+    {
+        xtf_failure("Fail: Unable to deactivate UMIP\n");
+        return;
+    }
+
+    /* run with UMIP inactive */
+    test_umip(false, false);
+
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+    else
+        test_umip(false, true);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.13.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.