summaryrefslogtreecommitdiff
path: root/arch/microblaze/kernel/mcount.S
blob: fed9da5de8c43caa577827d6b2c82d895d181d3a (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
/*
 * Low-level ftrace handling
 *
 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
 * Copyright (C) 2009 PetaLogix
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License. See the file COPYING in the main directory of this
 * archive for more details.
 */

#include <linux/linkage.h>

#define NOALIGN_ENTRY(name)	.globl name; name:

/* FIXME MS: I think that I don't need to save all regs */
#define SAVE_REGS		\
	addik	r1, r1, -120;	\
	swi	r2, r1, 4;	\
	swi	r3, r1, 8;	\
	swi	r4, r1, 12;	\
	swi	r5, r1, 116;	\
	swi	r6, r1, 16;	\
	swi	r7, r1, 20;	\
	swi	r8, r1, 24;	\
	swi	r9, r1, 28;	\
	swi	r10, r1, 32;	\
	swi	r11, r1, 36;	\
	swi	r12, r1, 40;	\
	swi	r13, r1, 44;	\
	swi	r14, r1, 48;	\
	swi	r16, r1, 52;	\
	swi	r17, r1, 56;	\
	swi	r18, r1, 60;	\
	swi	r19, r1, 64;	\
	swi	r20, r1, 68;	\
	swi	r21, r1, 72;	\
	swi	r22, r1, 76;	\
	swi	r23, r1, 80;	\
	swi	r24, r1, 84;	\
	swi	r25, r1, 88;	\
	swi	r26, r1, 92;	\
	swi	r27, r1, 96;	\
	swi	r28, r1, 100;	\
	swi	r29, r1, 104;	\
	swi	r30, r1, 108;	\
	swi	r31, r1, 112;

#define RESTORE_REGS		\
	lwi	r2, r1, 4;	\
	lwi	r3, r1, 8;	\
	lwi	r4, r1, 12;	\
	lwi	r5, r1, 116;	\
	lwi	r6, r1, 16;	\
	lwi	r7, r1, 20;	\
	lwi	r8, r1, 24;	\
	lwi	r9, r1, 28;	\
	lwi	r10, r1, 32;	\
	lwi	r11, r1, 36;	\
	lwi	r12, r1, 40;	\
	lwi	r13, r1, 44;	\
	lwi	r14, r1, 48;	\
	lwi	r16, r1, 52;	\
	lwi	r17, r1, 56;	\
	lwi	r18, r1, 60;	\
	lwi	r19, r1, 64;	\
	lwi	r20, r1, 68;	\
	lwi	r21, r1, 72;	\
	lwi	r22, r1, 76;	\
	lwi	r23, r1, 80;	\
	lwi	r24, r1, 84;	\
	lwi	r25, r1, 88;	\
	lwi	r26, r1, 92;	\
	lwi	r27, r1, 96;	\
	lwi	r28, r1, 100;	\
	lwi	r29, r1, 104;	\
	lwi	r30, r1, 108;	\
	lwi	r31, r1, 112;	\
	addik	r1, r1, 120;

ENTRY(ftrace_stub)
	rtsd	r15, 8;
	nop;

ENTRY(_mcount)
#ifdef CONFIG_DYNAMIC_FTRACE
ENTRY(ftrace_caller)
	/* MS: It is just barrier which is removed from C code */
	rtsd	r15, 8
	nop
#endif /* CONFIG_DYNAMIC_FTRACE */
	SAVE_REGS
	swi	r15, r1, 0;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#ifndef CONFIG_DYNAMIC_FTRACE
	lwi	r5, r0, ftrace_graph_return;
	addik	r6, r0, ftrace_stub; /* asm implementation */
	cmpu	r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
	beqid	r5, end_graph_tracer;
	nop;

	lwi	r6, r0, ftrace_graph_entry;
	addik	r5, r0, ftrace_graph_entry_stub; /* implemented in C */
	cmpu	r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
	beqid	r5, end_graph_tracer;
	nop;
#else /* CONFIG_DYNAMIC_FTRACE */
NOALIGN_ENTRY(ftrace_call_graph)
	/* MS: jump over graph function - replaced from C code */
	bri	end_graph_tracer
#endif /* CONFIG_DYNAMIC_FTRACE */
	addik	r5, r1, 120; /* MS: load parent addr */
	addik	r6, r15, 0; /* MS: load current function addr */
	bralid	r15, prepare_ftrace_return;
	nop;
	/* MS: graph was taken that's why - can jump over function trace */
	brid	end;
	nop;
end_graph_tracer:
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
#ifndef CONFIG_DYNAMIC_FTRACE
	/* MS: test function trace if is taken or not */
	lwi	r20, r0, ftrace_trace_function;
	addik	r6, r0, ftrace_stub;
	cmpu	r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
	beqid	r5, end; /* MS: not taken -> jump over */
	nop;
#else /* CONFIG_DYNAMIC_FTRACE */
NOALIGN_ENTRY(ftrace_call)
/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
	nop
	nop
#endif /* CONFIG_DYNAMIC_FTRACE */
/* static normal trace */
	lwi	r6, r1, 120; /* MS: load parent addr */
	addik	r5, r15, -4; /* MS: load current function addr */
	/* MS: here is dependency on previous code */
	brald	r15, r20; /* MS: jump to ftrace handler */
	nop;
end:
	lwi	r15, r1, 0;
	RESTORE_REGS

	rtsd	r15, 8; /* MS: jump back */
	nop;

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ENTRY(return_to_handler)
	nop; /* MS: just barrier for rtsd r15, 8 */
	nop;
	SAVE_REGS
	swi	r15, r1, 0;

	/* MS: find out returning address */
	bralid	r15, ftrace_return_to_handler;
	nop;

	/* MS: return value from ftrace_return_to_handler is my returning addr
	 * must be before restore regs because I have to restore r3 content */
	addik	r15, r3, 0;
	RESTORE_REGS

	rtsd	r15, 8; /* MS: jump back */
	nop;
#endif	/* CONFIG_FUNCTION_TRACER */