diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 3ad25983ec97..bfd712ab125c 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -2,6 +2,22 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config DEBUG_STACKOVERFLOW + bool "Check for stack overflows" + depends on DEBUG_KERNEL + help + This option will cause messages to be printed if free stack space + drops below a certain limit. + +config DEBUG_STACK_USAGE + bool "Enable stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T output. + + This option will slow down process creation somewhat. + config HAVE_ARCH_KGDB def_bool y diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 2cb0b8711fa4..83d57a85b14f 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h @@ -24,6 +24,14 @@ static inline void wrusp(unsigned long usp) __asm__ __volatile__("usp = %0;\n\t"::"da"(usp)); } +static inline unsigned long __get_SP(void) +{ + unsigned long sp; + + __asm__ __volatile__("%0 = sp;\n\t" : "=da"(sp)); + return sp; +} + /* * User space process size: 1st byte beyond user address space. * Fairly meaningless on nommu. Parts of user programs can be scattered diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h index 642769329d12..1d380def2410 100644 --- a/arch/blackfin/include/asm/thread_info.h +++ b/arch/blackfin/include/asm/thread_info.h @@ -44,6 +44,7 @@ */ #define THREAD_SIZE_ORDER 1 #define THREAD_SIZE 8192 /* 2 pages */ +#define STACK_WARN (THREAD_SIZE/8) #ifndef __ASSEMBLY__ diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 5ad07525ea3f..1624e1129681 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -120,7 +120,21 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) desc = &bad_irq_desc; irq_enter(); +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than STACK_WARN free? */ + { + long sp; + sp = __get_SP() & (THREAD_SIZE-1); + + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + dump_stack(); + printk(KERN_EMERG "%s: possible stack overflow while handling irq %i " + " only %ld bytes free\n", + __func__, irq, sp - sizeof(struct thread_info)); + } + } +#endif generic_handle_irq(irq); /* If we're the only interrupt running (ignoring IRQ15 which is for