summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/Kconfig.debug16
-rw-r--r--arch/sh/kernel/head.S4
-rw-r--r--arch/sh/kernel/irq.c17
-rw-r--r--arch/sh/kernel/vmlinux.lds.S14
-rw-r--r--include/asm-sh/page.h2
-rw-r--r--include/asm-sh/thread_info.h12
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
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 <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
#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 <asm/thread_info.h>
+#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
#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__ */