From: Andrew Cooper Date: Wed, 7 Feb 2018 10:41:41 +0000 (+0000) Subject: Allow for fine tuning of the exec_user_* infrastructure X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=fbefbc94cfb222eb1ff53b660735a58fbce953cd;p=xtf.git Allow for fine tuning of the exec_user_* infrastructure At the moment, %cs, %ss and eflags are hard coded. Introduce exec_user_{cs,ss,efl_{and,or}_mask} with suitable defaults. This allows for the complete removal of exec_user_with_iopl() from the pv-iopl test, which can now use the common infrastructure. Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/entry_32.S b/arch/x86/entry_32.S index 9869b78..b49b0e7 100644 --- a/arch/x86/entry_32.S +++ b/arch/x86/entry_32.S @@ -119,16 +119,18 @@ ENTRY(exec_user_param) mov %esp, %ebp /* Stash %esp for entry_ret_to_kernel(). */ /* Prepare an IRET frame. */ - push $__USER_DS /* SS */ + push exec_user_ss /* SS */ /* ESP */ push $user_stack + PAGE_SIZE pushf /* EFLAGS */ -#if defined(CONFIG_PV) /* PV guests see the real interrupt flag. Clobber it. */ - andl $~X86_EFLAGS_IF, (%esp) -#endif + /* Apply and/or masks to eflags. */ + mov exec_user_efl_and_mask, %edx + and %edx, (%esp) + mov exec_user_efl_or_mask, %edx + or %edx, (%esp) - push $__USER_CS /* CS */ + push exec_user_cs /* CS */ push $exec_user_stub /* EIP */ env_IRET /* Drop to user privilege. */ diff --git a/arch/x86/entry_64.S b/arch/x86/entry_64.S index e6a81f0..c638e60 100644 --- a/arch/x86/entry_64.S +++ b/arch/x86/entry_64.S @@ -117,16 +117,18 @@ ENTRY(exec_user_param) /* ulong (*fn)(ulong), ulong p1 */ mov %rsp, %rbp /* Stash %rsp for entry_ret_to_kernel(). */ /* Prepare an IRET frame. */ - push $__USER_DS /* SS */ + push exec_user_ss(%rip) /* SS */ /* RSP */ push $user_stack + PAGE_SIZE pushf /* RFLAGS */ -#if defined(CONFIG_PV) /* PV guests see the real interrupt flag. Clobber it. */ - andq $~X86_EFLAGS_IF, (%rsp) -#endif + /* Apply and/or masks to eflags. */ + mov exec_user_efl_and_mask(%rip), %rdx + and %rdx, (%esp) + mov exec_user_efl_or_mask(%rip), %rdx + or %rdx, (%esp) - push $__USER_CS /* CS */ + push exec_user_cs(%rip) /* CS */ push $exec_user_stub /* RIP */ env_IRETQ /* Drop to user privilege. */ diff --git a/arch/x86/include/arch/traps.h b/arch/x86/include/arch/traps.h index e2e7f69..0c6888b 100644 --- a/arch/x86/include/arch/traps.h +++ b/arch/x86/include/arch/traps.h @@ -59,6 +59,13 @@ extern xen_pv_start_info_t *pv_start_info; extern xen_pvh_start_info_t *pvh_start_info; extern shared_info_t shared_info; +/* + * Parameters for fine tuning the exec_user_*() behaviour. + */ +extern unsigned long exec_user_cs, exec_user_ss; +extern unsigned long exec_user_efl_and_mask; +extern unsigned long exec_user_efl_or_mask; + #endif /* XTF_X86_TRAPS_H */ /* diff --git a/arch/x86/traps.c b/arch/x86/traps.c index a09c8e2..8fee587 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -6,6 +6,16 @@ #include #include +/* + * Parameters for fine tuning the exec_user_*() behaviour. PV guests see the + * real interrupt flag, so mask it by default. + */ +unsigned long exec_user_cs = __USER_CS; +unsigned long exec_user_ss = __USER_DS; +unsigned long exec_user_efl_and_mask = + ~(IS_DEFINED(CONFIG_PV) ? X86_EFLAGS_IF : 0); +unsigned long exec_user_efl_or_mask; + bool (*xtf_unhandled_exception_hook)(struct cpu_regs *regs); /* diff --git a/tests/pv-iopl/Makefile b/tests/pv-iopl/Makefile index ec2f829..ce28b3a 100644 --- a/tests/pv-iopl/Makefile +++ b/tests/pv-iopl/Makefile @@ -6,6 +6,6 @@ TEST-ENVS := $(PV_ENVIRONMENTS) VARY-CFG := hypercall vmassist -obj-perenv += main.o asm.o +obj-perenv += main.o include $(ROOT)/build/gen.mk diff --git a/tests/pv-iopl/asm.S b/tests/pv-iopl/asm.S deleted file mode 100644 index ac1c85d..0000000 --- a/tests/pv-iopl/asm.S +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include - -ENTRY(exec_user_with_iopl) /* void (*fn)(void), unsigned int iopl */ - push %_ASM_BP - - /* Prepare to "call" exec_user_stub(). */ -#ifdef __i386__ - mov (1+1)*4(%esp), %eax /* Pass fn() in %eax */ -#endif - push $1f /* Fake return addr as if we'd called exec_user_stub(). */ - mov %_ASM_SP, %_ASM_BP /* Stash %esp for entry_ret_to_kernel(). */ - - /* Prepare an IRET frame. */ - push $__USER_DS /* SS */ - push $user_stack + PAGE_SIZE - /* ESP */ - pushf /* EFLAGS */ - - /* PV guests see the real interrupt flag. Clobber it. */ - andl $~(X86_EFLAGS_IOPL | X86_EFLAGS_IF), (%_ASM_SP) -#ifdef __i386__ - mov (5+2)*4(%esp), %ecx - shl $12, %ecx - or %ecx, (%esp) -#else - shl $12, %esi - or %esi, (%rsp) -#endif - - push $__USER_CS /* CS */ - push $exec_user_stub /* EIP */ - -#ifdef __x86_64__ - push $0 -#endif - jmp HYPERCALL_iret /* Drop to user privilege. */ - -1: /* entry_ret_to_kernel() returns here with a sensible stack. */ - pop %_ASM_BP - ret - -ENDFUNC(exec_user_with_iopl) - -/* - * Local variables: - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/tests/pv-iopl/main.c b/tests/pv-iopl/main.c index f6dc5ee..61b7194 100644 --- a/tests/pv-iopl/main.c +++ b/tests/pv-iopl/main.c @@ -44,11 +44,6 @@ const char test_title[] = "PV IOPL emulation"; bool test_wants_user_mappings = true; -/** - * Execute @p fn at user privilege, folding @p iopl into the iret frame. - */ -void exec_user_with_iopl(void (*fn)(void), unsigned int iopl); - /** Stub CLI instruction with @#GP fixup. */ static void stub_cli(void) { @@ -166,7 +161,8 @@ static void run_test(const struct test *t) /* Run insn in userspace. */ expect(seq->name, 1, t->should_fault(1, iopl)); - exec_user_with_iopl(seq->fn, iopl); + exec_user_void(seq->fn); + check(); } } @@ -219,7 +215,8 @@ static void vmassist_set_iopl(unsigned int iopl) * with the appropriate iopl set. Reuse the exec_user infrastructure to * issue the iret, and execute nothing interesting in user context. */ - exec_user_with_iopl(nop, iopl); + exec_user_efl_or_mask = iopl << 12; + exec_user_void(nop); } static bool vmassist_should_fault(bool user, unsigned int iopl)