aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/entry/common.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 66ccbd664d4c..b53e04d301a3 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -284,15 +284,40 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
284 user_enter(); 284 user_enter();
285} 285}
286 286
287#define SYSCALL_EXIT_WORK_FLAGS \
288 (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
289 _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT)
290
291static void syscall_slow_exit_work(struct pt_regs *regs, u32 cached_flags)
292{
293 bool step;
294
295 audit_syscall_exit(regs);
296
297 if (cached_flags & _TIF_SYSCALL_TRACEPOINT)
298 trace_sys_exit(regs, regs->ax);
299
300 /*
301 * If TIF_SYSCALL_EMU is set, we only get here because of
302 * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
303 * We already reported this syscall instruction in
304 * syscall_trace_enter().
305 */
306 step = unlikely(
307 (cached_flags & (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU))
308 == _TIF_SINGLESTEP);
309 if (step || cached_flags & _TIF_SYSCALL_TRACE)
310 tracehook_report_syscall_exit(regs, step);
311}
312
287/* 313/*
288 * Called with IRQs on and fully valid regs. Returns with IRQs off in a 314 * Called with IRQs on and fully valid regs. Returns with IRQs off in a
289 * state such that we can immediately switch to user mode. 315 * state such that we can immediately switch to user mode.
290 */ 316 */
291__visible void syscall_return_slowpath(struct pt_regs *regs) 317__visible inline void syscall_return_slowpath(struct pt_regs *regs)
292{ 318{
293 struct thread_info *ti = pt_regs_to_thread_info(regs); 319 struct thread_info *ti = pt_regs_to_thread_info(regs);
294 u32 cached_flags = READ_ONCE(ti->flags); 320 u32 cached_flags = READ_ONCE(ti->flags);
295 bool step;
296 321
297 CT_WARN_ON(ct_state() != CONTEXT_KERNEL); 322 CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
298 323
@@ -304,25 +329,8 @@ __visible void syscall_return_slowpath(struct pt_regs *regs)
304 * First do one-time work. If these work items are enabled, we 329 * First do one-time work. If these work items are enabled, we
305 * want to run them exactly once per syscall exit with IRQs on. 330 * want to run them exactly once per syscall exit with IRQs on.
306 */ 331 */
307 if (cached_flags & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | 332 if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
308 _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT)) { 333 syscall_slow_exit_work(regs, cached_flags);
309 audit_syscall_exit(regs);
310
311 if (cached_flags & _TIF_SYSCALL_TRACEPOINT)
312 trace_sys_exit(regs, regs->ax);
313
314 /*
315 * If TIF_SYSCALL_EMU is set, we only get here because of
316 * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
317 * We already reported this syscall instruction in
318 * syscall_trace_enter().
319 */
320 step = unlikely(
321 (cached_flags & (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU))
322 == _TIF_SINGLESTEP);
323 if (step || cached_flags & _TIF_SYSCALL_TRACE)
324 tracehook_report_syscall_exit(regs, step);
325 }
326 334
327#ifdef CONFIG_COMPAT 335#ifdef CONFIG_COMPAT
328 /* 336 /*