Commit d153ea88 authored by Paul Mundt's avatar Paul Mundt

sh: stack debugging support.

This adds a DEBUG_STACK_USAGE and DEBUG_STACKOVERFLOW for SH.
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 7a440c95
...@@ -30,6 +30,22 @@ config EARLY_PRINTK ...@@ -30,6 +30,22 @@ config EARLY_PRINTK
when the kernel may crash or hang before the serial console is when the kernel may crash or hang before the serial console is
initialised. If unsure, say N. 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 config KGDB
bool "Include KGDB kernel debugger" bool "Include KGDB kernel debugger"
select FRAME_POINTER select FRAME_POINTER
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* Head.S contains the SH exception handlers and startup code. * Head.S contains the SH exception handlers and startup code.
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#ifdef CONFIG_CPU_SH4A #ifdef CONFIG_CPU_SH4A
#define SYNCO() synco #define SYNCO() synco
...@@ -95,7 +97,7 @@ ENTRY(_stext) ...@@ -95,7 +97,7 @@ ENTRY(_stext)
.balign 4 .balign 4
1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 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 3: .long __bss_start
4: .long _end 4: .long _end
5: .long start_kernel 5: .long start_kernel
......
...@@ -60,7 +60,6 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -60,7 +60,6 @@ int show_interrupts(struct seq_file *p, void *v)
} }
#endif #endif
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r6, unsigned long r7,
struct pt_regs regs) struct pt_regs regs)
...@@ -69,6 +68,22 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, ...@@ -69,6 +68,22 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
irq_enter(); 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 #ifdef CONFIG_CPU_HAS_INTEVT
__asm__ __volatile__ ( __asm__ __volatile__ (
#ifdef CONFIG_CPU_HAS_SR_RB #ifdef CONFIG_CPU_HAS_SR_RB
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
* ld script to make SuperH Linux kernel * ld script to make SuperH Linux kernel
* Written by Niibe Yutaka * Written by Niibe Yutaka
*/ */
#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h> #include <asm-generic/vmlinux.lds.h>
#ifdef CONFIG_CPU_LITTLE_ENDIAN #ifdef CONFIG_CPU_LITTLE_ENDIAN
...@@ -40,16 +42,16 @@ SECTIONS ...@@ -40,16 +42,16 @@ SECTIONS
*(.data) *(.data)
/* Align the initial ramdisk image (INITRD) on page boundaries. */ /* Align the initial ramdisk image (INITRD) on page boundaries. */
. = ALIGN(4096); . = ALIGN(PAGE_SIZE);
__rd_start = .; __rd_start = .;
*(.initrd) *(.initrd)
. = ALIGN(4096); . = ALIGN(PAGE_SIZE);
__rd_end = .; __rd_end = .;
CONSTRUCTORS CONSTRUCTORS
} }
. = ALIGN(4096); . = ALIGN(PAGE_SIZE);
.data.page_aligned : { *(.data.idt) } .data.page_aligned : { *(.data.idt) }
. = ALIGN(32); . = ALIGN(32);
...@@ -60,10 +62,10 @@ SECTIONS ...@@ -60,10 +62,10 @@ SECTIONS
_edata = .; /* End of data section */ _edata = .; /* End of data section */
. = ALIGN(8192); /* init_task */ . = ALIGN(THREAD_SIZE); /* init_task */
.data.init_task : { *(.data.init_task) } .data.init_task : { *(.data.init_task) }
. = ALIGN(4096); /* Init code and data */ . = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .; __init_begin = .;
_sinittext = .; _sinittext = .;
.init.text : { *(.init.text) } .init.text : { *(.init.text) }
...@@ -94,7 +96,7 @@ SECTIONS ...@@ -94,7 +96,7 @@ SECTIONS
__machvec_start = .; __machvec_start = .;
.init.machvec : { *(.init.machvec) } .init.machvec : { *(.init.machvec) }
__machvec_end = .; __machvec_end = .;
. = ALIGN(4096); . = ALIGN(PAGE_SIZE);
__init_end = .; __init_end = .;
. = ALIGN(4); . = ALIGN(4);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
/* PAGE_SHIFT determines the page size */ /* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12 #define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_MASK (~(PAGE_SIZE-1))
#define PTE_MASK PAGE_MASK #define PTE_MASK PAGE_MASK
......
...@@ -29,6 +29,8 @@ struct thread_info { ...@@ -29,6 +29,8 @@ struct thread_info {
#endif #endif
#define PREEMPT_ACTIVE 0x10000000 #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 * macros/functions for gaining access to the thread information structure
...@@ -50,8 +52,6 @@ struct thread_info { ...@@ -50,8 +52,6 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack) #define init_stack (init_thread_union.stack)
#define THREAD_SIZE (2*PAGE_SIZE)
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void) static inline struct thread_info *current_thread_info(void)
{ {
...@@ -73,8 +73,12 @@ 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 */ /* thread information allocation */
#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) #ifdef CONFIG_DEBUG_STACK_USAGE
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) #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__ */ #else /* !__ASSEMBLY__ */
......
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