diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig.debug | 9 | ||||
-rw-r--r-- | arch/mips/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/mips/kernel/irq.c | 24 |
3 files changed, 35 insertions, 0 deletions
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 43dc27997730..f437cd1fafb8 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug | |||
@@ -67,6 +67,15 @@ config CMDLINE_OVERRIDE | |||
67 | 67 | ||
68 | Normally, you will choose 'N' here. | 68 | Normally, you will choose 'N' here. |
69 | 69 | ||
70 | config DEBUG_STACKOVERFLOW | ||
71 | bool "Check for stack overflows" | ||
72 | depends on DEBUG_KERNEL | ||
73 | help | ||
74 | This option will cause messages to be printed if free stack space | ||
75 | drops below a certain limit(2GB on MIPS). The debugging option | ||
76 | provides another way to check stack overflow happened on kernel mode | ||
77 | stack usually caused by nested interruption. | ||
78 | |||
70 | config DEBUG_STACK_USAGE | 79 | config DEBUG_STACK_USAGE |
71 | bool "Enable stack utilization instrumentation" | 80 | bool "Enable stack utilization instrumentation" |
72 | depends on DEBUG_KERNEL | 81 | depends on DEBUG_KERNEL |
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 70df9c0d3c5b..d309556cacf8 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h | |||
@@ -83,6 +83,8 @@ register struct thread_info *__current_thread_info __asm__("$28"); | |||
83 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) | 83 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) |
84 | #define THREAD_MASK (THREAD_SIZE - 1UL) | 84 | #define THREAD_MASK (THREAD_SIZE - 1UL) |
85 | 85 | ||
86 | #define STACK_WARN (THREAD_SIZE / 8) | ||
87 | |||
86 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | 88 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR |
87 | 89 | ||
88 | #ifdef CONFIG_DEBUG_STACK_USAGE | 90 | #ifdef CONFIG_DEBUG_STACK_USAGE |
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index c6345f579a8a..4f93db58a79e 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c | |||
@@ -151,6 +151,29 @@ void __init init_IRQ(void) | |||
151 | #endif | 151 | #endif |
152 | } | 152 | } |
153 | 153 | ||
154 | #ifdef DEBUG_STACKOVERFLOW | ||
155 | static inline void check_stack_overflow(void) | ||
156 | { | ||
157 | unsigned long sp; | ||
158 | |||
159 | __asm__ __volatile__("move %0, $sp" : "=r" (sp)); | ||
160 | sp &= THREAD_MASK; | ||
161 | |||
162 | /* | ||
163 | * Check for stack overflow: is there less than STACK_WARN free? | ||
164 | * STACK_WARN is defined as 1/8 of THREAD_SIZE by default. | ||
165 | */ | ||
166 | if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { | ||
167 | printk("do_IRQ: stack overflow: %ld\n", | ||
168 | sp - sizeof(struct thread_info)); | ||
169 | dump_stack(); | ||
170 | } | ||
171 | } | ||
172 | #else | ||
173 | static inline void check_stack_overflow(void) {} | ||
174 | #endif | ||
175 | |||
176 | |||
154 | /* | 177 | /* |
155 | * do_IRQ handles all normal device IRQ's (the special | 178 | * do_IRQ handles all normal device IRQ's (the special |
156 | * SMP cross-CPU interrupts have their own specific | 179 | * SMP cross-CPU interrupts have their own specific |
@@ -159,6 +182,7 @@ void __init init_IRQ(void) | |||
159 | void __irq_entry do_IRQ(unsigned int irq) | 182 | void __irq_entry do_IRQ(unsigned int irq) |
160 | { | 183 | { |
161 | irq_enter(); | 184 | irq_enter(); |
185 | check_stack_overflow(); | ||
162 | __DO_IRQ_SMTC_HOOK(irq); | 186 | __DO_IRQ_SMTC_HOOK(irq); |
163 | generic_handle_irq(irq); | 187 | generic_handle_irq(irq); |
164 | irq_exit(); | 188 | irq_exit(); |