[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 |