diff options
Diffstat (limited to 'arch/tile/kernel/mcount_64.S')
-rw-r--r-- | arch/tile/kernel/mcount_64.S | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/arch/tile/kernel/mcount_64.S b/arch/tile/kernel/mcount_64.S new file mode 100644 index 000000000000..70d7bb0c4d8f --- /dev/null +++ b/arch/tile/kernel/mcount_64.S | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * TILE-Gx specific __mcount support | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <asm/ftrace.h> | ||
19 | |||
20 | #define REGSIZE 8 | ||
21 | |||
22 | .text | ||
23 | .global __mcount | ||
24 | |||
25 | .macro MCOUNT_SAVE_REGS | ||
26 | addli sp, sp, -REGSIZE | ||
27 | { | ||
28 | st sp, lr | ||
29 | addli r29, sp, - (12 * REGSIZE) | ||
30 | } | ||
31 | { | ||
32 | addli sp, sp, - (13 * REGSIZE) | ||
33 | st r29, sp | ||
34 | } | ||
35 | addli r29, r29, REGSIZE | ||
36 | { st r29, r0; addli r29, r29, REGSIZE } | ||
37 | { st r29, r1; addli r29, r29, REGSIZE } | ||
38 | { st r29, r2; addli r29, r29, REGSIZE } | ||
39 | { st r29, r3; addli r29, r29, REGSIZE } | ||
40 | { st r29, r4; addli r29, r29, REGSIZE } | ||
41 | { st r29, r5; addli r29, r29, REGSIZE } | ||
42 | { st r29, r6; addli r29, r29, REGSIZE } | ||
43 | { st r29, r7; addli r29, r29, REGSIZE } | ||
44 | { st r29, r8; addli r29, r29, REGSIZE } | ||
45 | { st r29, r9; addli r29, r29, REGSIZE } | ||
46 | { st r29, r10; addli r29, r29, REGSIZE } | ||
47 | .endm | ||
48 | |||
49 | .macro MCOUNT_RESTORE_REGS | ||
50 | addli r29, sp, (2 * REGSIZE) | ||
51 | { ld r0, r29; addli r29, r29, REGSIZE } | ||
52 | { ld r1, r29; addli r29, r29, REGSIZE } | ||
53 | { ld r2, r29; addli r29, r29, REGSIZE } | ||
54 | { ld r3, r29; addli r29, r29, REGSIZE } | ||
55 | { ld r4, r29; addli r29, r29, REGSIZE } | ||
56 | { ld r5, r29; addli r29, r29, REGSIZE } | ||
57 | { ld r6, r29; addli r29, r29, REGSIZE } | ||
58 | { ld r7, r29; addli r29, r29, REGSIZE } | ||
59 | { ld r8, r29; addli r29, r29, REGSIZE } | ||
60 | { ld r9, r29; addli r29, r29, REGSIZE } | ||
61 | { ld r10, r29; addli lr, sp, (13 * REGSIZE) } | ||
62 | { ld lr, lr; addli sp, sp, (14 * REGSIZE) } | ||
63 | .endm | ||
64 | |||
65 | .macro RETURN_BACK | ||
66 | { move r12, lr; move lr, r10 } | ||
67 | jrp r12 | ||
68 | .endm | ||
69 | |||
70 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
71 | |||
72 | .align 64 | ||
73 | STD_ENTRY(__mcount) | ||
74 | __mcount: | ||
75 | j ftrace_stub | ||
76 | STD_ENDPROC(__mcount) | ||
77 | |||
78 | .align 64 | ||
79 | STD_ENTRY(ftrace_caller) | ||
80 | moveli r11, hw2_last(function_trace_stop) | ||
81 | { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr } | ||
82 | { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 } | ||
83 | ld r11, r11 | ||
84 | beqz r11, 1f | ||
85 | jrp r12 | ||
86 | |||
87 | 1: | ||
88 | { move r10, lr; move lr, r12 } | ||
89 | MCOUNT_SAVE_REGS | ||
90 | |||
91 | /* arg1: self return address */ | ||
92 | /* arg2: parent's return address */ | ||
93 | { move r0, lr; move r1, r10 } | ||
94 | |||
95 | .global ftrace_call | ||
96 | ftrace_call: | ||
97 | /* | ||
98 | * a placeholder for the call to a real tracing function, i.e. | ||
99 | * ftrace_trace_function() | ||
100 | */ | ||
101 | nop | ||
102 | |||
103 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
104 | .global ftrace_graph_call | ||
105 | ftrace_graph_call: | ||
106 | /* | ||
107 | * a placeholder for the call to a real tracing function, i.e. | ||
108 | * ftrace_graph_caller() | ||
109 | */ | ||
110 | nop | ||
111 | #endif | ||
112 | MCOUNT_RESTORE_REGS | ||
113 | .global ftrace_stub | ||
114 | ftrace_stub: | ||
115 | RETURN_BACK | ||
116 | STD_ENDPROC(ftrace_caller) | ||
117 | |||
118 | #else /* ! CONFIG_DYNAMIC_FTRACE */ | ||
119 | |||
120 | .align 64 | ||
121 | STD_ENTRY(__mcount) | ||
122 | moveli r11, hw2_last(function_trace_stop) | ||
123 | { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr } | ||
124 | { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 } | ||
125 | ld r11, r11 | ||
126 | beqz r11, 1f | ||
127 | jrp r12 | ||
128 | |||
129 | 1: | ||
130 | { move r10, lr; move lr, r12 } | ||
131 | { | ||
132 | moveli r11, hw2_last(ftrace_trace_function) | ||
133 | moveli r13, hw2_last(ftrace_stub) | ||
134 | } | ||
135 | { | ||
136 | shl16insli r11, r11, hw1(ftrace_trace_function) | ||
137 | shl16insli r13, r13, hw1(ftrace_stub) | ||
138 | } | ||
139 | { | ||
140 | shl16insli r11, r11, hw0(ftrace_trace_function) | ||
141 | shl16insli r13, r13, hw0(ftrace_stub) | ||
142 | } | ||
143 | |||
144 | ld r11, r11 | ||
145 | sub r14, r13, r11 | ||
146 | bnez r14, static_trace | ||
147 | |||
148 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
149 | moveli r15, hw2_last(ftrace_graph_return) | ||
150 | shl16insli r15, r15, hw1(ftrace_graph_return) | ||
151 | shl16insli r15, r15, hw0(ftrace_graph_return) | ||
152 | ld r15, r15 | ||
153 | sub r15, r15, r13 | ||
154 | bnez r15, ftrace_graph_caller | ||
155 | |||
156 | { | ||
157 | moveli r16, hw2_last(ftrace_graph_entry) | ||
158 | moveli r17, hw2_last(ftrace_graph_entry_stub) | ||
159 | } | ||
160 | { | ||
161 | shl16insli r16, r16, hw1(ftrace_graph_entry) | ||
162 | shl16insli r17, r17, hw1(ftrace_graph_entry_stub) | ||
163 | } | ||
164 | { | ||
165 | shl16insli r16, r16, hw0(ftrace_graph_entry) | ||
166 | shl16insli r17, r17, hw0(ftrace_graph_entry_stub) | ||
167 | } | ||
168 | ld r16, r16 | ||
169 | sub r17, r16, r17 | ||
170 | bnez r17, ftrace_graph_caller | ||
171 | |||
172 | #endif | ||
173 | RETURN_BACK | ||
174 | |||
175 | static_trace: | ||
176 | MCOUNT_SAVE_REGS | ||
177 | |||
178 | /* arg1: self return address */ | ||
179 | /* arg2: parent's return address */ | ||
180 | { move r0, lr; move r1, r10 } | ||
181 | |||
182 | /* call ftrace_trace_function() */ | ||
183 | jalr r11 | ||
184 | |||
185 | MCOUNT_RESTORE_REGS | ||
186 | |||
187 | .global ftrace_stub | ||
188 | ftrace_stub: | ||
189 | RETURN_BACK | ||
190 | STD_ENDPROC(__mcount) | ||
191 | |||
192 | #endif /* ! CONFIG_DYNAMIC_FTRACE */ | ||
193 | |||
194 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
195 | |||
196 | STD_ENTRY(ftrace_graph_caller) | ||
197 | ftrace_graph_caller: | ||
198 | #ifndef CONFIG_DYNAMIC_FTRACE | ||
199 | MCOUNT_SAVE_REGS | ||
200 | #endif | ||
201 | |||
202 | /* arg1: Get the location of the parent's return address */ | ||
203 | addi r0, sp, 12 * REGSIZE | ||
204 | /* arg2: Get self return address */ | ||
205 | move r1, lr | ||
206 | |||
207 | jal prepare_ftrace_return | ||
208 | |||
209 | MCOUNT_RESTORE_REGS | ||
210 | RETURN_BACK | ||
211 | STD_ENDPROC(ftrace_graph_caller) | ||
212 | |||
213 | .global return_to_handler | ||
214 | return_to_handler: | ||
215 | MCOUNT_SAVE_REGS | ||
216 | |||
217 | jal ftrace_return_to_handler | ||
218 | /* restore the real parent address */ | ||
219 | move r11, r0 | ||
220 | |||
221 | MCOUNT_RESTORE_REGS | ||
222 | jr r11 | ||
223 | |||
224 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||