aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/kernel/entry_64.S8
-rw-r--r--arch/powerpc/kernel/ftrace.c47
3 files changed, 49 insertions, 8 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index e122d241f17d..b298fb0703de 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -111,7 +111,7 @@ config PPC
111 select HAVE_FTRACE_MCOUNT_RECORD 111 select HAVE_FTRACE_MCOUNT_RECORD
112 select HAVE_DYNAMIC_FTRACE 112 select HAVE_DYNAMIC_FTRACE
113 select HAVE_FUNCTION_TRACER 113 select HAVE_FUNCTION_TRACER
114 select HAVE_FUNCTION_GRAPH_TRACER if !DYNAMIC_FTRACE && PPC64 114 select HAVE_FUNCTION_GRAPH_TRACER if PPC64
115 select ARCH_WANT_OPTIONAL_GPIOLIB 115 select ARCH_WANT_OPTIONAL_GPIOLIB
116 select HAVE_IDE 116 select HAVE_IDE
117 select HAVE_IOREMAP_PROT 117 select HAVE_IOREMAP_PROT
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index a32699e74c3c..9f61fd61f277 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -908,6 +908,12 @@ _GLOBAL(ftrace_caller)
908ftrace_call: 908ftrace_call:
909 bl ftrace_stub 909 bl ftrace_stub
910 nop 910 nop
911#ifdef CONFIG_FUNCTION_GRAPH_TRACER
912.globl ftrace_graph_call
913ftrace_graph_call:
914 b ftrace_graph_stub
915_GLOBAL(ftrace_graph_stub)
916#endif
911 ld r0, 128(r1) 917 ld r0, 128(r1)
912 mtlr r0 918 mtlr r0
913 addi r1, r1, 112 919 addi r1, r1, 112
@@ -946,7 +952,7 @@ _GLOBAL(ftrace_stub)
946#endif /* CONFIG_DYNAMIC_FTRACE */ 952#endif /* CONFIG_DYNAMIC_FTRACE */
947 953
948#ifdef CONFIG_FUNCTION_GRAPH_TRACER 954#ifdef CONFIG_FUNCTION_GRAPH_TRACER
949ftrace_graph_caller: 955_GLOBAL(ftrace_graph_caller)
950 /* load r4 with local address */ 956 /* load r4 with local address */
951 ld r4, 128(r1) 957 ld r4, 128(r1)
952 subi r4, r4, MCOUNT_INSN_SIZE 958 subi r4, r4, MCOUNT_INSN_SIZE
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.