aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/entry-common.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/entry-common.S')
-rw-r--r--arch/arm/kernel/entry-common.S235
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
1881: 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
1922: 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
202ftrace_call\suffix:
203 bl ftrace_stub
204
205#ifdef CONFIG_FUNCTION_GRAPH_TRACER
206 .globl ftrace_graph_call\suffix
207ftrace_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
247ENTRY(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
255ENDPROC(mcount)
256
257#ifdef CONFIG_DYNAMIC_FTRACE
258ENTRY(ftrace_caller_old)
259 __ftrace_caller _old
260ENDPROC(ftrace_caller_old)
261#endif
262
263#ifdef CONFIG_FUNCTION_GRAPH_TRACER
264ENTRY(ftrace_graph_caller_old)
265 __ftrace_graph_caller
266ENDPROC(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
297ENTRY(__gnu_mcount_nc)
298UNWIND(.fnstart)
299#ifdef CONFIG_DYNAMIC_FTRACE
300 mov ip, lr
301 ldmia sp!, {lr}
302 ret ip
303#else
304 __mcount
305#endif
306UNWIND(.fnend)
307ENDPROC(__gnu_mcount_nc)
308
309#ifdef CONFIG_DYNAMIC_FTRACE
310ENTRY(ftrace_caller)
311UNWIND(.fnstart)
312 __ftrace_caller
313UNWIND(.fnend)
314ENDPROC(ftrace_caller)
315#endif
316
317#ifdef CONFIG_FUNCTION_GRAPH_TRACER
318ENTRY(ftrace_graph_caller)
319UNWIND(.fnstart)
320 __ftrace_graph_caller
321UNWIND(.fnend)
322ENDPROC(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
331return_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
340ENTRY(ftrace_stub)
341.Lftrace_stub:
342 ret lr
343ENDPROC(ftrace_stub)
344
345#endif /* CONFIG_FUNCTION_TRACER */
346
347/*============================================================================= 112/*=============================================================================
348 * SWI handler 113 * SWI handler
349 *----------------------------------------------------------------------------- 114 *-----------------------------------------------------------------------------