diff options
Diffstat (limited to 'arch/arm/kernel/entry-common.S')
-rw-r--r-- | arch/arm/kernel/entry-common.S | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 6bb09d4abdea..f8ccc21fa032 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -109,241 +109,6 @@ ENDPROC(ret_from_fork) | |||
109 | #undef CALL | 109 | #undef CALL |
110 | #define CALL(x) .long x | 110 | #define CALL(x) .long x |
111 | 111 | ||
112 | #ifdef CONFIG_FUNCTION_TRACER | ||
113 | /* | ||
114 | * When compiling with -pg, gcc inserts a call to the mcount routine at the | ||
115 | * start of every function. In mcount, apart from the function's address (in | ||
116 | * lr), we need to get hold of the function's caller's address. | ||
117 | * | ||
118 | * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | ||
119 | * | ||
120 | * bl mcount | ||
121 | * | ||
122 | * These versions have the limitation that in order for the mcount routine to | ||
123 | * be able to determine the function's caller's address, an APCS-style frame | ||
124 | * pointer (which is set up with something like the code below) is required. | ||
125 | * | ||
126 | * mov ip, sp | ||
127 | * push {fp, ip, lr, pc} | ||
128 | * sub fp, ip, #4 | ||
129 | * | ||
130 | * With EABI, these frame pointers are not available unless -mapcs-frame is | ||
131 | * specified, and if building as Thumb-2, not even then. | ||
132 | * | ||
133 | * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | ||
134 | * with call sites like: | ||
135 | * | ||
136 | * push {lr} | ||
137 | * bl __gnu_mcount_nc | ||
138 | * | ||
139 | * With these compilers, frame pointers are not necessary. | ||
140 | * | ||
141 | * mcount can be thought of as a function called in the middle of a subroutine | ||
142 | * call. As such, it needs to be transparent for both the caller and the | ||
143 | * callee: the original lr needs to be restored when leaving mcount, and no | ||
144 | * registers should be clobbered. (In the __gnu_mcount_nc implementation, we | ||
145 | * clobber the ip register. This is OK because the ARM calling convention | ||
146 | * allows it to be clobbered in subroutines and doesn't use it to hold | ||
147 | * parameters.) | ||
148 | * | ||
149 | * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | ||
150 | * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | ||
151 | * arch/arm/kernel/ftrace.c). | ||
152 | */ | ||
153 | |||
154 | #ifndef CONFIG_OLD_MCOUNT | ||
155 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | ||
156 | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | ||
157 | #endif | ||
158 | #endif | ||
159 | |||
160 | .macro mcount_adjust_addr rd, rn | ||
161 | bic \rd, \rn, #1 @ clear the Thumb bit if present | ||
162 | sub \rd, \rd, #MCOUNT_INSN_SIZE | ||
163 | .endm | ||
164 | |||
165 | .macro __mcount suffix | ||
166 | mcount_enter | ||
167 | ldr r0, =ftrace_trace_function | ||
168 | ldr r2, [r0] | ||
169 | adr r0, .Lftrace_stub | ||
170 | cmp r0, r2 | ||
171 | bne 1f | ||
172 | |||
173 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
174 | ldr r1, =ftrace_graph_return | ||
175 | ldr r2, [r1] | ||
176 | cmp r0, r2 | ||
177 | bne ftrace_graph_caller\suffix | ||
178 | |||
179 | ldr r1, =ftrace_graph_entry | ||
180 | ldr r2, [r1] | ||
181 | ldr r0, =ftrace_graph_entry_stub | ||
182 | cmp r0, r2 | ||
183 | bne ftrace_graph_caller\suffix | ||
184 | #endif | ||
185 | |||
186 | mcount_exit | ||
187 | |||
188 | 1: mcount_get_lr r1 @ lr of instrumented func | ||
189 | mcount_adjust_addr r0, lr @ instrumented function | ||
190 | adr lr, BSYM(2f) | ||
191 | mov pc, r2 | ||
192 | 2: mcount_exit | ||
193 | .endm | ||
194 | |||
195 | .macro __ftrace_caller suffix | ||
196 | mcount_enter | ||
197 | |||
198 | mcount_get_lr r1 @ lr of instrumented func | ||
199 | mcount_adjust_addr r0, lr @ instrumented function | ||
200 | |||
201 | .globl ftrace_call\suffix | ||
202 | ftrace_call\suffix: | ||
203 | bl ftrace_stub | ||
204 | |||
205 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
206 | .globl ftrace_graph_call\suffix | ||
207 | ftrace_graph_call\suffix: | ||
208 | mov r0, r0 | ||
209 | #endif | ||
210 | |||
211 | mcount_exit | ||
212 | .endm | ||
213 | |||
214 | .macro __ftrace_graph_caller | ||
215 | sub r0, fp, #4 @ &lr of instrumented routine (&parent) | ||
216 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
217 | @ called from __ftrace_caller, saved in mcount_enter | ||
218 | ldr r1, [sp, #16] @ instrumented routine (func) | ||
219 | mcount_adjust_addr r1, r1 | ||
220 | #else | ||
221 | @ called from __mcount, untouched in lr | ||
222 | mcount_adjust_addr r1, lr @ instrumented routine (func) | ||
223 | #endif | ||
224 | mov r2, fp @ frame pointer | ||
225 | bl prepare_ftrace_return | ||
226 | mcount_exit | ||
227 | .endm | ||
228 | |||
229 | #ifdef CONFIG_OLD_MCOUNT | ||
230 | /* | ||
231 | * mcount | ||
232 | */ | ||
233 | |||
234 | .macro mcount_enter | ||
235 | stmdb sp!, {r0-r3, lr} | ||
236 | .endm | ||
237 | |||
238 | .macro mcount_get_lr reg | ||
239 | ldr \reg, [fp, #-4] | ||
240 | .endm | ||
241 | |||
242 | .macro mcount_exit | ||
243 | ldr lr, [fp, #-4] | ||
244 | ldmia sp!, {r0-r3, pc} | ||
245 | .endm | ||
246 | |||
247 | ENTRY(mcount) | ||
248 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
249 | stmdb sp!, {lr} | ||
250 | ldr lr, [fp, #-4] | ||
251 | ldmia sp!, {pc} | ||
252 | #else | ||
253 | __mcount _old | ||
254 | #endif | ||
255 | ENDPROC(mcount) | ||
256 | |||
257 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
258 | ENTRY(ftrace_caller_old) | ||
259 | __ftrace_caller _old | ||
260 | ENDPROC(ftrace_caller_old) | ||
261 | #endif | ||
262 | |||
263 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
264 | ENTRY(ftrace_graph_caller_old) | ||
265 | __ftrace_graph_caller | ||
266 | ENDPROC(ftrace_graph_caller_old) | ||
267 | #endif | ||
268 | |||
269 | .purgem mcount_enter | ||
270 | .purgem mcount_get_lr | ||
271 | .purgem mcount_exit | ||
272 | #endif | ||
273 | |||
274 | /* | ||
275 | * __gnu_mcount_nc | ||
276 | */ | ||
277 | |||
278 | .macro mcount_enter | ||
279 | /* | ||
280 | * This pad compensates for the push {lr} at the call site. Note that we are | ||
281 | * unable to unwind through a function which does not otherwise save its lr. | ||
282 | */ | ||
283 | UNWIND(.pad #4) | ||
284 | stmdb sp!, {r0-r3, lr} | ||
285 | UNWIND(.save {r0-r3, lr}) | ||
286 | .endm | ||
287 | |||
288 | .macro mcount_get_lr reg | ||
289 | ldr \reg, [sp, #20] | ||
290 | .endm | ||
291 | |||
292 | .macro mcount_exit | ||
293 | ldmia sp!, {r0-r3, ip, lr} | ||
294 | ret ip | ||
295 | .endm | ||
296 | |||
297 | ENTRY(__gnu_mcount_nc) | ||
298 | UNWIND(.fnstart) | ||
299 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
300 | mov ip, lr | ||
301 | ldmia sp!, {lr} | ||
302 | ret ip | ||
303 | #else | ||
304 | __mcount | ||
305 | #endif | ||
306 | UNWIND(.fnend) | ||
307 | ENDPROC(__gnu_mcount_nc) | ||
308 | |||
309 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
310 | ENTRY(ftrace_caller) | ||
311 | UNWIND(.fnstart) | ||
312 | __ftrace_caller | ||
313 | UNWIND(.fnend) | ||
314 | ENDPROC(ftrace_caller) | ||
315 | #endif | ||
316 | |||
317 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
318 | ENTRY(ftrace_graph_caller) | ||
319 | UNWIND(.fnstart) | ||
320 | __ftrace_graph_caller | ||
321 | UNWIND(.fnend) | ||
322 | ENDPROC(ftrace_graph_caller) | ||
323 | #endif | ||
324 | |||
325 | .purgem mcount_enter | ||
326 | .purgem mcount_get_lr | ||
327 | .purgem mcount_exit | ||
328 | |||
329 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
330 | .globl return_to_handler | ||
331 | return_to_handler: | ||
332 | stmdb sp!, {r0-r3} | ||
333 | mov r0, fp @ frame pointer | ||
334 | bl ftrace_return_to_handler | ||
335 | mov lr, r0 @ r0 has real ret addr | ||
336 | ldmia sp!, {r0-r3} | ||
337 | ret lr | ||
338 | #endif | ||
339 | |||
340 | ENTRY(ftrace_stub) | ||
341 | .Lftrace_stub: | ||
342 | ret lr | ||
343 | ENDPROC(ftrace_stub) | ||
344 | |||
345 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
346 | |||
347 | /*============================================================================= | 112 | /*============================================================================= |
348 | * SWI handler | 113 | * SWI handler |
349 | *----------------------------------------------------------------------------- | 114 | *----------------------------------------------------------------------------- |