diff options
author | Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> | 2017-06-01 06:48:15 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-06-16 05:49:43 -0400 |
commit | a9f8553e935f26cb5447f67e280946b0923cd2dc (patch) | |
tree | 50d94ef8c3ffe08b34b9ae3e9993c140733b1a61 | |
parent | a093c92dc7f96a15de98ec8cfe38e6f7610a5969 (diff) |
powerpc/kprobes: Pause function_graph tracing during jprobes handling
This fixes a crash when function_graph and jprobes are used together.
This is essentially commit 237d28db036e ("ftrace/jprobes/x86: Fix
conflict between jprobes and function graph tracing"), but for powerpc.
Jprobes breaks function_graph tracing since the jprobe hook needs to use
jprobe_return(), which never returns back to the hook, but instead to
the original jprobe'd function. The solution is to momentarily pause
function_graph tracing before invoking the jprobe hook and re-enable it
when returning back to the original jprobe'd function.
Fixes: 6794c78243bf ("powerpc64: port of the function graph tracer")
Cc: stable@vger.kernel.org # v2.6.30+
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index fc4343514bed..5075a4d6f1d7 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -617,6 +617,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
617 | regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); | 617 | regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); |
618 | #endif | 618 | #endif |
619 | 619 | ||
620 | /* | ||
621 | * jprobes use jprobe_return() which skips the normal return | ||
622 | * path of the function, and this messes up the accounting of the | ||
623 | * function graph tracer. | ||
624 | * | ||
625 | * Pause function graph tracing while performing the jprobe function. | ||
626 | */ | ||
627 | pause_graph_tracing(); | ||
628 | |||
620 | return 1; | 629 | return 1; |
621 | } | 630 | } |
622 | NOKPROBE_SYMBOL(setjmp_pre_handler); | 631 | NOKPROBE_SYMBOL(setjmp_pre_handler); |
@@ -642,6 +651,8 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
642 | * saved regs... | 651 | * saved regs... |
643 | */ | 652 | */ |
644 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); | 653 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); |
654 | /* It's OK to start function graph tracing again */ | ||
655 | unpause_graph_tracing(); | ||
645 | preempt_enable_no_resched(); | 656 | preempt_enable_no_resched(); |
646 | return 1; | 657 | return 1; |
647 | } | 658 | } |