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 
90 ENTRY(ftrace_stub)
91 	jmp	lr
92 END(ftrace_stub)
93 
94 #ifndef CONFIG_DYNAMIC_FTRACE
95 ENTRY(_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
114 skip_ftrace:
115 	mcount_exit
116 #else
117 skip_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
132 END(_mcount)
133 #else /* CONFIG_DYNAMIC_FTRACE */
134 ENTRY(_mcount)
135 	mov	t1, lr
136 	ldw	lr, (sp, 0)
137 	addi	sp, 4
138 	jmp	t1
139 ENDPROC(_mcount)
140 
141 ENTRY(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
151 GLOBAL(ftrace_call)
152 	nop32_stub
153 
154 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
155 	nop
156 GLOBAL(ftrace_graph_call)
157 	nop32_stub
158 #endif
159 
160 	mcount_exit
161 ENDPROC(ftrace_caller)
162 #endif /* CONFIG_DYNAMIC_FTRACE */
163 
164 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
165 ENTRY(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
174 END(ftrace_graph_caller)
175 
176 ENTRY(return_to_handler)
177 	save_return_regs
178 	mov	a0, r8
179 	jsri	ftrace_return_to_handler
180 	restore_return_regs
181 	jmp	lr
182 END(return_to_handler)
183 #endif
184 
185 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
186 ENTRY(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
200 GLOBAL(ftrace_regs_call)
201 	nop32_stub
202 
203 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
204 	nop
205 GLOBAL(ftrace_graph_regs_call)
206 	nop32_stub
207 #endif
208 
209 	mcount_exit_regs
210 ENDPROC(ftrace_regs_caller)
211 #endif /* CONFIG_DYNAMIC_FTRACE */
212