xref: /openbmc/linux/arch/csky/abiv2/mcount.S (revision 28bb030f93334495ddc64ade0bff18721bf7023d)
1230c77a5SGuo Ren/* SPDX-License-Identifier: GPL-2.0 */
2230c77a5SGuo Ren// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3230c77a5SGuo Ren
4230c77a5SGuo Ren#include <linux/linkage.h>
5d7950be1SGuo Ren#include <asm/ftrace.h>
6230c77a5SGuo Ren
7d7950be1SGuo Ren/*
8d7950be1SGuo Ren * csky-gcc with -pg will put the following asm after prologue:
9d7950be1SGuo Ren *      push	r15
10d7950be1SGuo Ren *      jsri	_mcount
11d7950be1SGuo Ren *
12d7950be1SGuo Ren * stack layout after mcount_enter in _mcount():
13d7950be1SGuo Ren *
14d7950be1SGuo Ren * current sp => 0:+-------+
15d7950be1SGuo Ren *                 | a0-a3 | -> must save all argument regs
16d7950be1SGuo Ren *             +16:+-------+
17d7950be1SGuo Ren *                 | lr    | -> _mcount lr (instrumente function's pc)
18d7950be1SGuo Ren *             +20:+-------+
19d7950be1SGuo Ren *                 | fp=r8 | -> instrumented function fp
20d7950be1SGuo Ren *             +24:+-------+
21d7950be1SGuo Ren *                 | plr   | -> instrumented function lr (parent's pc)
22d7950be1SGuo Ren *                 +-------+
23d7950be1SGuo Ren */
24d7950be1SGuo Ren
25d7950be1SGuo Ren.macro mcount_enter
26d7950be1SGuo Ren	subi	sp, 24
27230c77a5SGuo Ren	stw	a0, (sp, 0)
28230c77a5SGuo Ren	stw	a1, (sp, 4)
29230c77a5SGuo Ren	stw	a2, (sp, 8)
30230c77a5SGuo Ren	stw	a3, (sp, 12)
31230c77a5SGuo Ren	stw	lr, (sp, 16)
32d7950be1SGuo Ren	stw	r8, (sp, 20)
33d7950be1SGuo Ren.endm
34d7950be1SGuo Ren
35d7950be1SGuo Ren.macro mcount_exit
36230c77a5SGuo Ren	ldw	a0, (sp, 0)
37230c77a5SGuo Ren	ldw	a1, (sp, 4)
38230c77a5SGuo Ren	ldw	a2, (sp, 8)
39230c77a5SGuo Ren	ldw	a3, (sp, 12)
40230c77a5SGuo Ren	ldw	t1, (sp, 16)
41d7950be1SGuo Ren	ldw	r8, (sp, 20)
42d7950be1SGuo Ren	ldw	lr, (sp, 24)
43d7950be1SGuo Ren	addi	sp, 28
44230c77a5SGuo Ren	jmp	t1
45d7950be1SGuo Ren.endm
46d7950be1SGuo Ren
47d7950be1SGuo Ren.macro save_return_regs
48d7950be1SGuo Ren	subi	sp, 16
49d7950be1SGuo Ren	stw	a0, (sp, 0)
50d7950be1SGuo Ren	stw	a1, (sp, 4)
51d7950be1SGuo Ren	stw	a2, (sp, 8)
52d7950be1SGuo Ren	stw	a3, (sp, 12)
53d7950be1SGuo Ren.endm
54d7950be1SGuo Ren
55d7950be1SGuo Ren.macro restore_return_regs
56d7950be1SGuo Ren	mov	lr, a0
57d7950be1SGuo Ren	ldw	a0, (sp, 0)
58d7950be1SGuo Ren	ldw	a1, (sp, 4)
59d7950be1SGuo Ren	ldw	a2, (sp, 8)
60d7950be1SGuo Ren	ldw	a3, (sp, 12)
61d7950be1SGuo Ren	addi	sp, 16
62d7950be1SGuo Ren.endm
63d7950be1SGuo Ren
64*28bb030fSGuo Ren.macro nop32_stub
65*28bb030fSGuo Ren	nop32
66*28bb030fSGuo Ren	nop32
67*28bb030fSGuo Ren	nop32
68*28bb030fSGuo Ren.endm
69*28bb030fSGuo Ren
70d7950be1SGuo RenENTRY(ftrace_stub)
71d7950be1SGuo Ren	jmp	lr
72d7950be1SGuo RenEND(ftrace_stub)
73d7950be1SGuo Ren
74*28bb030fSGuo Ren#ifndef CONFIG_DYNAMIC_FTRACE
75d7950be1SGuo RenENTRY(_mcount)
76d7950be1SGuo Ren	mcount_enter
77d7950be1SGuo Ren
78d7950be1SGuo Ren	/* r26 is link register, only used with jsri translation */
79d7950be1SGuo Ren	lrw	r26, ftrace_trace_function
80d7950be1SGuo Ren	ldw	r26, (r26, 0)
81d7950be1SGuo Ren	lrw	a1, ftrace_stub
82d7950be1SGuo Ren	cmpne	r26, a1
83d7950be1SGuo Ren	bf	skip_ftrace
84d7950be1SGuo Ren
85d7950be1SGuo Ren	mov	a0, lr
86*28bb030fSGuo Ren	subi	a0, 4
87d7950be1SGuo Ren	ldw	a1, (sp, 24)
88d7950be1SGuo Ren
89d7950be1SGuo Ren	jsr	r26
90d7950be1SGuo Ren
91d7950be1SGuo Ren#ifndef CONFIG_FUNCTION_GRAPH_TRACER
92d7950be1SGuo Renskip_ftrace:
93d7950be1SGuo Ren	mcount_exit
94d7950be1SGuo Ren#else
95d7950be1SGuo Renskip_ftrace:
96d7950be1SGuo Ren	lrw	a0, ftrace_graph_return
97d7950be1SGuo Ren	ldw	a0, (a0, 0)
98d7950be1SGuo Ren	lrw	a1, ftrace_stub
99d7950be1SGuo Ren	cmpne	a0, a1
100d7950be1SGuo Ren	bt	ftrace_graph_caller
101d7950be1SGuo Ren
102d7950be1SGuo Ren	lrw	a0, ftrace_graph_entry
103d7950be1SGuo Ren	ldw	a0, (a0, 0)
104d7950be1SGuo Ren	lrw	a1, ftrace_graph_entry_stub
105d7950be1SGuo Ren	cmpne	a0, a1
106d7950be1SGuo Ren	bt	ftrace_graph_caller
107d7950be1SGuo Ren
108d7950be1SGuo Ren	mcount_exit
109d7950be1SGuo Ren#endif
110230c77a5SGuo RenEND(_mcount)
111*28bb030fSGuo Ren#else /* CONFIG_DYNAMIC_FTRACE */
112*28bb030fSGuo RenENTRY(_mcount)
113*28bb030fSGuo Ren	mov	t1, lr
114*28bb030fSGuo Ren	ldw	lr, (sp, 0)
115*28bb030fSGuo Ren	addi	sp, 4
116*28bb030fSGuo Ren	jmp	t1
117*28bb030fSGuo RenENDPROC(_mcount)
118*28bb030fSGuo Ren
119*28bb030fSGuo RenENTRY(ftrace_caller)
120*28bb030fSGuo Ren	mcount_enter
121*28bb030fSGuo Ren
122*28bb030fSGuo Ren	ldw	a0, (sp, 16)
123*28bb030fSGuo Ren	subi	a0, 4
124*28bb030fSGuo Ren	ldw	a1, (sp, 24)
125*28bb030fSGuo Ren
126*28bb030fSGuo Ren	nop
127*28bb030fSGuo RenGLOBAL(ftrace_call)
128*28bb030fSGuo Ren	nop32_stub
129*28bb030fSGuo Ren
130*28bb030fSGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER
131*28bb030fSGuo Ren	nop
132*28bb030fSGuo RenGLOBAL(ftrace_graph_call)
133*28bb030fSGuo Ren	nop32_stub
134*28bb030fSGuo Ren#endif
135*28bb030fSGuo Ren
136*28bb030fSGuo Ren	mcount_exit
137*28bb030fSGuo RenENDPROC(ftrace_caller)
138*28bb030fSGuo Ren#endif /* CONFIG_DYNAMIC_FTRACE */
139d7950be1SGuo Ren
140d7950be1SGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER
141d7950be1SGuo RenENTRY(ftrace_graph_caller)
142d7950be1SGuo Ren	mov	a0, sp
143d7950be1SGuo Ren	addi	a0, 24
144d7950be1SGuo Ren	ldw	a1, (sp, 16)
145*28bb030fSGuo Ren	subi	a1, 4
146d7950be1SGuo Ren	mov	a2, r8
147d7950be1SGuo Ren	lrw	r26, prepare_ftrace_return
148d7950be1SGuo Ren	jsr	r26
149d7950be1SGuo Ren	mcount_exit
150d7950be1SGuo RenEND(ftrace_graph_caller)
151d7950be1SGuo Ren
152d7950be1SGuo RenENTRY(return_to_handler)
153d7950be1SGuo Ren	save_return_regs
154d7950be1SGuo Ren	mov	a0, r8
155d7950be1SGuo Ren	jsri	ftrace_return_to_handler
156d7950be1SGuo Ren	restore_return_regs
157d7950be1SGuo Ren	jmp	lr
158d7950be1SGuo RenEND(return_to_handler)
159d7950be1SGuo Ren#endif
160