aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/blackfin/Kconfig1
-rw-r--r--arch/blackfin/kernel/Makefile3
-rw-r--r--arch/blackfin/kernel/ftrace-entry.S68
-rw-r--r--arch/blackfin/kernel/ftrace.c42
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S1
5 files changed, 115 insertions, 0 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index ea8d92c1d447..5bc1360de2ee 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -19,6 +19,7 @@ config RWSEM_XCHGADD_ALGORITHM
19 19
20config BLACKFIN 20config BLACKFIN
21 def_bool y 21 def_bool y
22 select HAVE_FUNCTION_GRAPH_TRACER
22 select HAVE_FUNCTION_TRACER 23 select HAVE_FUNCTION_TRACER
23 select HAVE_IDE 24 select HAVE_IDE
24 select HAVE_KERNEL_GZIP 25 select HAVE_KERNEL_GZIP
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index d2ae285e5b6e..3731088e181b 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -16,6 +16,9 @@ else
16endif 16endif
17 17
18obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o 18obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
19obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
20CFLAGS_REMOVE_ftrace.o = -pg
21
19obj-$(CONFIG_IPIPE) += ipipe.o 22obj-$(CONFIG_IPIPE) += ipipe.o
20obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o 23obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
21obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o 24obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S
index ce71487b515f..6980b7a0615d 100644
--- a/arch/blackfin/kernel/ftrace-entry.S
+++ b/arch/blackfin/kernel/ftrace-entry.S
@@ -35,6 +35,28 @@ ENTRY(__mcount)
35 cc = r2 == r3; 35 cc = r2 == r3;
36 if ! cc jump .Ldo_trace; 36 if ! cc jump .Ldo_trace;
37 37
38#ifdef CONFIG_FUNCTION_GRAPH_TRACER
39 /* if the ftrace_graph_return function pointer is not set to
40 * the ftrace_stub entry, call prepare_ftrace_return().
41 */
42 p0.l = _ftrace_graph_return;
43 p0.h = _ftrace_graph_return;
44 r3 = [p0];
45 cc = r2 == r3;
46 if ! cc jump _ftrace_graph_caller;
47
48 /* similarly, if the ftrace_graph_entry function pointer is not
49 * set to the ftrace_graph_entry_stub entry, ...
50 */
51 p0.l = _ftrace_graph_entry;
52 p0.h = _ftrace_graph_entry;
53 r2.l = _ftrace_graph_entry_stub;
54 r2.h = _ftrace_graph_entry_stub;
55 r3 = [p0];
56 cc = r2 == r3;
57 if ! cc jump _ftrace_graph_caller;
58#endif
59
38 r2 = [sp++]; 60 r2 = [sp++];
39 rts; 61 rts;
40 62
@@ -61,6 +83,7 @@ ENTRY(__mcount)
61 call (p0); 83 call (p0);
62 84
63 /* restore state and get out of dodge */ 85 /* restore state and get out of dodge */
86.Lfinish_trace:
64 rets = [sp++]; 87 rets = [sp++];
65 r1 = [sp++]; 88 r1 = [sp++];
66 r0 = [sp++]; 89 r0 = [sp++];
@@ -70,3 +93,48 @@ ENTRY(__mcount)
70_ftrace_stub: 93_ftrace_stub:
71 rts; 94 rts;
72ENDPROC(__mcount) 95ENDPROC(__mcount)
96
97#ifdef CONFIG_FUNCTION_GRAPH_TRACER
98/* The prepare_ftrace_return() function is similar to the trace function
99 * except it takes a pointer to the location of the frompc. This is so
100 * the prepare_ftrace_return() can hijack it temporarily for probing
101 * purposes.
102 */
103ENTRY(_ftrace_graph_caller)
104 /* save first/second function arg and the return register */
105 [--sp] = r0;
106 [--sp] = r1;
107 [--sp] = rets;
108
109 r0 = fp;
110 r1 = rets;
111 r0 += 4;
112 r1 += -MCOUNT_INSN_SIZE;
113 call _prepare_ftrace_return;
114
115 jump .Lfinish_trace;
116ENDPROC(_ftrace_graph_caller)
117
118/* Undo the rewrite caused by ftrace_graph_caller(). The common function
119 * ftrace_return_to_handler() will return the original rets so we can
120 * restore it and be on our way.
121 */
122ENTRY(_return_to_handler)
123 /* make sure original return values are saved */
124 [--sp] = p0;
125 [--sp] = r0;
126 [--sp] = r1;
127
128 /* get original return address */
129 call _ftrace_return_to_handler;
130 rets = r0;
131
132 /* anomaly 05000371 - make sure we have at least three instructions
133 * between rets setting and the return
134 */
135 r1 = [sp++];
136 r0 = [sp++];
137 p0 = [sp++];
138 rts;
139ENDPROC(_return_to_handler)
140#endif
diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c
new file mode 100644
index 000000000000..905bfc40a00b
--- /dev/null
+++ b/arch/blackfin/kernel/ftrace.c
@@ -0,0 +1,42 @@
1/*
2 * ftrace graph code
3 *
4 * Copyright (C) 2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
6 */
7
8#include <linux/ftrace.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <asm/atomic.h>
12
13#ifdef CONFIG_FUNCTION_GRAPH_TRACER
14
15/*
16 * Hook the return address and push it in the stack of return addrs
17 * in current thread info.
18 */
19void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
20{
21 struct ftrace_graph_ent trace;
22 unsigned long return_hooker = (unsigned long)&return_to_handler;
23
24 if (unlikely(atomic_read(&current->tracing_graph_pause)))
25 return;
26
27 if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
28 return;
29
30 trace.func = self_addr;
31
32 /* Only trace if the calling function expects to */
33 if (!ftrace_graph_entry(&trace)) {
34 current->curr_ret_stack--;
35 return;
36 }
37
38 /* all is well in the world ! hijack RETS ... */
39 *parent = return_hooker;
40}
41
42#endif
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 119fbdb46475..6ac307ca0d80 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -54,6 +54,7 @@ SECTIONS
54 SCHED_TEXT 54 SCHED_TEXT
55#endif 55#endif
56 LOCK_TEXT 56 LOCK_TEXT
57 IRQENTRY_TEXT
57 KPROBES_TEXT 58 KPROBES_TEXT
58 *(.text.*) 59 *(.text.*)
59 *(.fixup) 60 *(.fixup)