--- zzzz-none-000/linux-3.10.107/arch/tile/kernel/ptrace.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/tile/kernel/ptrace.c 2021-02-04 17:41:59.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -252,12 +253,24 @@ int do_syscall_trace_enter(struct pt_regs *regs) { - if (test_thread_flag(TIF_SYSCALL_TRACE)) { + u32 work = ACCESS_ONCE(current_thread_info()->flags); + + /* + * If TIF_NOHZ is set, we are required to call user_exit() before + * doing anything that could touch RCU. + */ + if (work & _TIF_NOHZ) + user_exit(); + + if (secure_computing() == -1) + return -1; + + if (work & _TIF_SYSCALL_TRACE) { if (tracehook_report_syscall_entry(regs)) regs->regs[TREG_SYSCALL_NR] = -1; } - if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + if (work & _TIF_SYSCALL_TRACEPOINT) trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]); return regs->regs[TREG_SYSCALL_NR]; @@ -265,6 +278,27 @@ void do_syscall_trace_exit(struct pt_regs *regs) { + long errno; + + /* + * We may come here right after calling schedule_user() + * in which case we can be in RCU user mode. + */ + user_exit(); + + /* + * The standard tile calling convention returns the value (or negative + * errno) in r0, and zero (or positive errno) in r1. + * It saves a couple of cycles on the hot path to do this work in + * registers only as we return, rather than updating the in-memory + * struct ptregs. + */ + errno = (long) regs->regs[0]; + if (errno < 0 && errno > -4096) + regs->regs[1] = -errno; + else + regs->regs[1] = 0; + if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); @@ -272,7 +306,7 @@ trace_sys_exit(regs, regs->regs[0]); } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs) { struct siginfo info; @@ -288,5 +322,7 @@ /* Handle synthetic interrupt delivered only by the simulator. */ void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num) { - send_sigtrap(current, regs, fault_num); + enum ctx_state prev_state = exception_enter(); + send_sigtrap(current, regs); + exception_exit(prev_state); }