sh: stack debugging support.

This adds a DEBUG_STACK_USAGE and DEBUG_STACKOVERFLOW for SH.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 75ed1be..f0188e6 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -30,6 +30,22 @@
 	  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 c5e3638..3e7d00b 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 @@
 
 	.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 c2e07f7..7066611 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -60,7 +60,6 @@
 }
 #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 @@
 
 	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 eb860c5..0220d8a 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 @@
 	*(.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 @@
 
   _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 @@
   __machvec_start = .;
   .init.machvec : { *(.init.machvec) }
   __machvec_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
   . = ALIGN(4);