Skip to content

Commit d680194

Browse files
svens-s390KAGA-KOKO
authored andcommitted
entry: Move exit to usermode functions to header file
To allow inlining, move exit_to_user_mode() to entry-common.h. Signed-off-by: Sven Schnelle <svens@linux.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20231218074520.1998026-2-svens@linux.ibm.com
1 parent 98b1cc8 commit d680194

2 files changed

Lines changed: 61 additions & 44 deletions

File tree

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
@@ -123,29 +123,16 @@ noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
123123
instrumentation_end();
124124
}
125125

126-
/* See comment for exit_to_user_mode() in entry-common.h */
127-
static __always_inline void __exit_to_user_mode(void)
128-
{
129-
instrumentation_begin();
130-
trace_hardirqs_on_prepare();
131-
lockdep_hardirqs_on_prepare();
132-
instrumentation_end();
133-
134-
user_enter_irqoff();
135-
arch_exit_to_user_mode();
136-
lockdep_hardirqs_on(CALLER_ADDR0);
137-
}
138-
139-
void noinstr exit_to_user_mode(void)
140-
{
141-
__exit_to_user_mode();
142-
}
143-
144126
/* Workaround to allow gradual conversion of architecture code */
145127
void __weak arch_do_signal_or_restart(struct pt_regs *regs) { }
146128

147-
static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
148-
unsigned long ti_work)
129+
/**
130+
* exit_to_user_mode_loop - do any pending work before leaving to user space
131+
* @regs: Pointer to pt_regs on entry stack
132+
* @ti_work: TIF work flags as read by the caller
133+
*/
134+
__always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
135+
unsigned long ti_work)
149136
{
150137
/*
151138
* Before returning to user space ensure that all pending work
@@ -190,27 +177,6 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
190177
return ti_work;
191178
}
192179

193-
static void exit_to_user_mode_prepare(struct pt_regs *regs)
194-
{
195-
unsigned long ti_work;
196-
197-
lockdep_assert_irqs_disabled();
198-
199-
/* Flush pending rcuog wakeup before the last need_resched() check */
200-
tick_nohz_user_enter_prepare();
201-
202-
ti_work = read_thread_flags();
203-
if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
204-
ti_work = exit_to_user_mode_loop(regs, ti_work);
205-
206-
arch_exit_to_user_mode_prepare(regs, ti_work);
207-
208-
/* Ensure that kernel state is sane for a return to userspace */
209-
kmap_assert_nomap();
210-
lockdep_assert_irqs_disabled();
211-
lockdep_sys_exit();
212-
}
213-
214180
/*
215181
* If SYSCALL_EMU is set, then the only reason to report is when
216182
* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall
@@ -295,7 +261,7 @@ __visible noinstr void syscall_exit_to_user_mode(struct pt_regs *regs)
295261
instrumentation_begin();
296262
__syscall_exit_to_user_mode_work(regs);
297263
instrumentation_end();
298-
__exit_to_user_mode();
264+
exit_to_user_mode();
299265
}
300266

301267
noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
@@ -308,7 +274,7 @@ noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
308274
instrumentation_begin();
309275
exit_to_user_mode_prepare(regs);
310276
instrumentation_end();
311-
__exit_to_user_mode();
277+
exit_to_user_mode();
312278
}
313279

314280
noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)

0 commit comments

Comments
 (0)