diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 75ed1be8a49e..f0188e626be0 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -30,6 +30,22 @@ config EARLY_PRINTK when the kernel may crash or hang before the serial console is initialised. If unsure, say N. +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 "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 and sysrq-P debug output. + + This option will slow down process creation somewhat. + config KGDB bool "Include KGDB kernel debugger" select FRAME_POINTER diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index c5e363872b91..3e7d00b7985a 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -11,6 +11,8 @@ * Head.S contains the SH exception handlers and startup code. */ #include +#include +#include #ifdef CONFIG_CPU_SH4A #define SYNCO() synco @@ -95,7 +97,7 @@ ENTRY(_stext) .balign 4 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF -2: .long init_thread_union+8192 +2: .long init_thread_union+THREAD_SIZE 3: .long __bss_start 4: .long _end 5: .long start_kernel diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index c2e07f7f3496..7066611aeb72 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -60,7 +60,6 @@ unlock: } #endif - asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) @@ -69,6 +68,22 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, irq_enter(); +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than 1KB free? */ + { + long sp; + + __asm__ __volatile__ ("and r15, %0" : + "=r" (sp) : "0" (THREAD_SIZE - 1)); + + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + printk("do_IRQ: stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + #ifdef CONFIG_CPU_HAS_INTEVT __asm__ __volatile__ ( #ifdef CONFIG_CPU_HAS_SR_RB diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index eb860c51c697..0220d8a838a7 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -2,6 +2,8 @@ * ld script to make SuperH Linux kernel * Written by Niibe Yutaka */ +#include +#include #include #ifdef CONFIG_CPU_LITTLE_ENDIAN @@ -40,16 +42,16 @@ SECTIONS *(.data) /* Align the initial ramdisk image (INITRD) on page boundaries. */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __rd_start = .; *(.initrd) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __rd_end = .; CONSTRUCTORS } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data.page_aligned : { *(.data.idt) } . = ALIGN(32); @@ -60,10 +62,10 @@ SECTIONS _edata = .; /* End of data section */ - . = ALIGN(8192); /* init_task */ + . = ALIGN(THREAD_SIZE); /* init_task */ .data.init_task : { *(.data.init_task) } - . = ALIGN(4096); /* Init code and data */ + . = ALIGN(PAGE_SIZE); /* Init code and data */ __init_begin = .; _sinittext = .; .init.text : { *(.init.text) } @@ -94,7 +96,7 @@ SECTIONS __machvec_start = .; .init.machvec : { *(.init.machvec) } __machvec_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_end = .; . = ALIGN(4); diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index e9135532d00c..888d6fe0030e 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -16,7 +16,7 @@ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) #define PTE_MASK PAGE_MASK diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index 5eb874b065a6..605259f88113 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h @@ -29,6 +29,8 @@ struct thread_info { #endif #define PREEMPT_ACTIVE 0x10000000 +#define THREAD_SIZE (PAGE_SIZE * 2) +#define STACK_WARN (THREAD_SIZE / 8) /* * macros/functions for gaining access to the thread information structure @@ -50,8 +52,6 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) -#define THREAD_SIZE (2*PAGE_SIZE) - /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { @@ -73,8 +73,12 @@ static inline struct thread_info *current_thread_info(void) } /* thread information allocation */ -#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) -#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(ti) kzalloc(THREAD_SIZE, GFP_KERNEL) +#else +#define alloc_thread_info(ti) kmalloc(THREAD_SIZE, GFP_KERNEL) +#endif +#define free_thread_info(ti) kfree(ti) #else /* !__ASSEMBLY__ */