[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH XTF v3] 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 v2 --> v3: * add test_insns() to simplify test_main() logic * make write_cr4_safe() return 0 for success. * add UMIP activation test even if !cpu_has_umip Test results: * With UMIP patch: ** boot with hvm_fep: SUCCESS ** boot without hvm_fep: SKIP * Without UMIP patch: ** boot with hvm_fep: SKIP ** boot without hvm_fep: SKIP (illed implementation) * With UMIP cpuid exposed but hvm_cr4_guest_valid_bits() didn't include X86_CR4_UMIP: ** boot with hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.." ** boot without hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.." * With UMIP cpuid not exposed but hvm_cr4_guest_valid_bits() included X86_CR4_UMIP: ** boot with hvm_fep: FAILURE, due to "UMIP unsupported, but setting CR4 succeeded" ** boot without hvm_fep: FAILURE, due to "UMIP unsupported, but setting CR4 succeeded" arch/x86/include/arch/lib.h | 13 +++ docs/all-tests.dox | 2 + tests/umip/Makefile | 9 ++ tests/umip/main.c | 214 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 238 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..82eb7da600c4 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..76764c8b38f4 --- /dev/null +++ b/tests/umip/main.c @@ -0,0 +1,214 @@ +/** + * @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" }, +}; + +static void test_insns(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; + } +} + +static void test_umip(bool umip_active) +{ + test_insns(umip_active, false); + + if ( xtf_has_fep ) + test_insns(umip_active, true); +} + +void test_main(void) +{ + if ( !xtf_has_fep ) + xtf_skip("FEP support not detected - some tests will be skipped\n"); + + test_umip(false); + + if ( !cpu_has_umip ) + { + xtf_skip("UMIP is not supported, skip the rest of test\n"); + + if ( !write_cr4_safe(read_cr4() | X86_CR4_UMIP) ) + xtf_failure("UMIP unsupported, but setting CR4 bit succeeded\n"); + + return; + } + + /* activate UMIP */ + if ( write_cr4_safe(read_cr4() | X86_CR4_UMIP) ) + { + xtf_failure("Fail: Unable to activate UMIP\n"); + return; + } + + test_umip(true); + + /* deactivate UMIP */ + if ( write_cr4_safe(read_cr4() & ~X86_CR4_UMIP) ) + { + xtf_failure("Fail: Unable to deactivate UMIP\n"); + return; + } + + test_umip(false); + + 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 |