Skip to content

Commit d172125

Browse files
amlutoKAGA-KOKO
authored andcommitted
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 <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/fe62bef67eda7fac75b8f3dbafccf571dc4ece6b.1593191971.git.luto@kernel.org
1 parent c9c2615 commit d172125

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

arch/x86/entry/common.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,18 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
522522
(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0;
523523
#endif
524524
}
525+
526+
/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
527+
__visible noinstr long do_SYSENTER_32(struct pt_regs *regs)
528+
{
529+
/* SYSENTER loses RSP, but the vDSO saved it in RBP. */
530+
regs->sp = regs->bp;
531+
532+
/* SYSENTER clobbers EFLAGS.IF. Assume it was set in usermode. */
533+
regs->flags |= X86_EFLAGS_IF;
534+
535+
return do_fast_syscall_32(regs);
536+
}
525537
#endif
526538

527539
SYSCALL_DEFINE0(ni_syscall)

arch/x86/entry/entry_32.S

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -933,9 +933,8 @@ SYM_FUNC_START(entry_SYSENTER_32)
933933

934934
.Lsysenter_past_esp:
935935
pushl $__USER_DS /* pt_regs->ss */
936-
pushl %ebp /* pt_regs->sp (stashed in bp) */
936+
pushl $0 /* pt_regs->sp (placeholder) */
937937
pushfl /* pt_regs->flags (except IF = 0) */
938-
orl $X86_EFLAGS_IF, (%esp) /* Fix IF */
939938
pushl $__USER_CS /* pt_regs->cs */
940939
pushl $0 /* pt_regs->ip = 0 (placeholder) */
941940
pushl %eax /* pt_regs->orig_ax */
@@ -965,7 +964,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
965964
.Lsysenter_flags_fixed:
966965

967966
movl %esp, %eax
968-
call do_fast_syscall_32
967+
call do_SYSENTER_32
969968
/* XEN PV guests always use IRET path */
970969
ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
971970
"jmp .Lsyscall_32_done", X86_FEATURE_XENPV

arch/x86/entry/entry_64_compat.S

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,15 @@ SYM_CODE_START(entry_SYSENTER_compat)
6868

6969
/* Construct struct pt_regs on stack */
7070
pushq $__USER32_DS /* pt_regs->ss */
71-
pushq %rbp /* pt_regs->sp (stashed in bp) */
71+
pushq $0 /* pt_regs->sp = 0 (placeholder) */
7272

7373
/*
7474
* Push flags. This is nasty. First, interrupts are currently
75-
* off, but we need pt_regs->flags to have IF set. Second, even
76-
* if TF was set when SYSENTER started, it's clear by now. We fix
77-
* that later using TIF_SINGLESTEP.
75+
* off, but we need pt_regs->flags to have IF set. Second, if TS
76+
* was set in usermode, it's still set, and we're singlestepping
77+
* through this code. do_SYSENTER_32() will fix up IF.
7878
*/
7979
pushfq /* pt_regs->flags (except IF = 0) */
80-
orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */
8180
pushq $__USER32_CS /* pt_regs->cs */
8281
pushq $0 /* pt_regs->ip = 0 (placeholder) */
8382
pushq %rax /* pt_regs->orig_ax */
@@ -135,7 +134,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
135134
.Lsysenter_flags_fixed:
136135

137136
movq %rsp, %rdi
138-
call do_fast_syscall_32
137+
call do_SYSENTER_32
139138
/* XEN PV guests always use IRET path */
140139
ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
141140
"jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV

0 commit comments

Comments
 (0)