aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2009-11-16 04:32:10 -0500
committerMichal Simek <monstr@monstr.eu>2009-12-14 02:44:53 -0500
commita0d3e66522e8f6119f002cf31e5d92d7ae73b409 (patch)
tree717d36ef5a2e103669403011317a88b1af84c9d3 /arch/microblaze
parent7d241ff0567b9503d79ee775c40927d09b509f83 (diff)
microblaze: ftrace: add function graph support
For more information look at Documentation/trace folder. Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/kernel/ftrace.c58
-rw-r--r--arch/microblaze/kernel/mcount.S41
3 files changed, 100 insertions, 0 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 102d73aa1063..e297802b8321 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -8,6 +8,7 @@ config MICROBLAZE
8 select HAVE_LMB 8 select HAVE_LMB
9 select HAVE_FUNCTION_TRACER 9 select HAVE_FUNCTION_TRACER
10 select HAVE_FUNCTION_TRACE_MCOUNT_TEST 10 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
11 select HAVE_FUNCTION_GRAPH_TRACER
11 select HAVE_DYNAMIC_FTRACE 12 select HAVE_DYNAMIC_FTRACE
12 select HAVE_FTRACE_MCOUNT_RECORD 13 select HAVE_FTRACE_MCOUNT_RECORD
13 select USB_ARCH_HAS_EHCI 14 select USB_ARCH_HAS_EHCI
diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c
index c1889b101cb8..0952a8b52c35 100644
--- a/arch/microblaze/kernel/ftrace.c
+++ b/arch/microblaze/kernel/ftrace.c
@@ -14,6 +14,64 @@
14#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
15#include <linux/ftrace.h> 15#include <linux/ftrace.h>
16 16
17#ifdef CONFIG_FUNCTION_GRAPH_TRACER
18/*
19 * Hook the return address and push it in the stack of return addrs
20 * in current thread info.
21 */
22void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
23{
24 unsigned long old;
25 int faulted, err;
26 struct ftrace_graph_ent trace;
27 unsigned long return_hooker = (unsigned long)
28 &return_to_handler;
29
30 if (unlikely(atomic_read(&current->tracing_graph_pause)))
31 return;
32
33 /*
34 * Protect against fault, even if it shouldn't
35 * happen. This tool is too much intrusive to
36 * ignore such a protection.
37 */
38 asm volatile(" 1: lwi %0, %2, 0; \
39 2: swi %3, %2, 0; \
40 addik %1, r0, 0; \
41 3: \
42 .section .fixup, \"ax\"; \
43 4: brid 3b; \
44 addik %1, r0, 1; \
45 .previous; \
46 .section __ex_table,\"a\"; \
47 .word 1b,4b; \
48 .word 2b,4b; \
49 .previous;" \
50 : "=&r" (old), "=r" (faulted)
51 : "r" (parent), "r" (return_hooker)
52 );
53
54 if (unlikely(faulted)) {
55 ftrace_graph_stop();
56 WARN_ON(1);
57 return;
58 }
59
60 err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
61 if (err == -EBUSY) {
62 *parent = old;
63 return;
64 }
65
66 trace.func = self_addr;
67 /* Only trace if the calling function expects to */
68 if (!ftrace_graph_entry(&trace)) {
69 current->curr_ret_stack--;
70 *parent = old;
71 }
72}
73#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
74
17#ifdef CONFIG_DYNAMIC_FTRACE 75#ifdef CONFIG_DYNAMIC_FTRACE
18/* save value to addr - it is save to do it in asm */ 76/* save value to addr - it is save to do it in asm */
19static int ftrace_modify_code(unsigned long addr, unsigned int value) 77static int ftrace_modify_code(unsigned long addr, unsigned int value)
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S
index 30aaf8fb55b2..84a19458c74d 100644
--- a/arch/microblaze/kernel/mcount.S
+++ b/arch/microblaze/kernel/mcount.S
@@ -96,6 +96,27 @@ ENTRY(ftrace_caller)
96 bneid r5, end; 96 bneid r5, end;
97 nop; 97 nop;
98 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ 98 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
99#ifdef CONFIG_FUNCTION_GRAPH_TRACER
100 lwi r5, r0, ftrace_graph_return;
101 addik r6, r0, ftrace_stub; /* asm implementation */
102 cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
103 beqid r5, end_graph_tracer;
104 nop;
105
106 lwi r6, r0, ftrace_graph_entry;
107 addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */
108 cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
109 beqid r5, end_graph_tracer;
110 nop;
111 addik r5, r1, 120; /* MS: load parent addr */
112 addik r6, r15, 0; /* MS: load current function addr */
113 bralid r15, prepare_ftrace_return;
114 nop;
115 /* MS: graph was taken that's why - can jump over function trace */
116 brid end;
117 nop;
118end_graph_tracer:
119#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
99#ifndef CONFIG_DYNAMIC_FTRACE 120#ifndef CONFIG_DYNAMIC_FTRACE
100 /* MS: test function trace if is taken or not */ 121 /* MS: test function trace if is taken or not */
101 lwi r20, r0, ftrace_trace_function; 122 lwi r20, r0, ftrace_trace_function;
@@ -121,3 +142,23 @@ end:
121 142
122 rtsd r15, 8; /* MS: jump back */ 143 rtsd r15, 8; /* MS: jump back */
123 nop; 144 nop;
145
146#ifdef CONFIG_FUNCTION_GRAPH_TRACER
147ENTRY(return_to_handler)
148 nop; /* MS: just barrier for rtsd r15, 8 */
149 nop;
150 SAVE_REGS
151 swi r15, r1, 0;
152
153 /* MS: find out returning address */
154 bralid r15, ftrace_return_to_handler;
155 nop;
156
157 /* MS: return value from ftrace_return_to_handler is my returning addr
158 * must be before restore regs because I have to restore r3 content */
159 addik r15, r3, 0;
160 RESTORE_REGS
161
162 rtsd r15, 8; /* MS: jump back */
163 nop;
164#endif /* CONFIG_FUNCTION_TRACER */