aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-11 01:19:54 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-02-22 18:48:54 -0500
commit465428884765b43d642a967915e16c6c7cacbe8e (patch)
treebee656decba5598493b920efab53ec4ca95afa08 /arch/powerpc/kernel/ftrace.c
parent6794c78243bfda020ab184d6d578944f8e90d26c (diff)
powerpc64, tracing: add function graph tracer with dynamic tracing
This is the port of the function graph tracer to PowerPC with dynamic tracing. 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.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index c9b1547f65a5..7538b944fa52 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -43,7 +43,8 @@ static unsigned char *ftrace_nop_replace(void)
43 return (char *)&ftrace_nop; 43 return (char *)&ftrace_nop;
44} 44}
45 45
46static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) 46static unsigned char *
47ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
47{ 48{
48 static unsigned int op; 49 static unsigned int op;
49 50
@@ -55,8 +56,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
55 */ 56 */
56 addr = GET_ADDR(addr); 57 addr = GET_ADDR(addr);
57 58
58 /* Set to "bl addr" */ 59 /* if (link) set op to 'bl' else 'b' */
59 op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc); 60 op = 0x48000000 | (link ? 1 : 0);
61 op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc);
60 62
61 /* 63 /*
62 * No locking needed, this must be called via kstop_machine 64 * No locking needed, this must be called via kstop_machine
@@ -344,7 +346,7 @@ int ftrace_make_nop(struct module *mod,
344 */ 346 */
345 if (test_24bit_addr(ip, addr)) { 347 if (test_24bit_addr(ip, addr)) {
346 /* within range */ 348 /* within range */
347 old = ftrace_call_replace(ip, addr); 349 old = ftrace_call_replace(ip, addr, 1);
348 new = ftrace_nop_replace(); 350 new = ftrace_nop_replace();
349 return ftrace_modify_code(ip, old, new); 351 return ftrace_modify_code(ip, old, new);
350 } 352 }
@@ -484,7 +486,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
484 if (test_24bit_addr(ip, addr)) { 486 if (test_24bit_addr(ip, addr)) {
485 /* within range */ 487 /* within range */
486 old = ftrace_nop_replace(); 488 old = ftrace_nop_replace();
487 new = ftrace_call_replace(ip, addr); 489 new = ftrace_call_replace(ip, addr, 1);
488 return ftrace_modify_code(ip, old, new); 490 return ftrace_modify_code(ip, old, new);
489 } 491 }
490 492
@@ -513,7 +515,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
513 int ret; 515 int ret;
514 516
515 memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); 517 memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
516 new = ftrace_call_replace(ip, (unsigned long)func); 518 new = ftrace_call_replace(ip, (unsigned long)func, 1);
517 ret = ftrace_modify_code(ip, old, new); 519 ret = ftrace_modify_code(ip, old, new);
518 520
519 return ret; 521 return ret;
@@ -532,6 +534,39 @@ int __init ftrace_dyn_arch_init(void *data)
532 534
533#ifdef CONFIG_FUNCTION_GRAPH_TRACER 535#ifdef CONFIG_FUNCTION_GRAPH_TRACER
534 536
537#ifdef CONFIG_DYNAMIC_FTRACE
538extern void ftrace_graph_call(void);
539extern void ftrace_graph_stub(void);
540
541int ftrace_enable_ftrace_graph_caller(void)
542{
543 unsigned long ip = (unsigned long)(&ftrace_graph_call);
544 unsigned long addr = (unsigned long)(&ftrace_graph_caller);
545 unsigned long stub = (unsigned long)(&ftrace_graph_stub);
546 unsigned char old[MCOUNT_INSN_SIZE], *new;
547
548 new = ftrace_call_replace(ip, stub, 0);
549 memcpy(old, new, MCOUNT_INSN_SIZE);
550 new = ftrace_call_replace(ip, addr, 0);
551
552 return ftrace_modify_code(ip, old, new);
553}
554
555int ftrace_disable_ftrace_graph_caller(void)
556{
557 unsigned long ip = (unsigned long)(&ftrace_graph_call);
558 unsigned long addr = (unsigned long)(&ftrace_graph_caller);
559 unsigned long stub = (unsigned long)(&ftrace_graph_stub);
560 unsigned char old[MCOUNT_INSN_SIZE], *new;
561
562 new = ftrace_call_replace(ip, addr, 0);
563 memcpy(old, new, MCOUNT_INSN_SIZE);
564 new = ftrace_call_replace(ip, stub, 0);
565
566 return ftrace_modify_code(ip, old, new);
567}
568#endif /* CONFIG_DYNAMIC_FTRACE */
569
535/* 570/*
536 * Hook the return address and push it in the stack of return addrs 571 * Hook the return address and push it in the stack of return addrs
537 * in current thread info. 572 * in current thread info.