Commit | Line | Data |
---|---|---|
a61fd5e3 TL |
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 */ |