1
2
3 #include <asm/assembler.h>
4 #include <asm/ftrace.h>
5 #include <asm/unwind.h>
6
7 #include "entry-header.S"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 .macro mcount_adjust_addr rd, rn
35 bic \rd, \rn, #1 @ clear the Thumb bit if present
36 sub \rd, \rd, #MCOUNT_INSN_SIZE
37 .endm
38
39 .macro __mcount suffix
40 mcount_enter
41 ldr r0, =ftrace_trace_function
42 ldr r2, [r0]
43 adr r0, .Lftrace_stub
44 cmp r0, r2
45 bne 1f
46
47 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
48 ldr r1, =ftrace_graph_return
49 ldr r2, [r1]
50 cmp r0, r2
51 bne ftrace_graph_caller\suffix
52
53 ldr r1, =ftrace_graph_entry
54 ldr r2, [r1]
55 ldr r0, =ftrace_graph_entry_stub
56 cmp r0, r2
57 bne ftrace_graph_caller\suffix
58 #endif
59
60 mcount_exit
61
62 1: mcount_get_lr r1 @ lr of instrumented func
63 mcount_adjust_addr r0, lr @ instrumented function
64 badr lr, 2f
65 mov pc, r2
66 2: mcount_exit
67 .endm
68
69 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
70
71 .macro __ftrace_regs_caller
72
73 sub sp, sp, #8 @ space for PC and CPSR OLD_R0,
74 @ OLD_R0 will overwrite previous LR
75
76 add ip, sp, #12 @ move in IP the value of SP as it was
77 @ before the push {lr} of the mcount mechanism
78
79 str lr, [sp, #0] @ store LR instead of PC
80
81 ldr lr, [sp, #8] @ get previous LR
82
83 str r0, [sp, #8] @ write r0 as OLD_R0 over previous LR
84
85 stmdb sp!, {ip, lr}
86 stmdb sp!, {r0-r11, lr}
87
88 @ stack content at this point:
89 @ 0 4 48 52 56 60 64 68 72
90 @ R0 | R1 | ... | LR | SP + 4 | previous LR | LR | PSR | OLD_R0 |
91
92 mov r3, sp @ struct pt_regs*
93
94 ldr r2, =function_trace_op
95 ldr r2, [r2] @ pointer to the current
96 @ function tracing op
97
98 ldr r1, [sp, #S_LR] @ lr of instrumented func
99
100 ldr lr, [sp, #S_PC] @ get LR
101
102 mcount_adjust_addr r0, lr @ instrumented function
103
104 .globl ftrace_regs_call
105 ftrace_regs_call:
106 bl ftrace_stub
107
108 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
109 .globl ftrace_graph_regs_call
110 ftrace_graph_regs_call:
111 mov r0, r0
112 #endif
113
114 @ pop saved regs
115 ldmia sp!, {r0-r12} @ restore r0 through r12
116 ldr ip, [sp, #8] @ restore PC
117 ldr lr, [sp, #4] @ restore LR
118 ldr sp, [sp, #0] @ restore SP
119 mov pc, ip @ return
120 .endm
121
122 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
123 .macro __ftrace_graph_regs_caller
124
125 sub r0, fp, #4 @ lr of instrumented routine (parent)
126
127 @ called from __ftrace_regs_caller
128 ldr r1, [sp, #S_PC] @ instrumented routine (func)
129 mcount_adjust_addr r1, r1
130
131 mov r2, fp @ frame pointer
132 bl prepare_ftrace_return
133
134 @ pop registers saved in ftrace_regs_caller
135 ldmia sp!, {r0-r12} @ restore r0 through r12
136 ldr ip, [sp, #8] @ restore PC
137 ldr lr, [sp, #4] @ restore LR
138 ldr sp, [sp, #0] @ restore SP
139 mov pc, ip @ return
140
141 .endm
142 #endif
143 #endif
144
145 .macro __ftrace_caller suffix
146 mcount_enter
147
148 mcount_get_lr r1 @ lr of instrumented func
149 mcount_adjust_addr r0, lr @ instrumented function
150
151 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
152 ldr r2, =function_trace_op
153 ldr r2, [r2] @ pointer to the current
154 @ function tracing op
155 mov r3, #0 @ regs is NULL
156 #endif
157
158 .globl ftrace_call\suffix
159 ftrace_call\suffix:
160 bl ftrace_stub
161
162 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
163 .globl ftrace_graph_call\suffix
164 ftrace_graph_call\suffix:
165 mov r0, r0
166 #endif
167
168 mcount_exit
169 .endm
170
171 .macro __ftrace_graph_caller
172 sub r0, fp, #4 @ &lr of instrumented routine (&parent)
173 #ifdef CONFIG_DYNAMIC_FTRACE
174 @ called from __ftrace_caller, saved in mcount_enter
175 ldr r1, [sp, #16] @ instrumented routine (func)
176 mcount_adjust_addr r1, r1
177 #else
178 @ called from __mcount, untouched in lr
179 mcount_adjust_addr r1, lr @ instrumented routine (func)
180 #endif
181 mov r2, fp @ frame pointer
182 bl prepare_ftrace_return
183 mcount_exit
184 .endm
185
186
187
188
189
190 .macro mcount_enter
191
192
193
194
195 UNWIND(.pad #4)
196 stmdb sp!, {r0-r3, lr}
197 UNWIND(.save {r0-r3, lr})
198 .endm
199
200 .macro mcount_get_lr reg
201 ldr \reg, [sp, #20]
202 .endm
203
204 .macro mcount_exit
205 ldmia sp!, {r0-r3, ip, lr}
206 ret ip
207 .endm
208
209 ENTRY(__gnu_mcount_nc)
210 UNWIND(.fnstart)
211 #ifdef CONFIG_DYNAMIC_FTRACE
212 mov ip, lr
213 ldmia sp!, {lr}
214 ret ip
215 #else
216 __mcount
217 #endif
218 UNWIND(.fnend)
219 ENDPROC(__gnu_mcount_nc)
220
221 #ifdef CONFIG_DYNAMIC_FTRACE
222 ENTRY(ftrace_caller)
223 UNWIND(.fnstart)
224 __ftrace_caller
225 UNWIND(.fnend)
226 ENDPROC(ftrace_caller)
227
228 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
229 ENTRY(ftrace_regs_caller)
230 UNWIND(.fnstart)
231 __ftrace_regs_caller
232 UNWIND(.fnend)
233 ENDPROC(ftrace_regs_caller)
234 #endif
235
236 #endif
237
238 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
239 ENTRY(ftrace_graph_caller)
240 UNWIND(.fnstart)
241 __ftrace_graph_caller
242 UNWIND(.fnend)
243 ENDPROC(ftrace_graph_caller)
244
245 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
246 ENTRY(ftrace_graph_regs_caller)
247 UNWIND(.fnstart)
248 __ftrace_graph_regs_caller
249 UNWIND(.fnend)
250 ENDPROC(ftrace_graph_regs_caller)
251 #endif
252 #endif
253
254 .purgem mcount_enter
255 .purgem mcount_get_lr
256 .purgem mcount_exit
257
258 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
259 .globl return_to_handler
260 return_to_handler:
261 stmdb sp!, {r0-r3}
262 mov r0, fp @ frame pointer
263 bl ftrace_return_to_handler
264 mov lr, r0 @ r0 has real ret addr
265 ldmia sp!, {r0-r3}
266 ret lr
267 #endif
268
269 ENTRY(ftrace_stub)
270 .Lftrace_stub:
271 ret lr
272 ENDPROC(ftrace_stub)