[PATCH 3/7][RFC] powerpc64, tracing: add function graph tracer with dynamic tracing
From: Steven Rostedt <rostedt@goodmis.org>
Date: 2009-02-12 01:15:47
Also in:
lkml
Subsystem:
function hooks (ftrace), linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Steven Rostedt, Masami Hiramatsu, Madhavan Srinivasan, Linus Torvalds
From: Steven Rostedt <redacted> This is the port of the function graph tracer to PowerPC with dynamic tracing. Signed-off-by: Steven Rostedt <redacted> --- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/entry_64.S | 8 ++++++- arch/powerpc/kernel/ftrace.c | 47 ++++++++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ca4647e..6e1ee1b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig@@ -111,7 +111,7 @@ config PPC select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER - select HAVE_FUNCTION_GRAPH_TRACER if !DYNAMIC_FTRACE && PPC64 + select HAVE_FUNCTION_GRAPH_TRACER if PPC64 select ARCH_WANT_OPTIONAL_GPIOLIB select HAVE_IDE select HAVE_IOREMAP_PROT
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index a32699e..9f61fd6 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S@@ -908,6 +908,12 @@ _GLOBAL(ftrace_caller) ftrace_call: bl ftrace_stub nop +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +.globl ftrace_graph_call +ftrace_graph_call: + b ftrace_graph_stub +_GLOBAL(ftrace_graph_stub) +#endif ld r0, 128(r1) mtlr r0 addi r1, r1, 112
@@ -946,7 +952,7 @@ _GLOBAL(ftrace_stub) #endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER -ftrace_graph_caller: +_GLOBAL(ftrace_graph_caller) /* load r4 with local address */ ld r4, 128(r1) subi r4, r4, MCOUNT_INSN_SIZE
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index c9b1547..7538b94 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c@@ -43,7 +43,8 @@ static unsigned char *ftrace_nop_replace(void) return (char *)&ftrace_nop; } -static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) +static unsigned char * +ftrace_call_replace(unsigned long ip, unsigned long addr, int link) { static unsigned int op;
@@ -55,8 +56,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) */ addr = GET_ADDR(addr); - /* Set to "bl addr" */ - op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc); + /* if (link) set op to 'bl' else 'b' */ + op = 0x48000000 | (link ? 1 : 0); + op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc); /* * No locking needed, this must be called via kstop_machine
@@ -344,7 +346,7 @@ int ftrace_make_nop(struct module *mod, */ if (test_24bit_addr(ip, addr)) { /* within range */ - old = ftrace_call_replace(ip, addr); + old = ftrace_call_replace(ip, addr, 1); new = ftrace_nop_replace(); return ftrace_modify_code(ip, old, new); }
@@ -484,7 +486,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) if (test_24bit_addr(ip, addr)) { /* within range */ old = ftrace_nop_replace(); - new = ftrace_call_replace(ip, addr); + new = ftrace_call_replace(ip, addr, 1); return ftrace_modify_code(ip, old, new); }
@@ -513,7 +515,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) int ret; memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); - new = ftrace_call_replace(ip, (unsigned long)func); + new = ftrace_call_replace(ip, (unsigned long)func, 1); ret = ftrace_modify_code(ip, old, new); return ret;
@@ -532,6 +534,39 @@ int __init ftrace_dyn_arch_init(void *data) #ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifdef CONFIG_DYNAMIC_FTRACE +extern void ftrace_graph_call(void); +extern void ftrace_graph_stub(void); + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned long ip = (unsigned long)(&ftrace_graph_call); + unsigned long addr = (unsigned long)(&ftrace_graph_caller); + unsigned long stub = (unsigned long)(&ftrace_graph_stub); + unsigned char old[MCOUNT_INSN_SIZE], *new; + + new = ftrace_call_replace(ip, stub, 0); + memcpy(old, new, MCOUNT_INSN_SIZE); + new = ftrace_call_replace(ip, addr, 0); + + return ftrace_modify_code(ip, old, new); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned long ip = (unsigned long)(&ftrace_graph_call); + unsigned long addr = (unsigned long)(&ftrace_graph_caller); + unsigned long stub = (unsigned long)(&ftrace_graph_stub); + unsigned char old[MCOUNT_INSN_SIZE], *new; + + new = ftrace_call_replace(ip, addr, 0); + memcpy(old, new, MCOUNT_INSN_SIZE); + new = ftrace_call_replace(ip, stub, 0); + + return ftrace_modify_code(ip, old, new); +} +#endif /* CONFIG_DYNAMIC_FTRACE */ + /* * Hook the return address and push it in the stack of return addrs * in current thread info.
--
1.5.6.5
--