diff --git a/arch/x86/entry.S b/arch/x86/entry.S index 19698463..9985ed44 100644 --- a/arch/x86/entry.S +++ b/arch/x86/entry.S @@ -60,6 +60,14 @@ SET_CR3 user_cr3 .endm +.macro WRITE_MSR msr_reg value + mov \msr_reg, %_ASM_CX + mov \value, %_ASM_AX + mov \value, %_ASM_DX + shr $32, %_ASM_DX + wrmsr +.endm + .macro exception_handler sym vec has_error_code ENTRY(entry_\sym) enter_from_usermode @@ -173,9 +181,15 @@ ENTRY(enter_usermode) PUSHF /* Save stack pointer onto per-cpu */ - mov %_ASM_DX, %gs:(usermode_private) + mov %_ASM_SP, %gs:usermode_private - syscall_to_usermode + /* provide sysenter the kernel stack to be used */ + push %_ASM_DX + WRITE_MSR $MSR_SYSENTER_ESP, %_ASM_SP + pop %_ASM_DX + + /* Move to user stack */ + mov %_ASM_DX, %_ASM_SP /* SS + SP */ push $__USER_DS @@ -189,6 +203,8 @@ ENTRY(enter_usermode) /* CS + IP */ push $__USER_CS push $usermode_stub + + enter_to_usermode IRET END_FUNC(enter_usermode) diff --git a/common/usermode.c b/common/usermode.c index d39dae4d..b78031de 100644 --- a/common/usermode.c +++ b/common/usermode.c @@ -99,7 +99,7 @@ static void init_syscall(void) { static void init_sysenter(void) { wrmsr(MSR_SYSENTER_CS, _ul(__KERN_CS)); - wrmsr(MSR_SYSENTER_ESP, _ul(get_free_page_top(GFP_KERNEL | GFP_USER))); + wrmsr(MSR_SYSENTER_ESP, _ul(0)); /* configure the stack on enter_usermode instead */ wrmsr(MSR_SYSENTER_EIP, _ul(&sysenter_handler_entry)); }