Linux 4.6-rc6
[linux/fpc-iii.git] / arch / sh / lib / mcount.S
blob7a8572f9d58bcdadc1fa5fb31fad65166907f515
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>
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
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
33 #ifdef CONFIG_STACK_DEBUG
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;                            \
78 #else
79 #define STACK_CHECK()
80 #endif /* CONFIG_STACK_DEBUG */
82         .align 2
83         .globl  _mcount
84         .type   _mcount,@function
85         .globl  mcount
86         .type   mcount,@function
87 _mcount:
88 mcount:
89         STACK_CHECK()
91 #ifndef CONFIG_FUNCTION_TRACER
92         rts
93          nop
94 #else
95         MCOUNT_ENTER()
97 #ifdef CONFIG_DYNAMIC_FTRACE
98         .globl  mcount_call
99 mcount_call:
100         mov.l   .Lftrace_stub, r6
101 #else
102         mov.l   .Lftrace_trace_function, r6
103         mov.l   ftrace_stub, r7
104         cmp/eq  r6, r7
105         bt      skip_trace
106         mov.l   @r6, r6
107 #endif
109         jsr     @r6
110          nop
112 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
113         mov.l   .Lftrace_graph_return, r6
114         mov.l   .Lftrace_stub, r7
115         cmp/eq  r6, r7
116         bt      1f
118         mov.l   .Lftrace_graph_caller, r0
119         jmp     @r0
120          nop
123         mov.l   .Lftrace_graph_entry, r6
124         mov.l   .Lftrace_graph_entry_stub, r7
125         cmp/eq  r6, r7
126         bt      skip_trace
128         mov.l   .Lftrace_graph_caller, r0
129         jmp     @r0
130          nop
132         .align 2
133 .Lftrace_graph_return:
134         .long   ftrace_graph_return
135 .Lftrace_graph_entry:
136         .long   ftrace_graph_entry
137 .Lftrace_graph_entry_stub:
138         .long   ftrace_graph_entry_stub
139 .Lftrace_graph_caller:
140         .long   ftrace_graph_caller
141 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
143         .globl skip_trace
144 skip_trace:
145         MCOUNT_LEAVE()
147         .align 2
148 .Lftrace_trace_function:
149         .long   ftrace_trace_function
151 #ifdef CONFIG_DYNAMIC_FTRACE
152 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
154  * NOTE: Do not move either ftrace_graph_call or ftrace_caller
155  * as this will affect the calculation of GRAPH_INSN_OFFSET.
156  */
157         .globl ftrace_graph_call
158 ftrace_graph_call:
159         mov.l   .Lskip_trace, r0
160         jmp     @r0
161          nop
163         .align 2
164 .Lskip_trace:
165         .long   skip_trace
166 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
168         .globl ftrace_caller
169 ftrace_caller:
170         MCOUNT_ENTER()
172         .globl ftrace_call
173 ftrace_call:
174         mov.l   .Lftrace_stub, r6
175         jsr     @r6
176          nop
178 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
179         bra     ftrace_graph_call
180          nop
181 #else
182         MCOUNT_LEAVE()
183 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
184 #endif /* CONFIG_DYNAMIC_FTRACE */
186         .align 2
189  * NOTE: From here on the locations of the .Lftrace_stub label and
190  * ftrace_stub itself are fixed. Adding additional data here will skew
191  * the displacement for the memory table and break the block replacement.
192  * Place new labels either after the ftrace_stub body, or before
193  * ftrace_caller. You have been warned.
194  */
195 .Lftrace_stub:
196         .long   ftrace_stub
198         .globl  ftrace_stub
199 ftrace_stub:
200         rts
201          nop
203 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
204         .globl  ftrace_graph_caller
205 ftrace_graph_caller:
206         mov.l   2f, r1
207         jmp     @r1
208          nop
210         /*
211          * MCOUNT_ENTER() pushed 5 registers onto the stack, so
212          * the stack address containing our return address is
213          * r15 + 20.
214          */
215         mov     #20, r0
216         add     r15, r0
217         mov     r0, r4
219         mov.l   .Lprepare_ftrace_return, r0
220         jsr     @r0
221          nop
223         MCOUNT_LEAVE()
225         .align 2
226 2:      .long   skip_trace
227 .Lprepare_ftrace_return:
228         .long   prepare_ftrace_return
230         .globl  return_to_handler
231 return_to_handler:
232         /*
233          * Save the return values.
234          */
235         mov.l   r0, @-r15
236         mov.l   r1, @-r15
238         mov     #0, r4
240         mov.l   .Lftrace_return_to_handler, r0
241         jsr     @r0
242          nop
244         /*
245          * The return value from ftrace_return_handler has the real
246          * address that we should return to.
247          */
248         lds     r0, pr
249         mov.l   @r15+, r1
250         rts
251          mov.l  @r15+, r0
254         .align 2
255 .Lftrace_return_to_handler:
256         .long   ftrace_return_to_handler
257 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
258 #endif /* CONFIG_FUNCTION_TRACER */
260 #ifdef CONFIG_STACK_DEBUG
261         .globl  stack_panic
262 stack_panic:
263         mov.l   .Ldump_stack, r0
264         jsr     @r0
265          nop
267         mov.l   .Lpanic, r0
268         jsr     @r0
269          mov.l  .Lpanic_s, r4
271         rts
272          nop
274         .align 2
275 .L_init_thread_union:
276         .long   init_thread_union
277 .L_ebss:
278         .long   __bss_stop
279 .Lpanic:
280         .long   panic
281 .Lpanic_s:
282         .long   .Lpanic_str
283 .Ldump_stack:
284         .long   dump_stack
286         .section        .rodata
287         .align 2
288 .Lpanic_str:
289         .string "Stack error"
290 #endif /* CONFIG_STACK_DEBUG */