diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-06-10 04:45:29 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-06-13 07:20:16 -0400 |
commit | 1ee76d7e169ff2b0ff1df4b40b9d5276eec9ffb4 (patch) | |
tree | 384f296a2e24ee0156a81d9b62cdf6bc48d10650 /arch/blackfin/kernel/ftrace-entry.S | |
parent | 1c873be744410e26fb91ee9228c90adff6eabe15 (diff) |
Blackfin: initial support for ftrace grapher
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/ftrace-entry.S')
-rw-r--r-- | arch/blackfin/kernel/ftrace-entry.S | 68 |
1 files changed, 68 insertions, 0 deletions
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; |
72 | ENDPROC(__mcount) | 95 | ENDPROC(__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 | */ | ||
103 | ENTRY(_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; | ||
116 | ENDPROC(_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 | */ | ||
122 | ENTRY(_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; | ||
139 | ENDPROC(_return_to_handler) | ||
140 | #endif | ||