aboutsummaryrefslogtreecommitdiff
path: root/arch/csky/abiv2/mcount.S
blob: d745e10c10b0268302cf34a0d3376c6f1ca0928f (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
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#include <linux/linkage.h>
#include <asm/ftrace.h>
#include <abi/entry.h>
#include <asm/asm-offsets.h>

/*
 * csky-gcc with -pg will put the following asm after prologue:
 *      push	r15
 *      jsri	_mcount
 *
 * stack layout after mcount_enter in _mcount():
 *
 * current sp => 0:+-------+
 *                 | a0-a3 | -> must save all argument regs
 *             +16:+-------+
 *                 | lr    | -> _mcount lr (instrumente function's pc)
 *             +20:+-------+
 *                 | fp=r8 | -> instrumented function fp
 *             +24:+-------+
 *                 | plr   | -> instrumented function lr (parent's pc)
 *                 +-------+
 */

.macro mcount_enter
	subi	sp, 24
	stw	a0, (sp, 0)
	stw	a1, (sp, 4)
	stw	a2, (sp, 8)
	stw	a3, (sp, 12)
	stw	lr, (sp, 16)
	stw	r8, (sp, 20)
.endm

.macro mcount_exit
	ldw	a0, (sp, 0)
	ldw	a1, (sp, 4)
	ldw	a2, (sp, 8)
	ldw	a3, (sp, 12)
	ldw	t1, (sp, 16)
	ldw	r8, (sp, 20)
	ldw	lr, (sp, 24)
	addi	sp, 28
	jmp	t1
.endm

.macro mcount_enter_regs
	subi	sp, 8
	stw	lr, (sp, 0)
	stw	r8, (sp, 4)
	SAVE_REGS_FTRACE
.endm

.macro mcount_exit_regs
	RESTORE_REGS_FTRACE
	subi	sp, 152
	ldw	t1, (sp, 4)
	addi	sp, 152
	ldw	r8, (sp, 4)
	ldw	lr, (sp, 8)
	addi	sp, 12
	jmp	t1
.endm

.macro save_return_regs
	subi	sp, 16
	stw	a0, (sp, 0)
	stw	a1, (sp, 4)
	stw	a2, (sp, 8)
	stw	a3, (sp, 12)
.endm

.macro restore_return_regs
	mov	lr, a0
	ldw	a0, (sp, 0)
	ldw	a1, (sp, 4)
	ldw	a2, (sp, 8)
	ldw	a3, (sp, 12)
	addi	sp, 16
.endm

.macro nop32_stub
	nop32
	nop32
	nop32
.endm

ENTRY(ftrace_stub)
	jmp	lr
END(ftrace_stub)

#ifndef CONFIG_DYNAMIC_FTRACE
ENTRY(_mcount)
	mcount_enter

	/* r26 is link register, only used with jsri translation */
	lrw	r26, ftrace_trace_function
	ldw	r26, (r26, 0)
	lrw	a1, ftrace_stub
	cmpne	r26, a1
	bf	skip_ftrace

	mov	a0, lr
	subi	a0, 4
	ldw	a1, (sp, 24)
	lrw	a2, function_trace_op
	ldw	a2, (a2, 0)

	jsr	r26

#ifndef CONFIG_FUNCTION_GRAPH_TRACER
skip_ftrace:
	mcount_exit
#else
skip_ftrace:
	lrw	a0, ftrace_graph_return
	ldw	a0, (a0, 0)
	lrw	a1, ftrace_stub
	cmpne	a0, a1
	bt	ftrace_graph_caller

	lrw	a0, ftrace_graph_entry
	ldw	a0, (a0, 0)
	lrw	a1, ftrace_graph_entry_stub
	cmpne	a0, a1
	bt	ftrace_graph_caller

	mcount_exit
#endif
END(_mcount)
#else /* CONFIG_DYNAMIC_FTRACE */
ENTRY(_mcount)
	mov	t1, lr
	ldw	lr, (sp, 0)
	addi	sp, 4
	jmp	t1
ENDPROC(_mcount)

ENTRY(ftrace_caller)
	mcount_enter

	ldw	a0, (sp, 16)
	subi	a0, 4
	ldw	a1, (sp, 24)
	lrw	a2, function_trace_op
	ldw	a2, (a2, 0)

	nop
GLOBAL(ftrace_call)
	nop32_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	nop
GLOBAL(ftrace_graph_call)
	nop32_stub
#endif

	mcount_exit
ENDPROC(ftrace_caller)
#endif /* CONFIG_DYNAMIC_FTRACE */

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ENTRY(ftrace_graph_caller)
	mov	a0, sp
	addi	a0, 24
	ldw	a1, (sp, 16)
	subi	a1, 4
	mov	a2, r8
	lrw	r26, prepare_ftrace_return
	jsr	r26
	mcount_exit
END(ftrace_graph_caller)

ENTRY(return_to_handler)
	save_return_regs
	mov	a0, r8
	jsri	ftrace_return_to_handler
	restore_return_regs
	jmp	lr
END(return_to_handler)
#endif

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
ENTRY(ftrace_regs_caller)
	mcount_enter_regs

	lrw	t1, PT_FRAME_SIZE
	add	t1, sp

	ldw	a0, (t1, 0)
	subi	a0, 4
	ldw	a1, (t1, 8)
	lrw	a2, function_trace_op
	ldw	a2, (a2, 0)
	mov	a3, sp

	nop
GLOBAL(ftrace_regs_call)
	nop32_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	nop
GLOBAL(ftrace_graph_regs_call)
	nop32_stub
#endif

	mcount_exit_regs
ENDPROC(ftrace_regs_caller)
#endif /* CONFIG_DYNAMIC_FTRACE */