aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig.debug9
-rw-r--r--arch/mips/include/asm/thread_info.h2
-rw-r--r--arch/mips/kernel/irq.c24
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
70config 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
70config DEBUG_STACK_USAGE 79config 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
155static 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
173static 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)
159void __irq_entry do_IRQ(unsigned int irq) 182void __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();