summaryrefslogtreecommitdiffstats
path: root/arch/riscv/kernel/mcount-dyn.S
blob: 35a6ed76cb8b74e7806d211173fdb77dc25f9298 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2017 Andes Technology Corporation */

#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/asm.h>
#include <asm/csr.h>
#include <asm/unistd.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm-generic/export.h>
#include <asm/ftrace.h>

	.text

	.macro SAVE_ABI_STATE
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	addi    sp, sp, -48
	sd      s0, 32(sp)
	sd      ra, 40(sp)
	addi    s0, sp, 48
	sd      t0, 24(sp)
	sd      t1, 16(sp)
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	sd      t2, 8(sp)
#endif
#else
	addi	sp, sp, -16
	sd	s0, 0(sp)
	sd	ra, 8(sp)
	addi	s0, sp, 16
#endif
	.endm

	.macro RESTORE_ABI_STATE
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	ld	s0, 32(sp)
	ld	ra, 40(sp)
	addi	sp, sp, 48
#else
	ld	ra, 8(sp)
	ld	s0, 0(sp)
	addi	sp, sp, 16
#endif
	.endm

	.macro RESTORE_GRAPH_ARGS
	ld	a0, 24(sp)
	ld	a1, 16(sp)
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	a2, 8(sp)
#endif
	.endm

ENTRY(ftrace_graph_caller)
	addi	sp, sp, -16
	sd	s0, 0(sp)
	sd	ra, 8(sp)
	addi	s0, sp, 16
ftrace_graph_call:
	.global ftrace_graph_call
	/*
	 * Calling ftrace_enable/disable_ftrace_graph_caller would overwrite the
	 * call below.  Check ftrace_modify_all_code for details.
	 */
	call	ftrace_stub
	ld	ra, 8(sp)
	ld	s0, 0(sp)
	addi	sp, sp, 16
	ret
ENDPROC(ftrace_graph_caller)

ENTRY(ftrace_caller)
	/*
	 * a0: the address in the caller when calling ftrace_caller
	 * a1: the caller's return address
	 * a2: the address of global variable function_trace_op
	 */
	ld	a1, -8(s0)
	addi	a0, ra, -MCOUNT_INSN_SIZE
	la	t5, function_trace_op
	ld	a2, 0(t5)

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	/*
	 * the graph tracer (specifically, prepare_ftrace_return) needs these
	 * arguments but for now the function tracer occupies the regs, so we
	 * save them in temporary regs to recover later.
	 */
	addi	t0, s0, -8
	mv	t1, a0
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	t2, -16(s0)
#endif
#endif

	SAVE_ABI_STATE
ftrace_call:
	.global ftrace_call
	/*
	 * For the dynamic ftrace to work, here we should reserve at least
	 * 8 bytes for a functional auipc-jalr pair.  The following call
	 * serves this purpose.
	 *
	 * Calling ftrace_update_ftrace_func would overwrite the nops below.
	 * Check ftrace_modify_all_code for details.
	 */
	call	ftrace_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	RESTORE_GRAPH_ARGS
	call	ftrace_graph_caller
#endif

	RESTORE_ABI_STATE
	ret
ENDPROC(ftrace_caller)

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
	.macro SAVE_ALL
	addi	sp, sp, -(PT_SIZE_ON_STACK+16)
	sd	s0, (PT_SIZE_ON_STACK)(sp)
	sd	ra, (PT_SIZE_ON_STACK+8)(sp)
	addi	s0, sp, (PT_SIZE_ON_STACK+16)

	sd x1,  PT_RA(sp)
	sd x2,  PT_SP(sp)
	sd x3,  PT_GP(sp)
	sd x4,  PT_TP(sp)
	sd x5,  PT_T0(sp)
	sd x6,  PT_T1(sp)
	sd x7,  PT_T2(sp)
	sd x8,  PT_S0(sp)
	sd x9,  PT_S1(sp)
	sd x10, PT_A0(sp)
	sd x11, PT_A1(sp)
	sd x12, PT_A2(sp)
	sd x13, PT_A3(sp)
	sd x14, PT_A4(sp)
	sd x15, PT_A5(sp)
	sd x16, PT_A6(sp)
	sd x17, PT_A7(sp)
	sd x18, PT_S2(sp)
	sd x19, PT_S3(sp)
	sd x20, PT_S4(sp)
	sd x21, PT_S5(sp)
	sd x22, PT_S6(sp)
	sd x23, PT_S7(sp)
	sd x24, PT_S8(sp)
	sd x25, PT_S9(sp)
	sd x26, PT_S10(sp)
	sd x27, PT_S11(sp)
	sd x28, PT_T3(sp)
	sd x29, PT_T4(sp)
	sd x30, PT_T5(sp)
	sd x31, PT_T6(sp)
	.endm

	.macro RESTORE_ALL
	ld x1,  PT_RA(sp)
	ld x2,  PT_SP(sp)
	ld x3,  PT_GP(sp)
	ld x4,  PT_TP(sp)
	ld x5,  PT_T0(sp)
	ld x6,  PT_T1(sp)
	ld x7,  PT_T2(sp)
	ld x8,  PT_S0(sp)
	ld x9,  PT_S1(sp)
	ld x10, PT_A0(sp)
	ld x11, PT_A1(sp)
	ld x12, PT_A2(sp)
	ld x13, PT_A3(sp)
	ld x14, PT_A4(sp)
	ld x15, PT_A5(sp)
	ld x16, PT_A6(sp)
	ld x17, PT_A7(sp)
	ld x18, PT_S2(sp)
	ld x19, PT_S3(sp)
	ld x20, PT_S4(sp)
	ld x21, PT_S5(sp)
	ld x22, PT_S6(sp)
	ld x23, PT_S7(sp)
	ld x24, PT_S8(sp)
	ld x25, PT_S9(sp)
	ld x26, PT_S10(sp)
	ld x27, PT_S11(sp)
	ld x28, PT_T3(sp)
	ld x29, PT_T4(sp)
	ld x30, PT_T5(sp)
	ld x31, PT_T6(sp)

	ld	s0, (PT_SIZE_ON_STACK)(sp)
	ld	ra, (PT_SIZE_ON_STACK+8)(sp)
	addi	sp, sp, (PT_SIZE_ON_STACK+16)
	.endm

	.macro RESTORE_GRAPH_REG_ARGS
	ld	a0, PT_T0(sp)
	ld	a1, PT_T1(sp)
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	a2, PT_T2(sp)
#endif
	.endm

/*
 * Most of the contents are the same as ftrace_caller.
 */
ENTRY(ftrace_regs_caller)
	/*
	 * a3: the address of all registers in the stack
	 */
	ld	a1, -8(s0)
	addi	a0, ra, -MCOUNT_INSN_SIZE
	la	t5, function_trace_op
	ld	a2, 0(t5)
	addi	a3, sp, -(PT_SIZE_ON_STACK+16)

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	addi	t0, s0, -8
	mv	t1, a0
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	t2, -16(s0)
#endif
#endif
	SAVE_ALL

ftrace_regs_call:
	.global ftrace_regs_call
	call	ftrace_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	RESTORE_GRAPH_REG_ARGS
	call	ftrace_graph_caller
#endif

	RESTORE_ALL
	ret
ENDPROC(ftrace_regs_caller)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */