aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-10 00:10:27 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-02-22 18:48:53 -0500
commit6794c78243bfda020ab184d6d578944f8e90d26c (patch)
treee697b43e4b757723ed9798c9666b759d9e29ca12 /arch/powerpc/kernel/ftrace.c
parent17be5b3ddf71d980f67fc826e49b00cd2afd724d (diff)
powerpc64: port of the function graph tracer
This is a port of the function graph tracer that was written by Frederic Weisbecker for the x86. This only works for PPC64 at the moment and only for static tracing. PPC32 and dynamic function graph tracing support will come later. The trace produces a visual calling of functions: # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 0) 2.224 us | } 0) ! 271.024 us | } 0) ! 320.080 us | } 0) ! 324.656 us | } 0) ! 329.136 us | } 0) | .put_prev_task_fair() { 0) | .update_curr() { 0) 2.240 us | .update_min_vruntime(); 0) 6.512 us | } 0) 2.528 us | .__enqueue_entity(); 0) + 15.536 us | } 0) | .pick_next_task_fair() { 0) 2.032 us | .__pick_next_entity(); 0) 2.064 us | .__clear_buddies(); 0) | .set_next_entity() { 0) 2.672 us | .__dequeue_entity(); 0) 6.864 us | } Geoff Lavand tested on PS3. Tested-by: Geoff Levand <geoffrey.levand@am.sony.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/ftrace.c')
-rw-r--r--arch/powerpc/kernel/ftrace.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 4112175183d3..c9b1547f65a5 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -5,6 +5,9 @@
5 * 5 *
6 * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box. 6 * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
7 * 7 *
8 * Added function graph tracer code, taken from x86 that was written
9 * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
10 *
8 */ 11 */
9 12
10#include <linux/spinlock.h> 13#include <linux/spinlock.h>
@@ -20,8 +23,6 @@
20#include <asm/code-patching.h> 23#include <asm/code-patching.h>
21#include <asm/ftrace.h> 24#include <asm/ftrace.h>
22 25
23static unsigned int ftrace_nop = PPC_NOP_INSTR;
24
25#ifdef CONFIG_PPC32 26#ifdef CONFIG_PPC32
26# define GET_ADDR(addr) addr 27# define GET_ADDR(addr) addr
27#else 28#else
@@ -29,6 +30,8 @@ static unsigned int ftrace_nop = PPC_NOP_INSTR;
29# define GET_ADDR(addr) (*(unsigned long *)addr) 30# define GET_ADDR(addr) (*(unsigned long *)addr)
30#endif 31#endif
31 32
33#ifdef CONFIG_DYNAMIC_FTRACE
34static unsigned int ftrace_nop = PPC_NOP_INSTR;
32 35
33static unsigned int ftrace_calc_offset(long ip, long addr) 36static unsigned int ftrace_calc_offset(long ip, long addr)
34{ 37{
@@ -525,3 +528,75 @@ int __init ftrace_dyn_arch_init(void *data)
525 528
526 return 0; 529 return 0;
527} 530}
531#endif /* CONFIG_DYNAMIC_FTRACE */
532
533#ifdef CONFIG_FUNCTION_GRAPH_TRACER
534
535/*
536 * Hook the return address and push it in the stack of return addrs
537 * in current thread info.
538 */
539void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
540{
541 unsigned long old;
542 unsigned long long calltime;
543 int faulted;
544 struct ftrace_graph_ent trace;
545 unsigned long return_hooker = (unsigned long)
546 &return_to_handler;
547
548 if (unlikely(atomic_read(&current->tracing_graph_pause)))
549 return;
550
551 return_hooker = GET_ADDR(return_hooker);
552
553 /*
554 * Protect against fault, even if it shouldn't
555 * happen. This tool is too much intrusive to
556 * ignore such a protection.
557 */
558 asm volatile(
559 "1: " PPC_LL "%[old], 0(%[parent])\n"
560 "2: " PPC_STL "%[return_hooker], 0(%[parent])\n"
561 " li %[faulted], 0\n"
562 "3:"
563
564 ".section .fixup, \"ax\"\n"
565 "4: li %[faulted], 1\n"
566 " b 3b\n"
567 ".previous\n"
568
569 ".section __ex_table,\"a\"\n"
570 PPC_LONG_ALIGN "\n"
571 PPC_LONG "1b,4b\n"
572 PPC_LONG "2b,4b\n"
573 ".previous"
574
575 : [old] "=r" (old), [faulted] "=r" (faulted)
576 : [parent] "r" (parent), [return_hooker] "r" (return_hooker)
577 : "memory"
578 );
579
580 if (unlikely(faulted)) {
581 ftrace_graph_stop();
582 WARN_ON(1);
583 return;
584 }
585
586 calltime = cpu_clock(raw_smp_processor_id());
587
588 if (ftrace_push_return_trace(old, calltime,
589 self_addr, &trace.depth) == -EBUSY) {
590 *parent = old;
591 return;
592 }
593
594 trace.func = self_addr;
595
596 /* Only trace if the calling function expects to */
597 if (!ftrace_graph_entry(&trace)) {
598 current->curr_ret_stack--;
599 *parent = old;
600 }
601}
602#endif /* CONFIG_FUNCTION_GRAPH_TRACER */