diff options
author | Mike Frysinger <vapier@gentoo.org> | 2010-07-21 09:13:02 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-08-06 12:55:54 -0400 |
commit | f5074429621ceb0ec42f8116bd51d02c031faf82 (patch) | |
tree | a5d22f85446c63be25961e2ea04321e197c615db /arch/blackfin/kernel/ftrace-entry.S | |
parent | 67df6cc665dc3441bf5eb2ad7018e969463a2588 (diff) |
Blackfin: add support for dynamic ftrace
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 | 85 |
1 files changed, 77 insertions, 8 deletions
diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S index d66446b572c0..7eed00bbd26d 100644 --- a/arch/blackfin/kernel/ftrace-entry.S +++ b/arch/blackfin/kernel/ftrace-entry.S | |||
@@ -10,6 +10,18 @@ | |||
10 | 10 | ||
11 | .text | 11 | .text |
12 | 12 | ||
13 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
14 | |||
15 | /* Simple stub so we can boot the kernel until runtime patching has | ||
16 | * disabled all calls to this. Then it'll be unused. | ||
17 | */ | ||
18 | ENTRY(__mcount) | ||
19 | # if ANOMALY_05000371 | ||
20 | nop; nop; nop; nop; | ||
21 | # endif | ||
22 | rts; | ||
23 | ENDPROC(__mcount) | ||
24 | |||
13 | /* GCC will have called us before setting up the function prologue, so we | 25 | /* GCC will have called us before setting up the function prologue, so we |
14 | * can clobber the normal scratch registers, but we need to make sure to | 26 | * can clobber the normal scratch registers, but we need to make sure to |
15 | * save/restore the registers used for argument passing (R0-R2) in case | 27 | * save/restore the registers used for argument passing (R0-R2) in case |
@@ -20,15 +32,65 @@ | |||
20 | * function. And since GCC pushed the previous RETS for us, the previous | 32 | * function. And since GCC pushed the previous RETS for us, the previous |
21 | * function will be waiting there. mmmm pie. | 33 | * function will be waiting there. mmmm pie. |
22 | */ | 34 | */ |
35 | ENTRY(_ftrace_caller) | ||
36 | # ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
37 | /* optional micro optimization: return if stopped */ | ||
38 | p1.l = _function_trace_stop; | ||
39 | p1.h = _function_trace_stop; | ||
40 | r3 = [p1]; | ||
41 | cc = r3 == 0; | ||
42 | if ! cc jump _ftrace_stub (bp); | ||
43 | # endif | ||
44 | |||
45 | /* save first/second/third function arg and the return register */ | ||
46 | [--sp] = r2; | ||
47 | [--sp] = r0; | ||
48 | [--sp] = r1; | ||
49 | [--sp] = rets; | ||
50 | |||
51 | /* function_trace_call(unsigned long ip, unsigned long parent_ip): | ||
52 | * ip: this point was called by ... | ||
53 | * parent_ip: ... this function | ||
54 | * the ip itself will need adjusting for the mcount call | ||
55 | */ | ||
56 | r0 = rets; | ||
57 | r1 = [sp + 16]; /* skip the 4 local regs on stack */ | ||
58 | r0 += -MCOUNT_INSN_SIZE; | ||
59 | |||
60 | .globl _ftrace_call | ||
61 | _ftrace_call: | ||
62 | call _ftrace_stub | ||
63 | |||
64 | # ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
65 | .globl _ftrace_graph_call | ||
66 | _ftrace_graph_call: | ||
67 | nop; /* jump _ftrace_graph_caller; */ | ||
68 | # endif | ||
69 | |||
70 | /* restore state and get out of dodge */ | ||
71 | .Lfinish_trace: | ||
72 | rets = [sp++]; | ||
73 | r1 = [sp++]; | ||
74 | r0 = [sp++]; | ||
75 | r2 = [sp++]; | ||
76 | |||
77 | .globl _ftrace_stub | ||
78 | _ftrace_stub: | ||
79 | rts; | ||
80 | ENDPROC(_ftrace_caller) | ||
81 | |||
82 | #else | ||
83 | |||
84 | /* See documentation for _ftrace_caller */ | ||
23 | ENTRY(__mcount) | 85 | ENTRY(__mcount) |
24 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | 86 | # ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST |
25 | /* optional micro optimization: return if stopped */ | 87 | /* optional micro optimization: return if stopped */ |
26 | p1.l = _function_trace_stop; | 88 | p1.l = _function_trace_stop; |
27 | p1.h = _function_trace_stop; | 89 | p1.h = _function_trace_stop; |
28 | r3 = [p1]; | 90 | r3 = [p1]; |
29 | cc = r3 == 0; | 91 | cc = r3 == 0; |
30 | if ! cc jump _ftrace_stub (bp); | 92 | if ! cc jump _ftrace_stub (bp); |
31 | #endif | 93 | # endif |
32 | 94 | ||
33 | /* save third function arg early so we can do testing below */ | 95 | /* save third function arg early so we can do testing below */ |
34 | [--sp] = r2; | 96 | [--sp] = r2; |
@@ -44,7 +106,7 @@ ENTRY(__mcount) | |||
44 | cc = r2 == r3; | 106 | cc = r2 == r3; |
45 | if ! cc jump .Ldo_trace; | 107 | if ! cc jump .Ldo_trace; |
46 | 108 | ||
47 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 109 | # ifdef CONFIG_FUNCTION_GRAPH_TRACER |
48 | /* if the ftrace_graph_return function pointer is not set to | 110 | /* if the ftrace_graph_return function pointer is not set to |
49 | * the ftrace_stub entry, call prepare_ftrace_return(). | 111 | * the ftrace_stub entry, call prepare_ftrace_return(). |
50 | */ | 112 | */ |
@@ -64,7 +126,7 @@ ENTRY(__mcount) | |||
64 | r3 = [p0]; | 126 | r3 = [p0]; |
65 | cc = r2 == r3; | 127 | cc = r2 == r3; |
66 | if ! cc jump _ftrace_graph_caller; | 128 | if ! cc jump _ftrace_graph_caller; |
67 | #endif | 129 | # endif |
68 | 130 | ||
69 | r2 = [sp++]; | 131 | r2 = [sp++]; |
70 | rts; | 132 | rts; |
@@ -103,6 +165,8 @@ _ftrace_stub: | |||
103 | rts; | 165 | rts; |
104 | ENDPROC(__mcount) | 166 | ENDPROC(__mcount) |
105 | 167 | ||
168 | #endif | ||
169 | |||
106 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 170 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
107 | /* The prepare_ftrace_return() function is similar to the trace function | 171 | /* The prepare_ftrace_return() function is similar to the trace function |
108 | * except it takes a pointer to the location of the frompc. This is so | 172 | * except it takes a pointer to the location of the frompc. This is so |
@@ -110,6 +174,7 @@ ENDPROC(__mcount) | |||
110 | * purposes. | 174 | * purposes. |
111 | */ | 175 | */ |
112 | ENTRY(_ftrace_graph_caller) | 176 | ENTRY(_ftrace_graph_caller) |
177 | # ifndef CONFIG_DYNAMIC_FTRACE | ||
113 | /* save first/second function arg and the return register */ | 178 | /* save first/second function arg and the return register */ |
114 | [--sp] = r0; | 179 | [--sp] = r0; |
115 | [--sp] = r1; | 180 | [--sp] = r1; |
@@ -118,9 +183,13 @@ ENTRY(_ftrace_graph_caller) | |||
118 | /* prepare_ftrace_return(parent, self_addr, frame_pointer) */ | 183 | /* prepare_ftrace_return(parent, self_addr, frame_pointer) */ |
119 | r0 = sp; /* unsigned long *parent */ | 184 | r0 = sp; /* unsigned long *parent */ |
120 | r1 = rets; /* unsigned long self_addr */ | 185 | r1 = rets; /* unsigned long self_addr */ |
121 | #ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST | 186 | # else |
187 | r0 = sp; /* unsigned long *parent */ | ||
188 | r1 = [sp]; /* unsigned long self_addr */ | ||
189 | # endif | ||
190 | # ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST | ||
122 | r2 = fp; /* unsigned long frame_pointer */ | 191 | r2 = fp; /* unsigned long frame_pointer */ |
123 | #endif | 192 | # endif |
124 | r0 += 16; /* skip the 4 local regs on stack */ | 193 | r0 += 16; /* skip the 4 local regs on stack */ |
125 | r1 += -MCOUNT_INSN_SIZE; | 194 | r1 += -MCOUNT_INSN_SIZE; |
126 | call _prepare_ftrace_return; | 195 | call _prepare_ftrace_return; |
@@ -139,9 +208,9 @@ ENTRY(_return_to_handler) | |||
139 | [--sp] = r1; | 208 | [--sp] = r1; |
140 | 209 | ||
141 | /* get original return address */ | 210 | /* get original return address */ |
142 | #ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST | 211 | # ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST |
143 | r0 = fp; /* Blackfin is sane, so omit this */ | 212 | r0 = fp; /* Blackfin is sane, so omit this */ |
144 | #endif | 213 | # endif |
145 | call _ftrace_return_to_handler; | 214 | call _ftrace_return_to_handler; |
146 | rets = r0; | 215 | rets = r0; |
147 | 216 | ||