~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/kernel/entry-ftrace.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  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  * When compiling with -pg, gcc inserts a call to the mcount routine at the
 11  * start of every function.  In mcount, apart from the function's address (in
 12  * lr), we need to get hold of the function's caller's address.
 13  *
 14  * Newer GCCs (4.4+) solve this problem by using a version of mcount with call
 15  * sites like:
 16  *
 17  *      push    {lr}
 18  *      bl      __gnu_mcount_nc
 19  *
 20  * With these compilers, frame pointers are not necessary.
 21  *
 22  * mcount can be thought of as a function called in the middle of a subroutine
 23  * call.  As such, it needs to be transparent for both the caller and the
 24  * callee: the original lr needs to be restored when leaving mcount, and no
 25  * registers should be clobbered.
 26  *
 27  * When using dynamic ftrace, we patch out the mcount call by a "add sp, #4"
 28  * instead of the __gnu_mcount_nc call (see arch/arm/kernel/ftrace.c).
 29  */
 30 
 31 .macro mcount_adjust_addr rd, rn
 32         bic     \rd, \rn, #1            @ clear the Thumb bit if present
 33         sub     \rd, \rd, #MCOUNT_INSN_SIZE
 34 .endm
 35 
 36 .macro __mcount suffix
 37         mcount_enter
 38         ldr_va  r2, ftrace_trace_function
 39         badr    r0, .Lftrace_stub
 40         cmp     r0, r2
 41         bne     1f
 42 
 43 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 44         ldr_va  r2, ftrace_graph_return
 45         cmp     r0, r2
 46         bne     ftrace_graph_caller\suffix
 47 
 48         ldr_va  r2, ftrace_graph_entry
 49         mov_l   r0, ftrace_graph_entry_stub
 50         cmp     r0, r2
 51         bne     ftrace_graph_caller\suffix
 52 #endif
 53 
 54         mcount_exit
 55 
 56 1:      mcount_get_lr   r1                      @ lr of instrumented func
 57         mcount_adjust_addr      r0, lr          @ instrumented function
 58         badr    lr, 2f
 59         mov     pc, r2
 60 2:      mcount_exit
 61 .endm
 62 
 63 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 64 
 65 .macro __ftrace_regs_caller
 66 
 67         str     lr, [sp, #-8]!  @ store LR as PC and make space for CPSR/OLD_R0,
 68                                 @ OLD_R0 will overwrite previous LR
 69 
 70         ldr     lr, [sp, #8]    @ get previous LR
 71 
 72         str     r0, [sp, #8]    @ write r0 as OLD_R0 over previous LR
 73 
 74         str     lr, [sp, #-4]!  @ store previous LR as LR
 75 
 76         add     lr, sp, #16     @ move in LR the value of SP as it was
 77                                 @ before the push {lr} of the mcount mechanism
 78 
 79         push    {r0-r11, ip, lr}
 80 
 81         @ stack content at this point:
 82         @ 0  4          48   52       56            60   64    68       72
 83         @ R0 | R1 | ... | IP | SP + 4 | previous LR | LR | PSR | OLD_R0 |
 84 
 85         mov     r3, sp                          @ struct pt_regs*
 86 
 87         ldr_va  r2, function_trace_op           @ pointer to the current
 88                                                 @ function tracing op
 89 
 90         ldr     r1, [sp, #S_LR]                 @ lr of instrumented func
 91 
 92         ldr     lr, [sp, #S_PC]                 @ get LR
 93 
 94         mcount_adjust_addr      r0, lr          @ instrumented function
 95 
 96         .globl ftrace_regs_call
 97 ftrace_regs_call:
 98         bl      ftrace_stub
 99 
100 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
101         .globl ftrace_graph_regs_call
102 ftrace_graph_regs_call:
103 ARM(    mov     r0, r0  )
104 THUMB(  nop.w           )
105 #endif
106 
107         @ pop saved regs
108         pop     {r0-r11, ip, lr}                @ restore r0 through r12
109         ldr     lr, [sp], #4                    @ restore LR
110         ldr     pc, [sp], #12
111 .endm
112 
113 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
114 .macro __ftrace_graph_regs_caller
115 
116 #ifdef CONFIG_UNWINDER_FRAME_POINTER
117         sub     r0, fp, #4              @ lr of instrumented routine (parent)
118 #else
119         add     r0, sp, #S_LR
120 #endif
121 
122         @ called from __ftrace_regs_caller
123         ldr     r1, [sp, #S_PC]         @ instrumented routine (func)
124         mcount_adjust_addr      r1, r1
125 
126         mov     r2, fpreg               @ frame pointer
127         add     r3, sp, #PT_REGS_SIZE
128         bl      prepare_ftrace_return
129 
130         @ pop registers saved in ftrace_regs_caller
131         pop     {r0-r11, ip, lr}                @ restore r0 through r12
132         ldr     lr, [sp], #4                    @ restore LR
133         ldr     pc, [sp], #12
134 
135 .endm
136 #endif
137 #endif
138 
139 .macro __ftrace_caller suffix
140         mcount_enter
141 
142         mcount_get_lr   r1                      @ lr of instrumented func
143         mcount_adjust_addr      r0, lr          @ instrumented function
144 
145 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
146         ldr_va  r2, function_trace_op           @ pointer to the current
147                                                 @ function tracing op
148         mov r3, #0                              @ regs is NULL
149 #endif
150 
151         .globl ftrace_call\suffix
152 ftrace_call\suffix:
153         bl      ftrace_stub
154 
155 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
156         .globl ftrace_graph_call\suffix
157 ftrace_graph_call\suffix:
158 ARM(    mov     r0, r0  )
159 THUMB(  nop.w           )
160 #endif
161 
162         mcount_exit
163 .endm
164 
165 .macro __ftrace_graph_caller
166 #ifdef CONFIG_UNWINDER_FRAME_POINTER
167         sub     r0, fp, #4              @ &lr of instrumented routine (&parent)
168 #else
169         add     r0, sp, #20
170 #endif
171 #ifdef CONFIG_DYNAMIC_FTRACE
172         @ called from __ftrace_caller, saved in mcount_enter
173         ldr     r1, [sp, #16]           @ instrumented routine (func)
174         mcount_adjust_addr      r1, r1
175 #else
176         @ called from __mcount, untouched in lr
177         mcount_adjust_addr      r1, lr  @ instrumented routine (func)
178 #endif
179         mov     r2, fpreg               @ frame pointer
180         add     r3, sp, #24
181         bl      prepare_ftrace_return
182         mcount_exit
183 .endm
184 
185 /*
186  * __gnu_mcount_nc
187  */
188 
189 .macro mcount_enter
190 /*
191  * This pad compensates for the push {lr} at the call site.  Note that we are
192  * unable to unwind through a function which does not otherwise save its lr.
193  */
194  UNWIND(.pad    #4)
195         stmdb   sp!, {r0-r3, lr}
196  UNWIND(.save   {r0-r3, lr})
197 .endm
198 
199 .macro mcount_get_lr reg
200         ldr     \reg, [sp, #20]
201 .endm
202 
203 .macro mcount_exit
204         ldmia   sp!, {r0-r3}
205         ldr     lr, [sp, #4]
206         ldr     pc, [sp], #8
207 .endm
208 
209 ENTRY(__gnu_mcount_nc)
210 UNWIND(.fnstart)
211 #ifdef CONFIG_DYNAMIC_FTRACE
212         push    {lr}
213         ldr     lr, [sp, #4]
214         ldr     pc, [sp], #8
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 ENTRY(return_to_handler)
260         stmdb   sp!, {r0-r3}
261         add     r0, sp, #16             @ sp at exit of instrumented routine
262         bl      ftrace_return_to_handler
263         mov     lr, r0                  @ r0 has real ret addr
264         ldmia   sp!, {r0-r3}
265         ret     lr
266 ENDPROC(return_to_handler)
267 #endif
268 
269 ENTRY(ftrace_stub)
270 .Lftrace_stub:
271         ret     lr
272 ENDPROC(ftrace_stub)
273 
274 ENTRY(ftrace_stub_graph)
275         ret     lr
276 ENDPROC(ftrace_stub_graph)
277 
278 #ifdef CONFIG_DYNAMIC_FTRACE
279 
280         __INIT
281 
282         .macro  init_tramp, dst:req
283 ENTRY(\dst\()_from_init)
284         ldr     pc, =\dst
285 ENDPROC(\dst\()_from_init)
286         .endm
287 
288         init_tramp      ftrace_caller
289 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
290         init_tramp      ftrace_regs_caller
291 #endif
292 #endif

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php