mtd/uclinux: Use generic __bss_stop instead of _ebss
[linux-3.10.git] / arch / sh / lib / mcount.S
1 /*
2  * arch/sh/lib/mcount.S
3  *
4  *  Copyright (C) 2008, 2009  Paul Mundt
5  *  Copyright (C) 2008, 2009  Matt Fleming
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  */
11 #include <asm/ftrace.h>
12 #include <asm/thread_info.h>
13 #include <asm/asm-offsets.h>
14
15 #define MCOUNT_ENTER()          \
16         mov.l   r4, @-r15;      \
17         mov.l   r5, @-r15;      \
18         mov.l   r6, @-r15;      \
19         mov.l   r7, @-r15;      \
20         sts.l   pr, @-r15;      \
21                                 \
22         mov.l   @(20,r15),r4;   \
23         sts     pr, r5
24
25 #define MCOUNT_LEAVE()          \
26         lds.l   @r15+, pr;      \
27         mov.l   @r15+, r7;      \
28         mov.l   @r15+, r6;      \
29         mov.l   @r15+, r5;      \
30         rts;                    \
31          mov.l  @r15+, r4
32
33 #ifdef CONFIG_STACK_DEBUG
34 /*
35  * Perform diagnostic checks on the state of the kernel stack.
36  *
37  * Check for stack overflow. If there is less than 1KB free
38  * then it has overflowed.
39  *
40  * Make sure the stack pointer contains a valid address. Valid
41  * addresses for kernel stacks are anywhere after the bss
42  * (after __bss_stop) and anywhere in init_thread_union (init_stack).
43  */
44 #define STACK_CHECK()                                   \
45         mov     #(THREAD_SIZE >> 10), r0;               \
46         shll8   r0;                                     \
47         shll2   r0;                                     \
48                                                         \
49         /* r1 = sp & (THREAD_SIZE - 1) */               \
50         mov     #-1, r1;                                \
51         add     r0, r1;                                 \
52         and     r15, r1;                                \
53                                                         \
54         mov     #TI_SIZE, r3;                           \
55         mov     #(STACK_WARN >> 8), r2;                 \
56         shll8   r2;                                     \
57         add     r3, r2;                                 \
58                                                         \
59         /* Is the stack overflowing? */                 \
60         cmp/hi  r2, r1;                                 \
61         bf      stack_panic;                            \
62                                                         \
63         /* If sp > __bss_stop then we're OK. */         \
64         mov.l   .L_ebss, r1;                            \
65         cmp/hi  r1, r15;                                \
66         bt      1f;                                     \
67                                                         \
68         /* If sp < init_stack, we're not OK. */         \
69         mov.l   .L_init_thread_union, r1;               \
70         cmp/hs  r1, r15;                                \
71         bf      stack_panic;                            \
72                                                         \
73         /* If sp > init_stack && sp < __bss_stop, not OK. */    \
74         add     r0, r1;                                 \
75         cmp/hs  r1, r15;                                \
76         bt      stack_panic;                            \
77 1:
78 #else
79 #define STACK_CHECK()
80 #endif /* CONFIG_STACK_DEBUG */
81
82         .align 2
83         .globl  _mcount
84         .type   _mcount,@function
85         .globl  mcount
86         .type   mcount,@function
87 _mcount:
88 mcount:
89         STACK_CHECK()
90
91 #ifndef CONFIG_FUNCTION_TRACER
92         rts
93          nop
94 #else
95 #ifndef CONFIG_DYNAMIC_FTRACE
96         mov.l   .Lfunction_trace_stop, r0
97         mov.l   @r0, r0
98         tst     r0, r0
99         bf      ftrace_stub
100 #endif
101
102         MCOUNT_ENTER()
103
104 #ifdef CONFIG_DYNAMIC_FTRACE
105         .globl  mcount_call
106 mcount_call:
107         mov.l   .Lftrace_stub, r6
108 #else
109         mov.l   .Lftrace_trace_function, r6
110         mov.l   ftrace_stub, r7
111         cmp/eq  r6, r7
112         bt      skip_trace
113         mov.l   @r6, r6
114 #endif
115
116         jsr     @r6
117          nop
118
119 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
120         mov.l   .Lftrace_graph_return, r6
121         mov.l   .Lftrace_stub, r7
122         cmp/eq  r6, r7
123         bt      1f
124
125         mov.l   .Lftrace_graph_caller, r0
126         jmp     @r0
127          nop
128
129 1:
130         mov.l   .Lftrace_graph_entry, r6
131         mov.l   .Lftrace_graph_entry_stub, r7
132         cmp/eq  r6, r7
133         bt      skip_trace
134
135         mov.l   .Lftrace_graph_caller, r0
136         jmp     @r0
137          nop
138
139         .align 2
140 .Lftrace_graph_return:
141         .long   ftrace_graph_return
142 .Lftrace_graph_entry:
143         .long   ftrace_graph_entry
144 .Lftrace_graph_entry_stub:
145         .long   ftrace_graph_entry_stub
146 .Lftrace_graph_caller:
147         .long   ftrace_graph_caller
148 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
149
150         .globl skip_trace
151 skip_trace:
152         MCOUNT_LEAVE()
153
154         .align 2
155 .Lftrace_trace_function:
156         .long   ftrace_trace_function
157
158 #ifdef CONFIG_DYNAMIC_FTRACE
159 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
160 /*
161  * NOTE: Do not move either ftrace_graph_call or ftrace_caller
162  * as this will affect the calculation of GRAPH_INSN_OFFSET.
163  */
164         .globl ftrace_graph_call
165 ftrace_graph_call:
166         mov.l   .Lskip_trace, r0
167         jmp     @r0
168          nop
169
170         .align 2
171 .Lskip_trace:
172         .long   skip_trace
173 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
174
175         .globl ftrace_caller
176 ftrace_caller:
177         mov.l   .Lfunction_trace_stop, r0
178         mov.l   @r0, r0
179         tst     r0, r0
180         bf      ftrace_stub
181
182         MCOUNT_ENTER()
183
184         .globl ftrace_call
185 ftrace_call:
186         mov.l   .Lftrace_stub, r6
187         jsr     @r6
188          nop
189
190 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
191         bra     ftrace_graph_call
192          nop
193 #else
194         MCOUNT_LEAVE()
195 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
196 #endif /* CONFIG_DYNAMIC_FTRACE */
197
198         .align 2
199 .Lfunction_trace_stop:
200         .long   function_trace_stop
201
202 /*
203  * NOTE: From here on the locations of the .Lftrace_stub label and
204  * ftrace_stub itself are fixed. Adding additional data here will skew
205  * the displacement for the memory table and break the block replacement.
206  * Place new labels either after the ftrace_stub body, or before
207  * ftrace_caller. You have been warned.
208  */
209 .Lftrace_stub:
210         .long   ftrace_stub
211
212         .globl  ftrace_stub
213 ftrace_stub:
214         rts
215          nop
216
217 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
218         .globl  ftrace_graph_caller
219 ftrace_graph_caller:
220         mov.l   2f, r0
221         mov.l   @r0, r0
222         tst     r0, r0
223         bt      1f
224
225         mov.l   3f, r1
226         jmp     @r1
227          nop
228 1:
229         /*
230          * MCOUNT_ENTER() pushed 5 registers onto the stack, so
231          * the stack address containing our return address is
232          * r15 + 20.
233          */
234         mov     #20, r0
235         add     r15, r0
236         mov     r0, r4
237
238         mov.l   .Lprepare_ftrace_return, r0
239         jsr     @r0
240          nop
241
242         MCOUNT_LEAVE()
243
244         .align 2
245 2:      .long   function_trace_stop
246 3:      .long   skip_trace
247 .Lprepare_ftrace_return:
248         .long   prepare_ftrace_return
249
250         .globl  return_to_handler
251 return_to_handler:
252         /*
253          * Save the return values.
254          */
255         mov.l   r0, @-r15
256         mov.l   r1, @-r15
257
258         mov     #0, r4
259
260         mov.l   .Lftrace_return_to_handler, r0
261         jsr     @r0
262          nop
263
264         /*
265          * The return value from ftrace_return_handler has the real
266          * address that we should return to.
267          */
268         lds     r0, pr
269         mov.l   @r15+, r1
270         rts
271          mov.l  @r15+, r0
272
273
274         .align 2
275 .Lftrace_return_to_handler:
276         .long   ftrace_return_to_handler
277 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
278 #endif /* CONFIG_FUNCTION_TRACER */
279
280 #ifdef CONFIG_STACK_DEBUG
281         .globl  stack_panic
282 stack_panic:
283         mov.l   .Ldump_stack, r0
284         jsr     @r0
285          nop
286
287         mov.l   .Lpanic, r0
288         jsr     @r0
289          mov.l  .Lpanic_s, r4
290
291         rts
292          nop
293
294         .align 2
295 .L_init_thread_union:
296         .long   init_thread_union
297 .Lpanic:
298         .long   panic
299 .Lpanic_s:
300         .long   .Lpanic_str
301 .Ldump_stack:
302         .long   dump_stack
303
304         .section        .rodata
305         .align 2
306 .Lpanic_str:
307         .string "Stack error"
308 #endif /* CONFIG_STACK_DEBUG */