Skip to content

Commit f283d30

Browse files
svens-s390Avenger-285714
authored andcommitted
entry: Move exit to usermode functions to header file
mainline inclusion from mainline-v6.8-rc1 category: performance To allow inlining, move exit_to_user_mode() to entry-common.h. Signed-off-by: Sven Schnelle <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected] (cherry picked from commit d680194) Signed-off-by: Wentao Guan <[email protected]>
1 parent 6bcb3f7 commit f283d30

File tree

2 files changed

+61
-44
lines changed

2 files changed

+61
-44
lines changed

include/linux/entry-common.h

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#include <linux/syscalls.h>
88
#include <linux/seccomp.h>
99
#include <linux/sched.h>
10+
#include <linux/context_tracking.h>
11+
#include <linux/livepatch.h>
12+
#include <linux/resume_user_mode.h>
13+
#include <linux/tick.h>
1014

1115
#include <asm/entry-common.h>
1216

@@ -258,6 +262,43 @@ static __always_inline void arch_exit_to_user_mode(void) { }
258262
*/
259263
void arch_do_signal_or_restart(struct pt_regs *regs);
260264

265+
/**
266+
* exit_to_user_mode_loop - do any pending work before leaving to user space
267+
*/
268+
unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
269+
unsigned long ti_work);
270+
271+
/**
272+
* exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required
273+
* @regs: Pointer to pt_regs on entry stack
274+
*
275+
* 1) check that interrupts are disabled
276+
* 2) call tick_nohz_user_enter_prepare()
277+
* 3) call exit_to_user_mode_loop() if any flags from
278+
* EXIT_TO_USER_MODE_WORK are set
279+
* 4) check that interrupts are still disabled
280+
*/
281+
static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs)
282+
{
283+
unsigned long ti_work;
284+
285+
lockdep_assert_irqs_disabled();
286+
287+
/* Flush pending rcuog wakeup before the last need_resched() check */
288+
tick_nohz_user_enter_prepare();
289+
290+
ti_work = read_thread_flags();
291+
if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
292+
ti_work = exit_to_user_mode_loop(regs, ti_work);
293+
294+
arch_exit_to_user_mode_prepare(regs, ti_work);
295+
296+
/* Ensure that kernel state is sane for a return to userspace */
297+
kmap_assert_nomap();
298+
lockdep_assert_irqs_disabled();
299+
lockdep_sys_exit();
300+
}
301+
261302
/**
262303
* exit_to_user_mode - Fixup state when exiting to user mode
263304
*
@@ -276,7 +317,17 @@ void arch_do_signal_or_restart(struct pt_regs *regs);
276317
* non-instrumentable.
277318
* The caller has to invoke syscall_exit_to_user_mode_work() before this.
278319
*/
279-
void exit_to_user_mode(void);
320+
static __always_inline void exit_to_user_mode(void)
321+
{
322+
instrumentation_begin();
323+
trace_hardirqs_on_prepare();
324+
lockdep_hardirqs_on_prepare();
325+
instrumentation_end();
326+
327+
user_enter_irqoff();
328+
arch_exit_to_user_mode();
329+
lockdep_hardirqs_on(CALLER_ADDR0);
330+
}
280331

281332
/**
282333
* syscall_exit_to_user_mode_work - Handle work before returning to user mode

kernel/entry/common.c

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -129,29 +129,16 @@ noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
129129
instrumentation_end();
130130
}
131131

132-
/* See comment for exit_to_user_mode() in entry-common.h */
133-
static __always_inline void __exit_to_user_mode(void)
134-
{
135-
instrumentation_begin();
136-
trace_hardirqs_on_prepare();
137-
lockdep_hardirqs_on_prepare();
138-
instrumentation_end();
139-
140-
user_enter_irqoff();
141-
arch_exit_to_user_mode();
142-
lockdep_hardirqs_on(CALLER_ADDR0);
143-
}
144-
145-
void noinstr exit_to_user_mode(void)
146-
{
147-
__exit_to_user_mode();
148-
}
149-
150132
/* Workaround to allow gradual conversion of architecture code */
151133
void __weak arch_do_signal_or_restart(struct pt_regs *regs) { }
152134

153-
static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
154-
unsigned long ti_work)
135+
/**
136+
* exit_to_user_mode_loop - do any pending work before leaving to user space
137+
* @regs: Pointer to pt_regs on entry stack
138+
* @ti_work: TIF work flags as read by the caller
139+
*/
140+
__always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
141+
unsigned long ti_work)
155142
{
156143
/*
157144
* Before returning to user space ensure that all pending work
@@ -196,27 +183,6 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
196183
return ti_work;
197184
}
198185

199-
static void exit_to_user_mode_prepare(struct pt_regs *regs)
200-
{
201-
unsigned long ti_work;
202-
203-
lockdep_assert_irqs_disabled();
204-
205-
/* Flush pending rcuog wakeup before the last need_resched() check */
206-
tick_nohz_user_enter_prepare();
207-
208-
ti_work = read_thread_flags();
209-
if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
210-
ti_work = exit_to_user_mode_loop(regs, ti_work);
211-
212-
arch_exit_to_user_mode_prepare(regs, ti_work);
213-
214-
/* Ensure that kernel state is sane for a return to userspace */
215-
kmap_assert_nomap();
216-
lockdep_assert_irqs_disabled();
217-
lockdep_sys_exit();
218-
}
219-
220186
/*
221187
* If SYSCALL_EMU is set, then the only reason to report is when
222188
* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall
@@ -301,7 +267,7 @@ __visible noinstr void syscall_exit_to_user_mode(struct pt_regs *regs)
301267
instrumentation_begin();
302268
__syscall_exit_to_user_mode_work(regs);
303269
instrumentation_end();
304-
__exit_to_user_mode();
270+
exit_to_user_mode();
305271
}
306272

307273
noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
@@ -314,7 +280,7 @@ noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
314280
instrumentation_begin();
315281
exit_to_user_mode_prepare(regs);
316282
instrumentation_end();
317-
__exit_to_user_mode();
283+
exit_to_user_mode();
318284
}
319285

320286
noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)

0 commit comments

Comments
 (0)