diff options
-rw-r--r-- | arch/x86/entry/common.c | 50 |
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 | |||
291 | static 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 | /* |