Commit 46542888 authored by Steven Rostedt's avatar Steven Rostedt Committed by Benjamin Herrenschmidt

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: default avatarGeoff Levand <geoffrey.levand@am.sony.com>
Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 6794c782
...@@ -111,7 +111,7 @@ config PPC ...@@ -111,7 +111,7 @@ config PPC
select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE
select HAVE_FUNCTION_TRACER 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 ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_IDE select HAVE_IDE
select HAVE_IOREMAP_PROT select HAVE_IOREMAP_PROT
......
...@@ -908,6 +908,12 @@ _GLOBAL(ftrace_caller) ...@@ -908,6 +908,12 @@ _GLOBAL(ftrace_caller)
ftrace_call: ftrace_call:
bl ftrace_stub bl ftrace_stub
nop 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) ld r0, 128(r1)
mtlr r0 mtlr r0
addi r1, r1, 112 addi r1, r1, 112
...@@ -946,7 +952,7 @@ _GLOBAL(ftrace_stub) ...@@ -946,7 +952,7 @@ _GLOBAL(ftrace_stub)
#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_DYNAMIC_FTRACE */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
ftrace_graph_caller: _GLOBAL(ftrace_graph_caller)
/* load r4 with local address */ /* load r4 with local address */
ld r4, 128(r1) ld r4, 128(r1)
subi r4, r4, MCOUNT_INSN_SIZE subi r4, r4, MCOUNT_INSN_SIZE
......
...@@ -43,7 +43,8 @@ static unsigned char *ftrace_nop_replace(void) ...@@ -43,7 +43,8 @@ static unsigned char *ftrace_nop_replace(void)
return (char *)&ftrace_nop; 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; static unsigned int op;
...@@ -55,8 +56,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) ...@@ -55,8 +56,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
*/ */
addr = GET_ADDR(addr); addr = GET_ADDR(addr);
/* Set to "bl addr" */ /* if (link) set op to 'bl' else 'b' */
op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc); op = 0x48000000 | (link ? 1 : 0);
op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc);
/* /*
* No locking needed, this must be called via kstop_machine * No locking needed, this must be called via kstop_machine
...@@ -344,7 +346,7 @@ int ftrace_make_nop(struct module *mod, ...@@ -344,7 +346,7 @@ int ftrace_make_nop(struct module *mod,
*/ */
if (test_24bit_addr(ip, addr)) { if (test_24bit_addr(ip, addr)) {
/* within range */ /* within range */
old = ftrace_call_replace(ip, addr); old = ftrace_call_replace(ip, addr, 1);
new = ftrace_nop_replace(); new = ftrace_nop_replace();
return ftrace_modify_code(ip, old, new); return ftrace_modify_code(ip, old, new);
} }
...@@ -484,7 +486,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -484,7 +486,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
if (test_24bit_addr(ip, addr)) { if (test_24bit_addr(ip, addr)) {
/* within range */ /* within range */
old = ftrace_nop_replace(); old = ftrace_nop_replace();
new = ftrace_call_replace(ip, addr); new = ftrace_call_replace(ip, addr, 1);
return ftrace_modify_code(ip, old, new); return ftrace_modify_code(ip, old, new);
} }
...@@ -513,7 +515,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) ...@@ -513,7 +515,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
int ret; int ret;
memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); 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); ret = ftrace_modify_code(ip, old, new);
return ret; return ret;
...@@ -532,6 +534,39 @@ int __init ftrace_dyn_arch_init(void *data) ...@@ -532,6 +534,39 @@ int __init ftrace_dyn_arch_init(void *data)
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #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 * Hook the return address and push it in the stack of return addrs
* in current thread info. * in current thread info.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment