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

#include <linux/linkage.h>
#include <asm/ftrace.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 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

ENTRY(ftrace_stub)
	jmp	lr
END(ftrace_stub)

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, MCOUNT_INSN_SIZE
	ldw	a1, (sp, 24)

	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)

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ENTRY(ftrace_graph_caller)
	mov	a0, sp
	addi	a0, 24
	ldw	a1, (sp, 16)
	subi	a1, MCOUNT_INSN_SIZE
	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