Skip to content

Commit 4983e5d

Browse files
committed
x86/entry: Move irq flags tracing to prepare_exit_to_usermode()
This is another step towards more C-code and less convoluted ASM. Similar to the entry path, invoke the tracer before context tracking which might turn off RCU and invoke lockdep as the last step before going back to user space. Annotate the code sections in exit_to_user_mode() accordingly so objtool won't complain about the tracer invocation. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Acked-by: Peter Zijlstra <[email protected]> Acked-by: Andy Lutomirski <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent dd8e2d9 commit 4983e5d

File tree

4 files changed

+27
-22
lines changed

4 files changed

+27
-22
lines changed

arch/x86/entry/common.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,27 @@ static __always_inline void enter_from_user_mode(void)
7272
}
7373
#endif
7474

75-
static noinstr void exit_to_user_mode(void)
75+
/**
76+
* exit_to_user_mode - Fixup state when exiting to user mode
77+
*
78+
* Syscall exit enables interrupts, but the kernel state is interrupts
79+
* disabled when this is invoked. Also tell RCU about it.
80+
*
81+
* 1) Trace interrupts on state
82+
* 2) Invoke context tracking if enabled to adjust RCU state
83+
* 3) Clear CPU buffers if CPU is affected by MDS and the migitation is on.
84+
* 4) Tell lockdep that interrupts are enabled
85+
*/
86+
static __always_inline void exit_to_user_mode(void)
7687
{
88+
instrumentation_begin();
89+
trace_hardirqs_on_prepare();
90+
lockdep_hardirqs_on_prepare(CALLER_ADDR0);
91+
instrumentation_end();
92+
7793
user_enter_irqoff();
7894
mds_user_clear_cpu_buffers();
95+
lockdep_hardirqs_on(CALLER_ADDR0);
7996
}
8097

8198
static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)

arch/x86/entry/entry_32.S

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,7 @@ SYM_CODE_START(ret_from_fork)
817817
/* When we fork, we trace the syscall return in the child, too. */
818818
movl %esp, %eax
819819
call syscall_return_slowpath
820-
STACKLEAK_ERASE
821-
jmp restore_all
820+
jmp .Lsyscall_32_done
822821

823822
/* kernel thread */
824823
1: movl %edi, %eax
@@ -862,7 +861,7 @@ ret_from_intr:
862861
TRACE_IRQS_OFF
863862
movl %esp, %eax
864863
call prepare_exit_to_usermode
865-
jmp restore_all
864+
jmp restore_all_switch_stack
866865
SYM_CODE_END(ret_from_exception)
867866

868867
SYM_ENTRY(__begin_SYSENTER_singlestep_region, SYM_L_GLOBAL, SYM_A_NONE)
@@ -975,8 +974,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
975974

976975
STACKLEAK_ERASE
977976

978-
/* Opportunistic SYSEXIT */
979-
TRACE_IRQS_ON /* User mode traces as IRQs on. */
977+
/* Opportunistic SYSEXIT */
980978

981979
/*
982980
* Setup entry stack - we keep the pointer in %eax and do the
@@ -1079,11 +1077,9 @@ SYM_FUNC_START(entry_INT80_32)
10791077
movl %esp, %eax
10801078
call do_int80_syscall_32
10811079
.Lsyscall_32_done:
1082-
10831080
STACKLEAK_ERASE
10841081

1085-
restore_all:
1086-
TRACE_IRQS_ON
1082+
restore_all_switch_stack:
10871083
SWITCH_TO_ENTRY_STACK
10881084
CHECK_AND_APPLY_ESPFIX
10891085

arch/x86/entry/entry_64.S

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,6 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
172172
movq %rsp, %rsi
173173
call do_syscall_64 /* returns with IRQs disabled */
174174

175-
TRACE_IRQS_ON /* return enables interrupts */
176-
177175
/*
178176
* Try to use SYSRET instead of IRET if we're returning to
179177
* a completely clean 64-bit userspace context. If we're not,
@@ -342,7 +340,6 @@ SYM_CODE_START(ret_from_fork)
342340
UNWIND_HINT_REGS
343341
movq %rsp, %rdi
344342
call syscall_return_slowpath /* returns with IRQs disabled */
345-
TRACE_IRQS_ON /* user mode is traced as IRQS on */
346343
jmp swapgs_restore_regs_and_return_to_usermode
347344

348345
1:
@@ -620,7 +617,6 @@ ret_from_intr:
620617
.Lretint_user:
621618
mov %rsp,%rdi
622619
call prepare_exit_to_usermode
623-
TRACE_IRQS_ON
624620

625621
SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
626622
#ifdef CONFIG_DEBUG_ENTRY

arch/x86/entry/entry_64_compat.S

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ SYM_FUNC_START(entry_SYSENTER_compat)
132132
movq %rsp, %rdi
133133
call do_fast_syscall_32
134134
/* XEN PV guests always use IRET path */
135-
ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
136-
"jmp .Lsyscall_32_done", X86_FEATURE_XENPV
135+
ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
136+
"jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
137137
jmp sysret32_from_system_call
138138

139139
.Lsysenter_fix_flags:
@@ -244,8 +244,8 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL)
244244
movq %rsp, %rdi
245245
call do_fast_syscall_32
246246
/* XEN PV guests always use IRET path */
247-
ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
248-
"jmp .Lsyscall_32_done", X86_FEATURE_XENPV
247+
ALTERNATIVE "testl %eax, %eax; jz swapgs_restore_regs_and_return_to_usermode", \
248+
"jmp swapgs_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV
249249

250250
/* Opportunistic SYSRET */
251251
sysret32_from_system_call:
@@ -254,7 +254,7 @@ sysret32_from_system_call:
254254
* stack. So let's erase the thread stack right now.
255255
*/
256256
STACKLEAK_ERASE
257-
TRACE_IRQS_ON /* User mode traces as IRQs on. */
257+
258258
movq RBX(%rsp), %rbx /* pt_regs->rbx */
259259
movq RBP(%rsp), %rbp /* pt_regs->rbp */
260260
movq EFLAGS(%rsp), %r11 /* pt_regs->flags (in r11) */
@@ -393,9 +393,5 @@ SYM_CODE_START(entry_INT80_compat)
393393

394394
movq %rsp, %rdi
395395
call do_int80_syscall_32
396-
.Lsyscall_32_done:
397-
398-
/* Go back to user mode. */
399-
TRACE_IRQS_ON
400396
jmp swapgs_restore_regs_and_return_to_usermode
401397
SYM_CODE_END(entry_INT80_compat)

0 commit comments

Comments
 (0)