Blackfin: initial support for ftrace grapher
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
1c873be744
commit
1ee76d7e16
5 changed files with 115 additions and 0 deletions
|
@ -19,6 +19,7 @@ config RWSEM_XCHGADD_ALGORITHM
|
|||
|
||||
config BLACKFIN
|
||||
def_bool y
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_IDE
|
||||
select HAVE_KERNEL_GZIP
|
||||
|
|
|
@ -16,6 +16,9 @@ else
|
|||
endif
|
||||
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
|
||||
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
||||
CFLAGS_REMOVE_ftrace.o = -pg
|
||||
|
||||
obj-$(CONFIG_IPIPE) += ipipe.o
|
||||
obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
|
||||
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
|
||||
|
|
|
@ -35,6 +35,28 @@ ENTRY(__mcount)
|
|||
cc = r2 == r3;
|
||||
if ! cc jump .Ldo_trace;
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* if the ftrace_graph_return function pointer is not set to
|
||||
* the ftrace_stub entry, call prepare_ftrace_return().
|
||||
*/
|
||||
p0.l = _ftrace_graph_return;
|
||||
p0.h = _ftrace_graph_return;
|
||||
r3 = [p0];
|
||||
cc = r2 == r3;
|
||||
if ! cc jump _ftrace_graph_caller;
|
||||
|
||||
/* similarly, if the ftrace_graph_entry function pointer is not
|
||||
* set to the ftrace_graph_entry_stub entry, ...
|
||||
*/
|
||||
p0.l = _ftrace_graph_entry;
|
||||
p0.h = _ftrace_graph_entry;
|
||||
r2.l = _ftrace_graph_entry_stub;
|
||||
r2.h = _ftrace_graph_entry_stub;
|
||||
r3 = [p0];
|
||||
cc = r2 == r3;
|
||||
if ! cc jump _ftrace_graph_caller;
|
||||
#endif
|
||||
|
||||
r2 = [sp++];
|
||||
rts;
|
||||
|
||||
|
@ -61,6 +83,7 @@ ENTRY(__mcount)
|
|||
call (p0);
|
||||
|
||||
/* restore state and get out of dodge */
|
||||
.Lfinish_trace:
|
||||
rets = [sp++];
|
||||
r1 = [sp++];
|
||||
r0 = [sp++];
|
||||
|
@ -70,3 +93,48 @@ ENTRY(__mcount)
|
|||
_ftrace_stub:
|
||||
rts;
|
||||
ENDPROC(__mcount)
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* The prepare_ftrace_return() function is similar to the trace function
|
||||
* except it takes a pointer to the location of the frompc. This is so
|
||||
* the prepare_ftrace_return() can hijack it temporarily for probing
|
||||
* purposes.
|
||||
*/
|
||||
ENTRY(_ftrace_graph_caller)
|
||||
/* save first/second function arg and the return register */
|
||||
[--sp] = r0;
|
||||
[--sp] = r1;
|
||||
[--sp] = rets;
|
||||
|
||||
r0 = fp;
|
||||
r1 = rets;
|
||||
r0 += 4;
|
||||
r1 += -MCOUNT_INSN_SIZE;
|
||||
call _prepare_ftrace_return;
|
||||
|
||||
jump .Lfinish_trace;
|
||||
ENDPROC(_ftrace_graph_caller)
|
||||
|
||||
/* Undo the rewrite caused by ftrace_graph_caller(). The common function
|
||||
* ftrace_return_to_handler() will return the original rets so we can
|
||||
* restore it and be on our way.
|
||||
*/
|
||||
ENTRY(_return_to_handler)
|
||||
/* make sure original return values are saved */
|
||||
[--sp] = p0;
|
||||
[--sp] = r0;
|
||||
[--sp] = r1;
|
||||
|
||||
/* get original return address */
|
||||
call _ftrace_return_to_handler;
|
||||
rets = r0;
|
||||
|
||||
/* anomaly 05000371 - make sure we have at least three instructions
|
||||
* between rets setting and the return
|
||||
*/
|
||||
r1 = [sp++];
|
||||
r0 = [sp++];
|
||||
p0 = [sp++];
|
||||
rts;
|
||||
ENDPROC(_return_to_handler)
|
||||
#endif
|
||||
|
|
42
arch/blackfin/kernel/ftrace.c
Normal file
42
arch/blackfin/kernel/ftrace.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* ftrace graph code
|
||||
*
|
||||
* Copyright (C) 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
struct ftrace_graph_ent trace;
|
||||
unsigned long return_hooker = (unsigned long)&return_to_handler;
|
||||
|
||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return;
|
||||
|
||||
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
|
||||
return;
|
||||
|
||||
trace.func = self_addr;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
current->curr_ret_stack--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* all is well in the world ! hijack RETS ... */
|
||||
*parent = return_hooker;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -54,6 +54,7 @@ SECTIONS
|
|||
SCHED_TEXT
|
||||
#endif
|
||||
LOCK_TEXT
|
||||
IRQENTRY_TEXT
|
||||
KPROBES_TEXT
|
||||
*(.text.*)
|
||||
*(.fixup)
|
||||
|
|
Loading…
Add table
Reference in a new issue