Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 138463
b: refs/heads/master
c: 6794c78
h: refs/heads/master
i:
  138461: 2c2fa16
  138459: 2376ba1
  138455: 199ed5d
  138447: 26a4195
  138431: c3df475
v: v3
  • Loading branch information
Steven Rostedt authored and Benjamin Herrenschmidt committed Feb 22, 2009
1 parent 497c275 commit a5c8210
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 17be5b3ddf71d980f67fc826e49b00cd2afd724d
refs/heads/master: 6794c78243bfda020ab184d6d578944f8e90d26c
1 change: 1 addition & 0 deletions trunk/arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +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 ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_IDE
select HAVE_IOREMAP_PROT
Expand Down
9 changes: 4 additions & 5 deletions trunk/arch/powerpc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@ CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog
CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog
CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog
CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog

ifdef CONFIG_DYNAMIC_FTRACE
# dynamic ftrace setup.
# do not trace tracer code
CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog
endif

# timers used by tracing
CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog
endif

obj-y := cputable.o ptrace.o syscalls.o \
Expand Down Expand Up @@ -95,6 +93,7 @@ obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o

obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o

obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o

Expand Down
58 changes: 55 additions & 3 deletions trunk/arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -931,13 +931,65 @@ _GLOBAL(_mcount)
ld r5,0(r5)
mtctr r5
bctrl

nop


#ifdef CONFIG_FUNCTION_GRAPH_TRACER
b ftrace_graph_caller
#endif
ld r0, 128(r1)
mtlr r0
addi r1, r1, 112
_GLOBAL(ftrace_stub)
blr

#endif
#endif
#endif /* CONFIG_DYNAMIC_FTRACE */

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ftrace_graph_caller:
/* load r4 with local address */
ld r4, 128(r1)
subi r4, r4, MCOUNT_INSN_SIZE

/* get the parent address */
ld r11, 112(r1)
addi r3, r11, 16

bl .prepare_ftrace_return
nop

ld r0, 128(r1)
mtlr r0
addi r1, r1, 112
blr

_GLOBAL(return_to_handler)
/* need to save return values */
std r4, -32(r1)
std r3, -24(r1)
/* save TOC */
std r2, -16(r1)
std r31, -8(r1)
mr r31, r1
stdu r1, -112(r1)

/* update the TOC */
LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler)
ld r2, 8(r4)

bl .ftrace_return_to_handler
nop

/* return value has real return address */
mtlr r3

ld r1, 0(r1)
ld r4, -32(r1)
ld r3, -24(r1)
ld r2, -16(r1)
ld r31, -8(r1)

/* Jump back to real return address */
blr
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
#endif /* CONFIG_FUNCTION_TRACER */
79 changes: 77 additions & 2 deletions trunk/arch/powerpc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
*
* Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
*
* Added function graph tracer code, taken from x86 that was written
* by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
*
*/

#include <linux/spinlock.h>
Expand All @@ -20,15 +23,15 @@
#include <asm/code-patching.h>
#include <asm/ftrace.h>

static unsigned int ftrace_nop = PPC_NOP_INSTR;

#ifdef CONFIG_PPC32
# define GET_ADDR(addr) addr
#else
/* PowerPC64's functions are data that points to the functions */
# define GET_ADDR(addr) (*(unsigned long *)addr)
#endif

#ifdef CONFIG_DYNAMIC_FTRACE
static unsigned int ftrace_nop = PPC_NOP_INSTR;

static unsigned int ftrace_calc_offset(long ip, long addr)
{
Expand Down Expand Up @@ -525,3 +528,75 @@ int __init ftrace_dyn_arch_init(void *data)

return 0;
}
#endif /* CONFIG_DYNAMIC_FTRACE */

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

/*
* Hook the return address and push it in the stack of return addrs
* in current thread info.
*/
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
{
unsigned long old;
unsigned long long calltime;
int faulted;
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)
&return_to_handler;

if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;

return_hooker = GET_ADDR(return_hooker);

/*
* Protect against fault, even if it shouldn't
* happen. This tool is too much intrusive to
* ignore such a protection.
*/
asm volatile(
"1: " PPC_LL "%[old], 0(%[parent])\n"
"2: " PPC_STL "%[return_hooker], 0(%[parent])\n"
" li %[faulted], 0\n"
"3:"

".section .fixup, \"ax\"\n"
"4: li %[faulted], 1\n"
" b 3b\n"
".previous\n"

".section __ex_table,\"a\"\n"
PPC_LONG_ALIGN "\n"
PPC_LONG "1b,4b\n"
PPC_LONG "2b,4b\n"
".previous"

: [old] "=r" (old), [faulted] "=r" (faulted)
: [parent] "r" (parent), [return_hooker] "r" (return_hooker)
: "memory"
);

if (unlikely(faulted)) {
ftrace_graph_stop();
WARN_ON(1);
return;
}

calltime = cpu_clock(raw_smp_processor_id());

if (ftrace_push_return_trace(old, calltime,
self_addr, &trace.depth) == -EBUSY) {
*parent = old;
return;
}

trace.func = self_addr;

/* Only trace if the calling function expects to */
if (!ftrace_graph_entry(&trace)) {
current->curr_ret_stack--;
*parent = old;
}
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
16 changes: 16 additions & 0 deletions trunk/arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
#include <linux/ftrace.h>
#include <linux/kernel_stat.h>

#include <asm/pgtable.h>
Expand Down Expand Up @@ -1008,6 +1009,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
unsigned long sp, ip, lr, newsp;
int count = 0;
int firstframe = 1;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int curr_frame = current->curr_ret_stack;
extern void return_to_handler(void);
unsigned long addr = (unsigned long)return_to_handler;
#ifdef CONFIG_PPC64
addr = *(unsigned long*)addr;
#endif
#endif

sp = (unsigned long) stack;
if (tsk == NULL)
Expand All @@ -1030,6 +1039,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
ip = stack[STACK_FRAME_LR_SAVE];
if (!firstframe || ip != lr) {
printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if (ip == addr && curr_frame >= 0) {
printk(" (%pS)",
(void *)current->ret_stack[curr_frame].ret);
curr_frame--;
}
#endif
if (firstframe)
printk(" (unreliable)");
printk("\n");
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/powerpc/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ SECTIONS
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
IRQENTRY_TEXT

#ifdef CONFIG_PPC32
*(.got1)
Expand Down

0 comments on commit a5c8210

Please sign in to comment.