summaryrefslogtreecommitdiff
path: root/arch/tile/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/ptrace.c')
-rw-r--r--arch/tile/kernel/ptrace.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index de98c6ddf136..f84eed8243da 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -22,6 +22,7 @@
#include <linux/regset.h>
#include <linux/elf.h>
#include <linux/tracehook.h>
+#include <linux/context_tracking.h>
#include <asm/traps.h>
#include <arch/chip.h>
@@ -252,12 +253,21 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
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 (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];
@@ -268,6 +278,12 @@ 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
@@ -303,5 +319,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs)
/* Handle synthetic interrupt delivered only by the simulator. */
void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
{
+ enum ctx_state prev_state = exception_enter();
send_sigtrap(current, regs);
+ exception_exit(prev_state);
}