Skip to content

Commit

Permalink
powerpc64, tracing: add function graph tracer with dynamic tracing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steven Rostedt authored and Benjamin Herrenschmidt committed Feb 22, 2009
1 parent 6794c78 commit 4654288
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
47 changes: 41 additions & 6 deletions arch/powerpc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down

0 comments on commit 4654288

Please sign in to comment.