]> Git Repo - J-linux.git/blob - arch/powerpc/kernel/trace/ftrace_entry.S
Merge patch series "riscv: Extension parsing fixes"
[J-linux.git] / arch / powerpc / kernel / trace / ftrace_entry.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Split from ftrace_64.S
4  */
5
6 #include <linux/export.h>
7 #include <linux/magic.h>
8 #include <asm/ppc_asm.h>
9 #include <asm/asm-offsets.h>
10 #include <asm/ftrace.h>
11 #include <asm/ppc-opcode.h>
12 #include <asm/thread_info.h>
13 #include <asm/bug.h>
14 #include <asm/ptrace.h>
15
16 /*
17  *
18  * ftrace_caller()/ftrace_regs_caller() is the function that replaces _mcount()
19  * when ftrace is active.
20  *
21  * We arrive here after a function A calls function B, and we are the trace
22  * function for B. When we enter r1 points to A's stack frame, B has not yet
23  * had a chance to allocate one yet.
24  *
25  * Additionally r2 may point either to the TOC for A, or B, depending on
26  * whether B did a TOC setup sequence before calling us.
27  *
28  * On entry the LR points back to the _mcount() call site, and r0 holds the
29  * saved LR as it was on entry to B, ie. the original return address at the
30  * call site in A.
31  *
32  * Our job is to save the register state into a struct pt_regs (on the stack)
33  * and then arrange for the ftrace function to be called.
34  */
35 .macro  ftrace_regs_entry allregs
36         /* Create a minimal stack frame for representing B */
37         PPC_STLU        r1, -STACK_FRAME_MIN_SIZE(r1)
38
39         /* Create our stack frame + pt_regs */
40         PPC_STLU        r1,-SWITCH_FRAME_SIZE(r1)
41
42         /* Save all gprs to pt_regs */
43         SAVE_GPR(0, r1)
44         SAVE_GPRS(3, 10, r1)
45
46 #ifdef CONFIG_PPC64
47         /* Save the original return address in A's stack frame */
48         std     r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1)
49         /* Ok to continue? */
50         lbz     r3, PACA_FTRACE_ENABLED(r13)
51         cmpdi   r3, 0
52         beq     ftrace_no_trace
53 #endif
54
55         .if \allregs == 1
56         SAVE_GPR(2, r1)
57         SAVE_GPRS(11, 31, r1)
58         .else
59 #ifdef CONFIG_LIVEPATCH_64
60         SAVE_GPR(14, r1)
61 #endif
62         .endif
63
64         /* Save previous stack pointer (r1) */
65         addi    r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
66         PPC_STL r8, GPR1(r1)
67
68         .if \allregs == 1
69         /* Load special regs for save below */
70         mfmsr   r8
71         mfctr   r9
72         mfxer   r10
73         mfcr    r11
74         .else
75         /* Clear MSR to flag as ftrace_caller versus frace_regs_caller */
76         li      r8, 0
77         .endif
78
79         /* Get the _mcount() call site out of LR */
80         mflr    r7
81         /* Save it as pt_regs->nip */
82         PPC_STL r7, _NIP(r1)
83         /* Also save it in B's stackframe header for proper unwind */
84         PPC_STL r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
85         /* Save the read LR in pt_regs->link */
86         PPC_STL r0, _LINK(r1)
87
88 #ifdef CONFIG_PPC64
89         /* Save callee's TOC in the ABI compliant location */
90         std     r2, STK_GOT(r1)
91         LOAD_PACA_TOC()         /* get kernel TOC in r2 */
92         LOAD_REG_ADDR(r3, function_trace_op)
93         ld      r5,0(r3)
94 #else
95         lis     r3,function_trace_op@ha
96         lwz     r5,function_trace_op@l(r3)
97 #endif
98
99 #ifdef CONFIG_LIVEPATCH_64
100         mr      r14, r7         /* remember old NIP */
101 #endif
102
103         /* Calculate ip from nip-4 into r3 for call below */
104         subi    r3, r7, MCOUNT_INSN_SIZE
105
106         /* Put the original return address in r4 as parent_ip */
107         mr      r4, r0
108
109         /* Save special regs */
110         PPC_STL r8, _MSR(r1)
111         .if \allregs == 1
112         PPC_STL r9, _CTR(r1)
113         PPC_STL r10, _XER(r1)
114         PPC_STL r11, _CCR(r1)
115         .endif
116
117         /* Load &pt_regs in r6 for call below */
118         addi    r6, r1, STACK_INT_FRAME_REGS
119 .endm
120
121 .macro  ftrace_regs_exit allregs
122         /* Load ctr with the possibly modified NIP */
123         PPC_LL  r3, _NIP(r1)
124         mtctr   r3
125
126 #ifdef CONFIG_LIVEPATCH_64
127         cmpd    r14, r3         /* has NIP been altered? */
128 #endif
129
130         /* Restore gprs */
131         .if \allregs == 1
132         REST_GPRS(2, 31, r1)
133         .else
134         REST_GPRS(3, 10, r1)
135 #ifdef CONFIG_LIVEPATCH_64
136         REST_GPR(14, r1)
137 #endif
138         .endif
139
140         /* Restore possibly modified LR */
141         PPC_LL  r0, _LINK(r1)
142         mtlr    r0
143
144 #ifdef CONFIG_PPC64
145         /* Restore callee's TOC */
146         ld      r2, STK_GOT(r1)
147 #endif
148
149         /* Pop our stack frame */
150         addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
151
152 #ifdef CONFIG_LIVEPATCH_64
153         /* Based on the cmpd above, if the NIP was altered handle livepatch */
154         bne-    livepatch_handler
155 #endif
156         bctr                    /* jump after _mcount site */
157 .endm
158
159 _GLOBAL(ftrace_regs_caller)
160         ftrace_regs_entry 1
161         /* ftrace_call(r3, r4, r5, r6) */
162 .globl ftrace_regs_call
163 ftrace_regs_call:
164         bl      ftrace_stub
165         ftrace_regs_exit 1
166
167 _GLOBAL(ftrace_caller)
168         ftrace_regs_entry 0
169         /* ftrace_call(r3, r4, r5, r6) */
170 .globl ftrace_call
171 ftrace_call:
172         bl      ftrace_stub
173         ftrace_regs_exit 0
174
175 _GLOBAL(ftrace_stub)
176         blr
177
178 #ifdef CONFIG_PPC64
179 ftrace_no_trace:
180         mflr    r3
181         mtctr   r3
182         REST_GPR(3, r1)
183         addi    r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
184         mtlr    r0
185         bctr
186 #endif
187
188 #ifdef CONFIG_LIVEPATCH_64
189         /*
190          * This function runs in the mcount context, between two functions. As
191          * such it can only clobber registers which are volatile and used in
192          * function linkage.
193          *
194          * We get here when a function A, calls another function B, but B has
195          * been live patched with a new function C.
196          *
197          * On entry:
198          *  - we have no stack frame and can not allocate one
199          *  - LR points back to the original caller (in A)
200          *  - CTR holds the new NIP in C
201          *  - r0, r11 & r12 are free
202          */
203 livepatch_handler:
204         ld      r12, PACA_THREAD_INFO(r13)
205
206         /* Allocate 3 x 8 bytes */
207         ld      r11, TI_livepatch_sp(r12)
208         addi    r11, r11, 24
209         std     r11, TI_livepatch_sp(r12)
210
211         /* Save toc & real LR on livepatch stack */
212         std     r2,  -24(r11)
213         mflr    r12
214         std     r12, -16(r11)
215
216         /* Store stack end marker */
217         lis     r12, STACK_END_MAGIC@h
218         ori     r12, r12, STACK_END_MAGIC@l
219         std     r12, -8(r11)
220
221         /* Put ctr in r12 for global entry and branch there */
222         mfctr   r12
223         bctrl
224
225         /*
226          * Now we are returning from the patched function to the original
227          * caller A. We are free to use r11, r12 and we can use r2 until we
228          * restore it.
229          */
230
231         ld      r12, PACA_THREAD_INFO(r13)
232
233         ld      r11, TI_livepatch_sp(r12)
234
235         /* Check stack marker hasn't been trashed */
236         lis     r2,  STACK_END_MAGIC@h
237         ori     r2,  r2, STACK_END_MAGIC@l
238         ld      r12, -8(r11)
239 1:      tdne    r12, r2
240         EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0
241
242         /* Restore LR & toc from livepatch stack */
243         ld      r12, -16(r11)
244         mtlr    r12
245         ld      r2,  -24(r11)
246
247         /* Pop livepatch stack frame */
248         ld      r12, PACA_THREAD_INFO(r13)
249         subi    r11, r11, 24
250         std     r11, TI_livepatch_sp(r12)
251
252         /* Return to original caller of live patched function */
253         blr
254 #endif /* CONFIG_LIVEPATCH */
255
256 #ifndef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY
257 _GLOBAL(mcount)
258 _GLOBAL(_mcount)
259 EXPORT_SYMBOL(_mcount)
260         mflr    r12
261         mtctr   r12
262         mtlr    r0
263         bctr
264 #endif
265
266 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
267 _GLOBAL(return_to_handler)
268         /* need to save return values */
269 #ifdef CONFIG_PPC64
270         std     r4,  -32(r1)
271         std     r3,  -24(r1)
272         /* save TOC */
273         std     r2,  -16(r1)
274         std     r31, -8(r1)
275         mr      r31, r1
276         stdu    r1, -112(r1)
277
278         /*
279          * We might be called from a module.
280          * Switch to our TOC to run inside the core kernel.
281          */
282         LOAD_PACA_TOC()
283 #else
284         stwu    r1, -16(r1)
285         stw     r3, 8(r1)
286         stw     r4, 12(r1)
287 #endif
288
289         bl      ftrace_return_to_handler
290         nop
291
292         /* return value has real return address */
293         mtlr    r3
294
295 #ifdef CONFIG_PPC64
296         ld      r1, 0(r1)
297         ld      r4,  -32(r1)
298         ld      r3,  -24(r1)
299         ld      r2,  -16(r1)
300         ld      r31, -8(r1)
301 #else
302         lwz     r3, 8(r1)
303         lwz     r4, 12(r1)
304         addi    r1, r1, 16
305 #endif
306
307         /* Jump back to real return address */
308         blr
309 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
310
311 .pushsection ".tramp.ftrace.text","aw",@progbits;
312 .globl ftrace_tramp_text
313 ftrace_tramp_text:
314         .space 32
315 .popsection
316
317 .pushsection ".tramp.ftrace.init","aw",@progbits;
318 .globl ftrace_tramp_init
319 ftrace_tramp_init:
320         .space 32
321 .popsection
This page took 0.043545 seconds and 4 git commands to generate.