x86/entry: Move SYSENTER's regs->sp and regs->flags fixups into C
The SYSENTER asm (32-bit and compat) contains fixups for regs->sp and regs->flags. Move the fixups into C and fix some comments while at it. This is a valid cleanup all by itself, and it also simplifies the subsequent patch that will fix Xen PV SYSENTER. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/fe62bef67eda7fac75b8f3dbafccf571dc4ece6b.1593191971.git.luto@kernel.org
This commit is contained in:
Родитель
c9c26150e6
Коммит
d1721250f3
|
@ -522,6 +522,18 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
|
|||
(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
|
||||
__visible noinstr long do_SYSENTER_32(struct pt_regs *regs)
|
||||
{
|
||||
/* SYSENTER loses RSP, but the vDSO saved it in RBP. */
|
||||
regs->sp = regs->bp;
|
||||
|
||||
/* SYSENTER clobbers EFLAGS.IF. Assume it was set in usermode. */
|
||||
regs->flags |= X86_EFLAGS_IF;
|
||||
|
||||
return do_fast_syscall_32(regs);
|
||||
}
|
||||
#endif
|
||||
|
||||
SYSCALL_DEFINE0(ni_syscall)
|
||||
|
|
|
@ -933,9 +933,8 @@ SYM_FUNC_START(entry_SYSENTER_32)
|
|||
|
||||
.Lsysenter_past_esp:
|
||||
pushl $__USER_DS /* pt_regs->ss */
|
||||
pushl %ebp /* pt_regs->sp (stashed in bp) */
|
||||
pushl $0 /* pt_regs->sp (placeholder) */
|
||||
pushfl /* pt_regs->flags (except IF = 0) */
|
||||
orl $X86_EFLAGS_IF, (%esp) /* Fix IF */
|
||||
pushl $__USER_CS /* pt_regs->cs */
|
||||
pushl $0 /* pt_regs->ip = 0 (placeholder) */
|
||||
pushl %eax /* pt_regs->orig_ax */
|
||||
|
@ -965,7 +964,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
|
|||
.Lsysenter_flags_fixed:
|
||||
|
||||
movl %esp, %eax
|
||||
call do_fast_syscall_32
|
||||
call do_SYSENTER_32
|
||||
/* XEN PV guests always use IRET path */
|
||||
ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
|
||||
"jmp .Lsyscall_32_done", X86_FEATURE_XENPV
|
||||
|
|
|
@ -68,16 +68,15 @@ SYM_CODE_START(entry_SYSENTER_compat)
|
|||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq $__USER32_DS /* pt_regs->ss */
|
||||
pushq %rbp /* pt_regs->sp (stashed in bp) */
|
||||
pushq $0 /* pt_regs->sp = 0 (placeholder) */
|
||||
|
||||
/*
|
||||
* Push flags. This is nasty. First, interrupts are currently
|
||||
* off, but we need pt_regs->flags to have IF set. Second, even
|
||||
* if TF was set when SYSENTER started, it's clear by now. We fix
|
||||
* that later using TIF_SINGLESTEP.
|
||||
* off, but we need pt_regs->flags to have IF set. Second, if TS
|
||||
* was set in usermode, it's still set, and we're singlestepping
|
||||
* through this code. do_SYSENTER_32() will fix up IF.
|
||||
*/
|
||||
pushfq /* pt_regs->flags (except IF = 0) */
|
||||
orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */
|
||||
pushq $__USER32_CS /* pt_regs->cs */
|
||||
pushq $0 /* pt_regs->ip = 0 (placeholder) */
|
||||
pushq %rax /* pt_regs->orig_ax */
|
||||
|
@ -135,7 +134,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
|
|||
.Lsysenter_flags_fixed:
|
||||
|
||||
movq %rsp, %rdi
|
||||
call do_fast_syscall_32
|
||||
call do_SYSENTER_32
|
||||
/* XEN PV guests always use IRET path */
|
||||
ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
|
||||
"jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
|
||||
|
|
Загрузка…
Ссылка в новой задаче