1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/linkage.h>
5#include <asm/ftrace.h>
6#include <abi/entry.h>
7#include <asm/asm-offsets.h>
8
9/*
10 * csky-gcc with -pg will put the following asm after prologue:
11 *      push	r15
12 *      jsri	_mcount
13 *
14 * stack layout after mcount_enter in _mcount():
15 *
16 * current sp => 0:+-------+
17 *                 | a0-a3 | -> must save all argument regs
18 *             +16:+-------+
19 *                 | lr    | -> _mcount lr (instrumente function's pc)
20 *             +20:+-------+
21 *                 | fp=r8 | -> instrumented function fp
22 *             +24:+-------+
23 *                 | plr   | -> instrumented function lr (parent's pc)
24 *                 +-------+
25 */
26
27.macro mcount_enter
28	subi	sp, 24
29	stw	a0, (sp, 0)
30	stw	a1, (sp, 4)
31	stw	a2, (sp, 8)
32	stw	a3, (sp, 12)
33	stw	lr, (sp, 16)
34	stw	r8, (sp, 20)
35.endm
36
37.macro mcount_exit
38	ldw	a0, (sp, 0)
39	ldw	a1, (sp, 4)
40	ldw	a2, (sp, 8)
41	ldw	a3, (sp, 12)
42	ldw	t1, (sp, 16)
43	ldw	r8, (sp, 20)
44	ldw	lr, (sp, 24)
45	addi	sp, 28
46	jmp	t1
47.endm
48
49.macro mcount_enter_regs
50	subi	sp, 8
51	stw	lr, (sp, 0)
52	stw	r8, (sp, 4)
53	SAVE_REGS_FTRACE
54.endm
55
56.macro mcount_exit_regs
57	RESTORE_REGS_FTRACE
58	subi	sp, 152
59	ldw	t1, (sp, 4)
60	addi	sp, 152
61	ldw	r8, (sp, 4)
62	ldw	lr, (sp, 8)
63	addi	sp, 12
64	jmp	t1
65.endm
66
67.macro save_return_regs
68	subi	sp, 16
69	stw	a0, (sp, 0)
70	stw	a1, (sp, 4)
71	stw	a2, (sp, 8)
72	stw	a3, (sp, 12)
73.endm
74
75.macro restore_return_regs
76	mov	lr, a0
77	ldw	a0, (sp, 0)
78	ldw	a1, (sp, 4)
79	ldw	a2, (sp, 8)
80	ldw	a3, (sp, 12)
81	addi	sp, 16
82.endm
83
84.macro nop32_stub
85	nop32
86	nop32
87	nop32
88.endm
89
90ENTRY(ftrace_stub)
91	jmp	lr
92END(ftrace_stub)
93
94#ifndef CONFIG_DYNAMIC_FTRACE
95ENTRY(_mcount)
96	mcount_enter
97
98	/* r26 is link register, only used with jsri translation */
99	lrw	r26, ftrace_trace_function
100	ldw	r26, (r26, 0)
101	lrw	a1, ftrace_stub
102	cmpne	r26, a1
103	bf	skip_ftrace
104
105	mov	a0, lr
106	subi	a0, 4
107	ldw	a1, (sp, 24)
108	lrw	a2, function_trace_op
109	ldw	a2, (a2, 0)
110
111	jsr	r26
112
113#ifndef CONFIG_FUNCTION_GRAPH_TRACER
114skip_ftrace:
115	mcount_exit
116#else
117skip_ftrace:
118	lrw	a0, ftrace_graph_return
119	ldw	a0, (a0, 0)
120	lrw	a1, ftrace_stub
121	cmpne	a0, a1
122	bt	ftrace_graph_caller
123
124	lrw	a0, ftrace_graph_entry
125	ldw	a0, (a0, 0)
126	lrw	a1, ftrace_graph_entry_stub
127	cmpne	a0, a1
128	bt	ftrace_graph_caller
129
130	mcount_exit
131#endif
132END(_mcount)
133#else /* CONFIG_DYNAMIC_FTRACE */
134ENTRY(_mcount)
135	mov	t1, lr
136	ldw	lr, (sp, 0)
137	addi	sp, 4
138	jmp	t1
139ENDPROC(_mcount)
140
141ENTRY(ftrace_caller)
142	mcount_enter
143
144	ldw	a0, (sp, 16)
145	subi	a0, 4
146	ldw	a1, (sp, 24)
147	lrw	a2, function_trace_op
148	ldw	a2, (a2, 0)
149
150	nop
151GLOBAL(ftrace_call)
152	nop32_stub
153
154#ifdef CONFIG_FUNCTION_GRAPH_TRACER
155	nop
156GLOBAL(ftrace_graph_call)
157	nop32_stub
158#endif
159
160	mcount_exit
161ENDPROC(ftrace_caller)
162#endif /* CONFIG_DYNAMIC_FTRACE */
163
164#ifdef CONFIG_FUNCTION_GRAPH_TRACER
165ENTRY(ftrace_graph_caller)
166	mov	a0, sp
167	addi	a0, 24
168	ldw	a1, (sp, 16)
169	subi	a1, 4
170	mov	a2, r8
171	lrw	r26, prepare_ftrace_return
172	jsr	r26
173	mcount_exit
174END(ftrace_graph_caller)
175
176ENTRY(return_to_handler)
177	save_return_regs
178	mov	a0, r8
179	jsri	ftrace_return_to_handler
180	restore_return_regs
181	jmp	lr
182END(return_to_handler)
183#endif
184
185#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
186ENTRY(ftrace_regs_caller)
187	mcount_enter_regs
188
189	lrw	t1, PT_FRAME_SIZE
190	add	t1, sp
191
192	ldw	a0, (t1, 0)
193	subi	a0, 4
194	ldw	a1, (t1, 8)
195	lrw	a2, function_trace_op
196	ldw	a2, (a2, 0)
197	mov	a3, sp
198
199	nop
200GLOBAL(ftrace_regs_call)
201	nop32_stub
202
203#ifdef CONFIG_FUNCTION_GRAPH_TRACER
204	nop
205GLOBAL(ftrace_graph_regs_call)
206	nop32_stub
207#endif
208
209	mcount_exit_regs
210ENDPROC(ftrace_regs_caller)
211#endif /* CONFIG_DYNAMIC_FTRACE */
212