Commit b99610fb authored by Matt Fleming's avatar Matt Fleming Committed by Paul Mundt

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: default avatarMatt Fleming <matt@console-pimps.org>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent c652d780
...@@ -123,4 +123,15 @@ config SH64_SR_WATCH ...@@ -123,4 +123,15 @@ config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
depends on SUPERH64 depends on SUPERH64
config STACK_DEBUG
bool "Enable diagnostic checks of the kernel stack"
depends on FUNCTION_TRACER
select DEBUG_STACKOVERFLOW
default n
help
This option allows checks to be performed on the kernel stack
at runtime. Saying Y here will add overhead to every function
call and will therefore incur a major performance hit. Most
users should say N.
endmenu endmenu
...@@ -26,6 +26,7 @@ int main(void) ...@@ -26,6 +26,7 @@ int main(void)
DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
DEFINE(TI_SIZE, sizeof(struct thread_info));
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* for more details. * for more details.
*/ */
#include <asm/ftrace.h> #include <asm/ftrace.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#define MCOUNT_ENTER() \ #define MCOUNT_ENTER() \
mov.l r4, @-r15; \ mov.l r4, @-r15; \
...@@ -28,6 +30,55 @@ ...@@ -28,6 +30,55 @@
rts; \ rts; \
mov.l @r15+, r4 mov.l @r15+, r4
#ifdef CONFIG_STACK_DEBUG
/*
* Perform diagnostic checks on the state of the kernel stack.
*
* Check for stack overflow. If there is less than 1KB free
* then it has overflowed.
*
* Make sure the stack pointer contains a valid address. Valid
* addresses for kernel stacks are anywhere after the bss
* (after _ebss) and anywhere in init_thread_union (init_stack).
*/
#define STACK_CHECK() \
mov #(THREAD_SIZE >> 10), r0; \
shll8 r0; \
shll2 r0; \
\
/* r1 = sp & (THREAD_SIZE - 1) */ \
mov #-1, r1; \
add r0, r1; \
and r15, r1; \
\
mov #TI_SIZE, r3; \
mov #(STACK_WARN >> 8), r2; \
shll8 r2; \
add r3, r2; \
\
/* Is the stack overflowing? */ \
cmp/hi r2, r1; \
bf stack_panic; \
\
/* If sp > _ebss then we're OK. */ \
mov.l .L_ebss, r1; \
cmp/hi r1, r15; \
bt 1f; \
\
/* If sp < init_stack, we're not OK. */ \
mov.l .L_init_thread_union, r1; \
cmp/hs r1, r15; \
bf stack_panic; \
\
/* If sp > init_stack && sp < _ebss, not OK. */ \
add r0, r1; \
cmp/hs r1, r15; \
bt stack_panic; \
1:
#else
#define STACK_CHECK()
#endif /* CONFIG_STACK_DEBUG */
.align 2 .align 2
.globl _mcount .globl _mcount
.type _mcount,@function .type _mcount,@function
...@@ -41,6 +92,8 @@ mcount: ...@@ -41,6 +92,8 @@ mcount:
tst r0, r0 tst r0, r0
bf ftrace_stub bf ftrace_stub
#endif #endif
STACK_CHECK()
MCOUNT_ENTER() MCOUNT_ENTER()
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
...@@ -73,6 +126,8 @@ ftrace_caller: ...@@ -73,6 +126,8 @@ ftrace_caller:
tst r0, r0 tst r0, r0
bf ftrace_stub bf ftrace_stub
STACK_CHECK()
MCOUNT_ENTER() MCOUNT_ENTER()
.globl ftrace_call .globl ftrace_call
...@@ -100,6 +155,36 @@ ftrace_stub: ...@@ -100,6 +155,36 @@ ftrace_stub:
rts rts
nop nop
#ifdef CONFIG_STACK_DEBUG
.globl stack_panic
stack_panic:
mov.l .Ldump_stack, r0
jsr @r0
nop
mov.l .Lpanic, r0
jsr @r0
mov.l .Lpanic_s, r4
rts
nop
.align 2 .align 2
.Lfunction_trace_stop: .Lfunction_trace_stop:
.long function_trace_stop .long function_trace_stop
.L_ebss:
.long _ebss
.L_init_thread_union:
.long init_thread_union
.Lpanic:
.long panic
.Lpanic_s:
.long .Lpanic_str
.Ldump_stack:
.long dump_stack
.section .rodata
.align 2
.Lpanic_str:
.string "Stack error"
#endif /* CONFIG_STACK_DEBUG */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment