aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorTim Bird <tim.bird@am.sony.com>2010-10-09 12:54:38 -0400
committerRabin Vincent <rabin@rab.in>2010-11-19 11:13:27 -0500
commit376cfa8730c08c0394d0aa1d4a80fd8c9971f323 (patch)
treef1384eb77981241b1ab1028a50b94382c2c6e723 /arch/arm
parentd3b9dc9dd2b994f396741f7086ffe7a48bacb165 (diff)
ARM: ftrace: function graph tracer support
Cc: Tim Bird <tim.bird@am.sony.com> [rabin@rab.in: rebase on top of latest code, keep code in ftrace.c instead of separate file, check for ftrace_graph_entry also] Signed-off-by: Rabin Vincent <rabin@rab.in>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/Makefile3
-rw-r--r--arch/arm/kernel/entry-common.S46
-rw-r--r--arch/arm/kernel/ftrace.c34
3 files changed, 82 insertions, 1 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5b9b268f4fbb..679851a9f589 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -5,7 +5,7 @@
5CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) 5CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
6AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) 6AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
7 7
8ifdef CONFIG_DYNAMIC_FTRACE 8ifdef CONFIG_FUNCTION_TRACER
9CFLAGS_REMOVE_ftrace.o = -pg 9CFLAGS_REMOVE_ftrace.o = -pg
10endif 10endif
11 11
@@ -33,6 +33,7 @@ obj-$(CONFIG_SMP) += smp.o
33obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o 33obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
34obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o 34obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
35obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 35obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
36obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
36obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 37obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
37obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o 38obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
38obj-$(CONFIG_ATAGS_PROC) += atags.o 39obj-$(CONFIG_ATAGS_PROC) += atags.o
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index fe1d5862b19f..9f1766211668 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -148,6 +148,20 @@ ENDPROC(ret_from_fork)
148 adr r0, .Lftrace_stub 148 adr r0, .Lftrace_stub
149 cmp r0, r2 149 cmp r0, r2
150 bne 1f 150 bne 1f
151
152#ifdef CONFIG_FUNCTION_GRAPH_TRACER
153 ldr r1, =ftrace_graph_return
154 ldr r2, [r1]
155 cmp r0, r2
156 bne ftrace_graph_caller\suffix
157
158 ldr r1, =ftrace_graph_entry
159 ldr r2, [r1]
160 ldr r0, =ftrace_graph_entry_stub
161 cmp r0, r2
162 bne ftrace_graph_caller\suffix
163#endif
164
151 mcount_exit 165 mcount_exit
152 166
1531: mcount_get_lr r1 @ lr of instrumented func 1671: mcount_get_lr r1 @ lr of instrumented func
@@ -172,6 +186,15 @@ ftrace_call\suffix:
172 mcount_exit 186 mcount_exit
173.endm 187.endm
174 188
189.macro __ftrace_graph_caller
190 sub r0, fp, #4 @ &lr of instrumented routine (&parent)
191 mov r1, lr @ instrumented routine (func)
192 sub r1, r1, #MCOUNT_INSN_SIZE
193 mov r2, fp @ frame pointer
194 bl prepare_ftrace_return
195 mcount_exit
196.endm
197
175#ifdef CONFIG_OLD_MCOUNT 198#ifdef CONFIG_OLD_MCOUNT
176/* 199/*
177 * mcount 200 * mcount
@@ -206,6 +229,12 @@ ENTRY(ftrace_caller_old)
206ENDPROC(ftrace_caller_old) 229ENDPROC(ftrace_caller_old)
207#endif 230#endif
208 231
232#ifdef CONFIG_FUNCTION_GRAPH_TRACER
233ENTRY(ftrace_graph_caller_old)
234 __ftrace_graph_caller
235ENDPROC(ftrace_graph_caller_old)
236#endif
237
209.purgem mcount_enter 238.purgem mcount_enter
210.purgem mcount_get_lr 239.purgem mcount_get_lr
211.purgem mcount_exit 240.purgem mcount_exit
@@ -244,10 +273,27 @@ ENTRY(ftrace_caller)
244ENDPROC(ftrace_caller) 273ENDPROC(ftrace_caller)
245#endif 274#endif
246 275
276#ifdef CONFIG_FUNCTION_GRAPH_TRACER
277ENTRY(ftrace_graph_caller)
278 __ftrace_graph_caller
279ENDPROC(ftrace_graph_caller)
280#endif
281
247.purgem mcount_enter 282.purgem mcount_enter
248.purgem mcount_get_lr 283.purgem mcount_get_lr
249.purgem mcount_exit 284.purgem mcount_exit
250 285
286#ifdef CONFIG_FUNCTION_GRAPH_TRACER
287 .globl return_to_handler
288return_to_handler:
289 stmdb sp!, {r0-r3}
290 mov r0, fp @ frame pointer
291 bl ftrace_return_to_handler
292 mov lr, r0 @ r0 has real ret addr
293 ldmia sp!, {r0-r3}
294 mov pc, lr
295#endif
296
251ENTRY(ftrace_stub) 297ENTRY(ftrace_stub)
252.Lftrace_stub: 298.Lftrace_stub:
253 mov pc, lr 299 mov pc, lr
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index 971ac8c36ea7..7a702a502871 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -24,6 +24,7 @@
24#define NOP 0xe8bd4000 /* pop {lr} */ 24#define NOP 0xe8bd4000 /* pop {lr} */
25#endif 25#endif
26 26
27#ifdef CONFIG_DYNAMIC_FTRACE
27#ifdef CONFIG_OLD_MCOUNT 28#ifdef CONFIG_OLD_MCOUNT
28#define OLD_MCOUNT_ADDR ((unsigned long) mcount) 29#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
29#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old) 30#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
@@ -193,3 +194,36 @@ int __init ftrace_dyn_arch_init(void *data)
193 194
194 return 0; 195 return 0;
195} 196}
197#endif /* CONFIG_DYNAMIC_FTRACE */
198
199#ifdef CONFIG_FUNCTION_GRAPH_TRACER
200void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
201 unsigned long frame_pointer)
202{
203 unsigned long return_hooker = (unsigned long) &return_to_handler;
204 struct ftrace_graph_ent trace;
205 unsigned long old;
206 int err;
207
208 if (unlikely(atomic_read(&current->tracing_graph_pause)))
209 return;
210
211 old = *parent;
212 *parent = return_hooker;
213
214 err = ftrace_push_return_trace(old, self_addr, &trace.depth,
215 frame_pointer);
216 if (err == -EBUSY) {
217 *parent = old;
218 return;
219 }
220
221 trace.func = self_addr;
222
223 /* Only trace if the calling function expects to */
224 if (!ftrace_graph_entry(&trace)) {
225 current->curr_ret_stack--;
226 *parent = old;
227 }
228}
229#endif /* CONFIG_FUNCTION_GRAPH_TRACER */