1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Split from entry_32.S
4 */
5
6#include <linux/magic.h>
7#include <asm/reg.h>
8#include <asm/ppc_asm.h>
9#include <asm/asm-offsets.h>
10#include <asm/ftrace.h>
11#include <asm/export.h>
12
13_GLOBAL(mcount)
14_GLOBAL(_mcount)
15	/*
16	 * It is required that _mcount on PPC32 must preserve the
17	 * link register. But we have r0 to play with. We use r0
18	 * to push the return address back to the caller of mcount
19	 * into the ctr register, restore the link register and
20	 * then jump back using the ctr register.
21	 */
22	mflr	r0
23	mtctr	r0
24	lwz	r0, 4(r1)
25	mtlr	r0
26	bctr
27
28_GLOBAL(ftrace_caller)
29	MCOUNT_SAVE_FRAME
30	/* r3 ends up with link register */
31	subi	r3, r3, MCOUNT_INSN_SIZE
32.globl ftrace_call
33ftrace_call:
34	bl	ftrace_stub
35	nop
36#ifdef CONFIG_FUNCTION_GRAPH_TRACER
37.globl ftrace_graph_call
38ftrace_graph_call:
39	b	ftrace_graph_stub
40_GLOBAL(ftrace_graph_stub)
41#endif
42	MCOUNT_RESTORE_FRAME
43	/* old link register ends up in ctr reg */
44	bctr
45
46EXPORT_SYMBOL(_mcount)
47
48_GLOBAL(ftrace_stub)
49	blr
50
51#ifdef CONFIG_FUNCTION_GRAPH_TRACER
52_GLOBAL(ftrace_graph_caller)
53	addi	r5, r1, 48
54	/* load r4 with local address */
55	lwz	r4, 44(r1)
56	subi	r4, r4, MCOUNT_INSN_SIZE
57
58	/* Grab the LR out of the caller stack frame */
59	lwz	r3,52(r1)
60
61	bl	prepare_ftrace_return
62	nop
63
64        /*
65         * prepare_ftrace_return gives us the address we divert to.
66         * Change the LR in the callers stack frame to this.
67         */
68	stw	r3,52(r1)
69
70	MCOUNT_RESTORE_FRAME
71	/* old link register ends up in ctr reg */
72	bctr
73
74_GLOBAL(return_to_handler)
75	/* need to save return values */
76	stwu	r1, -32(r1)
77	stw	r3, 20(r1)
78	stw	r4, 16(r1)
79	stw	r31, 12(r1)
80	mr	r31, r1
81
82	bl	ftrace_return_to_handler
83	nop
84
85	/* return value has real return address */
86	mtlr	r3
87
88	lwz	r3, 20(r1)
89	lwz	r4, 16(r1)
90	lwz	r31,12(r1)
91	lwz	r1, 0(r1)
92
93	/* Jump back to real return address */
94	blr
95#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
96