aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-07-10 21:00:23 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-07-10 21:07:58 -0400
commitb99610fb9cdf390965c62c22322596d961591160 (patch)
tree0c836b4390370b4848f151e3b3cbe27e6d8b48e2 /arch
parentc652d780c9cf7f860141de232b37160fe013feca (diff)
sh: Provide diagnostic kernel stack checks
Enable kernel stack checking code in both the dynamic ftrace and mcount code paths. Check the stack to see if it's overflowing and make sure that the stack pointer contains an address that's either in init_stack or after the bss. Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/Kconfig.debug11
-rw-r--r--arch/sh/kernel/asm-offsets.c1
-rw-r--r--arch/sh/lib/mcount.S85
3 files changed, 97 insertions, 0 deletions
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 39224b57c6ef..52a132c24aab 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -123,4 +123,15 @@ config SH64_SR_WATCH
123 bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" 123 bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
124 depends on SUPERH64 124 depends on SUPERH64
125 125
126config STACK_DEBUG
127 bool "Enable diagnostic checks of the kernel stack"
128 depends on FUNCTION_TRACER
129 select DEBUG_STACKOVERFLOW
130 default n
131 help
132 This option allows checks to be performed on the kernel stack
133 at runtime. Saying Y here will add overhead to every function
134 call and will therefore incur a major performance hit. Most
135 users should say N.
136
126endmenu 137endmenu
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 99aceb28ee24..d218e808294e 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -26,6 +26,7 @@ int main(void)
26 DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); 26 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
27 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); 27 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
28 DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); 28 DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
29 DEFINE(TI_SIZE, sizeof(struct thread_info));
29 30
30#ifdef CONFIG_HIBERNATION 31#ifdef CONFIG_HIBERNATION
31 DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); 32 DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S
index 71e87f9b4fda..8596483f7b41 100644
--- a/arch/sh/lib/mcount.S
+++ b/arch/sh/lib/mcount.S
@@ -9,6 +9,8 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11#include <asm/ftrace.h> 11#include <asm/ftrace.h>
12#include <asm/thread_info.h>
13#include <asm/asm-offsets.h>
12 14
13#define MCOUNT_ENTER() \ 15#define MCOUNT_ENTER() \
14 mov.l r4, @-r15; \ 16 mov.l r4, @-r15; \
@@ -28,6 +30,55 @@
28 rts; \ 30 rts; \
29 mov.l @r15+, r4 31 mov.l @r15+, r4
30 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; \
771:
78#else
79#define STACK_CHECK()
80#endif /* CONFIG_STACK_DEBUG */
81
31 .align 2 82 .align 2
32 .globl _mcount 83 .globl _mcount
33 .type _mcount,@function 84 .type _mcount,@function
@@ -41,6 +92,8 @@ mcount:
41 tst r0, r0 92 tst r0, r0
42 bf ftrace_stub 93 bf ftrace_stub
43#endif 94#endif
95 STACK_CHECK()
96
44 MCOUNT_ENTER() 97 MCOUNT_ENTER()
45 98
46#ifdef CONFIG_DYNAMIC_FTRACE 99#ifdef CONFIG_DYNAMIC_FTRACE
@@ -73,6 +126,8 @@ ftrace_caller:
73 tst r0, r0 126 tst r0, r0
74 bf ftrace_stub 127 bf ftrace_stub
75 128
129 STACK_CHECK()
130
76 MCOUNT_ENTER() 131 MCOUNT_ENTER()
77 132
78 .globl ftrace_call 133 .globl ftrace_call
@@ -100,6 +155,36 @@ ftrace_stub:
100 rts 155 rts
101 nop 156 nop
102 157
158#ifdef CONFIG_STACK_DEBUG
159 .globl stack_panic
160stack_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
103 .align 2 172 .align 2
104.Lfunction_trace_stop: 173.Lfunction_trace_stop:
105 .long function_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 */