Skip to content

Commit

Permalink
Blackfin: initial support for ftrace grapher
Browse files Browse the repository at this point in the history
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
  • Loading branch information
Mike Frysinger committed Jun 13, 2009
1 parent 1c873be commit 1ee76d7
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions arch/blackfin/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions arch/blackfin/kernel/ftrace-entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -61,6 +83,7 @@ ENTRY(__mcount)
call (p0);

/* restore state and get out of dodge */
.Lfinish_trace:
rets = [sp++];
r1 = [sp++];
r0 = [sp++];
Expand All @@ -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 changes: 42 additions & 0 deletions arch/blackfin/kernel/ftrace.c
Original file line number Diff line number Diff line change
@@ -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(&current->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
1 change: 1 addition & 0 deletions arch/blackfin/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ SECTIONS
SCHED_TEXT
#endif
LOCK_TEXT
IRQENTRY_TEXT
KPROBES_TEXT
*(.text.*)
*(.fixup)
Expand Down

0 comments on commit 1ee76d7

Please sign in to comment.