|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |