sh: Provide diagnostic kernel stack checks
[deliverable/linux.git] / arch / sh / lib / mcount.S
1 /*
2 * arch/sh/lib/mcount.S
3 *
4 * Copyright (C) 2008 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 _ebss) 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 > _ebss 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 < _ebss, 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 #ifndef CONFIG_DYNAMIC_FTRACE
90 mov.l .Lfunction_trace_stop, r0
91 mov.l @r0, r0
92 tst r0, r0
93 bf ftrace_stub
94 #endif
95 STACK_CHECK()
96
97 MCOUNT_ENTER()
98
99 #ifdef CONFIG_DYNAMIC_FTRACE
100 .globl mcount_call
101 mcount_call:
102 mov.l .Lftrace_stub, r6
103 #else
104 mov.l .Lftrace_trace_function, r6
105 mov.l ftrace_stub, r7
106 cmp/eq r6, r7
107 bt skip_trace
108 mov.l @r6, r6
109 #endif
110
111 jsr @r6
112 nop
113
114 skip_trace:
115 MCOUNT_LEAVE()
116
117 .align 2
118 .Lftrace_trace_function:
119 .long ftrace_trace_function
120
121 #ifdef CONFIG_DYNAMIC_FTRACE
122 .globl ftrace_caller
123 ftrace_caller:
124 mov.l .Lfunction_trace_stop, r0
125 mov.l @r0, r0
126 tst r0, r0
127 bf ftrace_stub
128
129 STACK_CHECK()
130
131 MCOUNT_ENTER()
132
133 .globl ftrace_call
134 ftrace_call:
135 mov.l .Lftrace_stub, r6
136 jsr @r6
137 nop
138
139 MCOUNT_LEAVE()
140 #endif /* CONFIG_DYNAMIC_FTRACE */
141
142 /*
143 * NOTE: From here on the locations of the .Lftrace_stub label and
144 * ftrace_stub itself are fixed. Adding additional data here will skew
145 * the displacement for the memory table and break the block replacement.
146 * Place new labels either after the ftrace_stub body, or before
147 * ftrace_caller. You have been warned.
148 */
149 .align 2
150 .Lftrace_stub:
151 .long ftrace_stub
152
153 .globl ftrace_stub
154 ftrace_stub:
155 rts
156 nop
157
158 #ifdef CONFIG_STACK_DEBUG
159 .globl stack_panic
160 stack_panic:
161 mov.l .Ldump_stack, r0
162 jsr @r0
163 nop
164
165 mov.l .Lpanic, r0
166 jsr @r0
167 mov.l .Lpanic_s, r4
168
169 rts
170 nop
171
172 .align 2
173 .Lfunction_trace_stop:
174 .long function_trace_stop
175 .L_ebss:
176 .long _ebss
177 .L_init_thread_union:
178 .long init_thread_union
179 .Lpanic:
180 .long panic
181 .Lpanic_s:
182 .long .Lpanic_str
183 .Ldump_stack:
184 .long dump_stack
185
186 .section .rodata
187 .align 2
188 .Lpanic_str:
189 .string "Stack error"
190 #endif /* CONFIG_STACK_DEBUG */
This page took 0.039599 seconds and 5 git commands to generate.