diff options
author | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 05:20:16 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 05:20:16 -0400 |
commit | d153ea88dccf003173315b5d21acabebb897fb4a (patch) | |
tree | 5cdc96ef0ec58026d82c03f76250ac1833f566d4 | |
parent | 7a440c950efb5cdc8a05cc6c3ec8fc864b60ef77 (diff) |
sh: stack debugging support.
This adds a DEBUG_STACK_USAGE and DEBUG_STACKOVERFLOW for SH.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/Kconfig.debug | 16 | ||||
-rw-r--r-- | arch/sh/kernel/head.S | 4 | ||||
-rw-r--r-- | arch/sh/kernel/irq.c | 17 | ||||
-rw-r--r-- | arch/sh/kernel/vmlinux.lds.S | 14 | ||||
-rw-r--r-- | include/asm-sh/page.h | 2 | ||||
-rw-r--r-- | include/asm-sh/thread_info.h | 12 |
6 files changed, 52 insertions, 13 deletions
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 | |||
30 | when the kernel may crash or hang before the serial console is | 30 | when the kernel may crash or hang before the serial console is |
31 | initialised. If unsure, say N. | 31 | initialised. If unsure, say N. |
32 | 32 | ||
33 | config DEBUG_STACKOVERFLOW | ||
34 | bool "Check for stack overflows" | ||
35 | depends on DEBUG_KERNEL | ||
36 | help | ||
37 | This option will cause messages to be printed if free stack space | ||
38 | drops below a certain limit. | ||
39 | |||
40 | config DEBUG_STACK_USAGE | ||
41 | bool "Stack utilization instrumentation" | ||
42 | depends on DEBUG_KERNEL | ||
43 | help | ||
44 | Enables the display of the minimum amount of free stack which each | ||
45 | task has ever had available in the sysrq-T and sysrq-P debug output. | ||
46 | |||
47 | This option will slow down process creation somewhat. | ||
48 | |||
33 | config KGDB | 49 | config KGDB |
34 | bool "Include KGDB kernel debugger" | 50 | bool "Include KGDB kernel debugger" |
35 | select FRAME_POINTER | 51 | 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 @@ | |||
11 | * Head.S contains the SH exception handlers and startup code. | 11 | * Head.S contains the SH exception handlers and startup code. |
12 | */ | 12 | */ |
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/thread_info.h> | ||
15 | #include <asm/page.h> | ||
14 | 16 | ||
15 | #ifdef CONFIG_CPU_SH4A | 17 | #ifdef CONFIG_CPU_SH4A |
16 | #define SYNCO() synco | 18 | #define SYNCO() synco |
@@ -95,7 +97,7 @@ ENTRY(_stext) | |||
95 | 97 | ||
96 | .balign 4 | 98 | .balign 4 |
97 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF | 99 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF |
98 | 2: .long init_thread_union+8192 | 100 | 2: .long init_thread_union+THREAD_SIZE |
99 | 3: .long __bss_start | 101 | 3: .long __bss_start |
100 | 4: .long _end | 102 | 4: .long _end |
101 | 5: .long start_kernel | 103 | 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: | |||
60 | } | 60 | } |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | |||
64 | asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | 63 | asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, |
65 | unsigned long r6, unsigned long r7, | 64 | unsigned long r6, unsigned long r7, |
66 | struct pt_regs regs) | 65 | struct pt_regs regs) |
@@ -69,6 +68,22 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, | |||
69 | 68 | ||
70 | irq_enter(); | 69 | irq_enter(); |
71 | 70 | ||
71 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | ||
72 | /* Debugging check for stack overflow: is there less than 1KB free? */ | ||
73 | { | ||
74 | long sp; | ||
75 | |||
76 | __asm__ __volatile__ ("and r15, %0" : | ||
77 | "=r" (sp) : "0" (THREAD_SIZE - 1)); | ||
78 | |||
79 | if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { | ||
80 | printk("do_IRQ: stack overflow: %ld\n", | ||
81 | sp - sizeof(struct thread_info)); | ||
82 | dump_stack(); | ||
83 | } | ||
84 | } | ||
85 | #endif | ||
86 | |||
72 | #ifdef CONFIG_CPU_HAS_INTEVT | 87 | #ifdef CONFIG_CPU_HAS_INTEVT |
73 | __asm__ __volatile__ ( | 88 | __asm__ __volatile__ ( |
74 | #ifdef CONFIG_CPU_HAS_SR_RB | 89 | #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 @@ | |||
2 | * ld script to make SuperH Linux kernel | 2 | * ld script to make SuperH Linux kernel |
3 | * Written by Niibe Yutaka | 3 | * Written by Niibe Yutaka |
4 | */ | 4 | */ |
5 | #include <asm/thread_info.h> | ||
6 | #include <asm/page.h> | ||
5 | #include <asm-generic/vmlinux.lds.h> | 7 | #include <asm-generic/vmlinux.lds.h> |
6 | 8 | ||
7 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 9 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
@@ -40,16 +42,16 @@ SECTIONS | |||
40 | *(.data) | 42 | *(.data) |
41 | 43 | ||
42 | /* Align the initial ramdisk image (INITRD) on page boundaries. */ | 44 | /* Align the initial ramdisk image (INITRD) on page boundaries. */ |
43 | . = ALIGN(4096); | 45 | . = ALIGN(PAGE_SIZE); |
44 | __rd_start = .; | 46 | __rd_start = .; |
45 | *(.initrd) | 47 | *(.initrd) |
46 | . = ALIGN(4096); | 48 | . = ALIGN(PAGE_SIZE); |
47 | __rd_end = .; | 49 | __rd_end = .; |
48 | 50 | ||
49 | CONSTRUCTORS | 51 | CONSTRUCTORS |
50 | } | 52 | } |
51 | 53 | ||
52 | . = ALIGN(4096); | 54 | . = ALIGN(PAGE_SIZE); |
53 | .data.page_aligned : { *(.data.idt) } | 55 | .data.page_aligned : { *(.data.idt) } |
54 | 56 | ||
55 | . = ALIGN(32); | 57 | . = ALIGN(32); |
@@ -60,10 +62,10 @@ SECTIONS | |||
60 | 62 | ||
61 | _edata = .; /* End of data section */ | 63 | _edata = .; /* End of data section */ |
62 | 64 | ||
63 | . = ALIGN(8192); /* init_task */ | 65 | . = ALIGN(THREAD_SIZE); /* init_task */ |
64 | .data.init_task : { *(.data.init_task) } | 66 | .data.init_task : { *(.data.init_task) } |
65 | 67 | ||
66 | . = ALIGN(4096); /* Init code and data */ | 68 | . = ALIGN(PAGE_SIZE); /* Init code and data */ |
67 | __init_begin = .; | 69 | __init_begin = .; |
68 | _sinittext = .; | 70 | _sinittext = .; |
69 | .init.text : { *(.init.text) } | 71 | .init.text : { *(.init.text) } |
@@ -94,7 +96,7 @@ SECTIONS | |||
94 | __machvec_start = .; | 96 | __machvec_start = .; |
95 | .init.machvec : { *(.init.machvec) } | 97 | .init.machvec : { *(.init.machvec) } |
96 | __machvec_end = .; | 98 | __machvec_end = .; |
97 | . = ALIGN(4096); | 99 | . = ALIGN(PAGE_SIZE); |
98 | __init_end = .; | 100 | __init_end = .; |
99 | 101 | ||
100 | . = ALIGN(4); | 102 | . = 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 @@ | |||
16 | 16 | ||
17 | /* PAGE_SHIFT determines the page size */ | 17 | /* PAGE_SHIFT determines the page size */ |
18 | #define PAGE_SHIFT 12 | 18 | #define PAGE_SHIFT 12 |
19 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | 19 | #define PAGE_SIZE (1 << PAGE_SHIFT) |
20 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 20 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
21 | #define PTE_MASK PAGE_MASK | 21 | #define PTE_MASK PAGE_MASK |
22 | 22 | ||
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 { | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define PREEMPT_ACTIVE 0x10000000 | 31 | #define PREEMPT_ACTIVE 0x10000000 |
32 | #define THREAD_SIZE (PAGE_SIZE * 2) | ||
33 | #define STACK_WARN (THREAD_SIZE / 8) | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * macros/functions for gaining access to the thread information structure | 36 | * macros/functions for gaining access to the thread information structure |
@@ -50,8 +52,6 @@ struct thread_info { | |||
50 | #define init_thread_info (init_thread_union.thread_info) | 52 | #define init_thread_info (init_thread_union.thread_info) |
51 | #define init_stack (init_thread_union.stack) | 53 | #define init_stack (init_thread_union.stack) |
52 | 54 | ||
53 | #define THREAD_SIZE (2*PAGE_SIZE) | ||
54 | |||
55 | /* how to get the thread information struct from C */ | 55 | /* how to get the thread information struct from C */ |
56 | static inline struct thread_info *current_thread_info(void) | 56 | static inline struct thread_info *current_thread_info(void) |
57 | { | 57 | { |
@@ -73,8 +73,12 @@ static inline struct thread_info *current_thread_info(void) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /* thread information allocation */ | 75 | /* thread information allocation */ |
76 | #define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) | 76 | #ifdef CONFIG_DEBUG_STACK_USAGE |
77 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) | 77 | #define alloc_thread_info(ti) kzalloc(THREAD_SIZE, GFP_KERNEL) |
78 | #else | ||
79 | #define alloc_thread_info(ti) kmalloc(THREAD_SIZE, GFP_KERNEL) | ||
80 | #endif | ||
81 | #define free_thread_info(ti) kfree(ti) | ||
78 | 82 | ||
79 | #else /* !__ASSEMBLY__ */ | 83 | #else /* !__ASSEMBLY__ */ |
80 | 84 | ||