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 | |