Index: corebootv3-stackcheck/include/globalvars.h
===================================================================
--- corebootv3-stackcheck/include/globalvars.h	(Revision 986)
+++ corebootv3-stackcheck/include/globalvars.h	(Arbeitskopie)
@@ -59,6 +59,10 @@
 	struct sys_info sys_info;
 	/* has the spd hardware been set up? */
 	int spd_inited;
+	int ram_available;
+#ifdef CONFIG_CHECK_STACK_USAGE
+	void *loweststack;
+#endif
 };
 
 #endif /* GLOBALVARS_H */
Index: corebootv3-stackcheck/include/arch/x86/cpu.h
===================================================================
--- corebootv3-stackcheck/include/arch/x86/cpu.h	(Revision 986)
+++ corebootv3-stackcheck/include/arch/x86/cpu.h	(Arbeitskopie)
@@ -265,6 +265,7 @@
 EXPORT_SYMBOL(bottom_of_stack);
 struct global_vars * global_vars(void);
 EXPORT_SYMBOL(global_vars);
+void check_stack(void);
 
 #define CAR_STACK_BASE (CONFIG_CARBASE + CONFIG_CARSIZE - 4)
 #define RAM_STACK_BASE 0x88ffc
@@ -278,6 +279,8 @@
 #else
 #define CAR_STACK_SIZE (CONFIG_CARSIZE - 4)
 #endif
+/* To be honest, this limit is arbitrary and only used for stack checking. */
+#define RAM_STACK_SIZE (65536 - 4)
 
 /* resource maps. These started out as special for the K8 but now have more general usage */
 /* it's not totally clear that the type and union are a great idea, but see the v2 code: 
Index: corebootv3-stackcheck/lib/console.c
===================================================================
--- corebootv3-stackcheck/lib/console.c	(Revision 986)
+++ corebootv3-stackcheck/lib/console.c	(Arbeitskopie)
@@ -150,6 +150,9 @@
 	i += vtxprintf(console_tx_byte, (void *)0, fmt, args);
 	va_end(args);
 
+#ifdef CONFIG_CHECK_STACK_USAGE
+	check_stack();
+#endif
 	return i;
 }
 
Index: corebootv3-stackcheck/arch/x86/Kconfig
===================================================================
--- corebootv3-stackcheck/arch/x86/Kconfig	(Revision 986)
+++ corebootv3-stackcheck/arch/x86/Kconfig	(Arbeitskopie)
@@ -227,4 +227,13 @@
 	help
 	  Test the CAR area after it has been set up.
 
+config CHECK_STACK_USAGE
+	bool "Check stack usage"
+	default n
+	help
+	  Continuously monitor stack usage and keep statistics.
+	  The monitoring code is invoked from printk because printk is
+	  a leaf function and consumes quite a bit of stack for itself.
+	  This slows down booting a LOT.
+
 endmenu
Index: corebootv3-stackcheck/arch/x86/stage1.c
===================================================================
--- corebootv3-stackcheck/arch/x86/stage1.c	(Revision 986)
+++ corebootv3-stackcheck/arch/x86/stage1.c	(Arbeitskopie)
@@ -105,6 +105,28 @@
 
 }
 
+#ifdef CONFIG_CHECK_STACK_USAGE
+/* STACKFILL_BYTE could be a special value like 0x6b. Just make sure the stage0
+ * code fills the complete CAR area with it. And the stack switching needs to
+ * overwrite the unused parts of the stack with STACKFILL_BYTE as well.
+ */
+#define STACKFILL_BYTE 0x0
+void check_stack()
+{
+	unsigned long stacksize, i;
+	char *lowestaddr;
+	if (global_vars()->ram_available)
+		stacksize = RAM_STACK_SIZE;
+	else
+		stacksize = CAR_STACK_SIZE;
+	lowestaddr = bottom_of_stack() - stacksize;
+	for (i = 0; i < stacksize; i++)
+		if (lowestaddr[i] != STACKFILL_BYTE)
+			break;
+	global_vars()->loweststack = lowestaddr + i;
+}
+#endif
+
 void dump_mem_range(int msg_level, unsigned char *buf, int size)
 {
 	int i;
@@ -194,6 +216,10 @@
 	 */
 	console_init();
 
+#ifdef CONFIG_CHECK_STACK_USAGE
+	printk(BIOS_DEBUG, "Initial lowest stack is %p\n",
+		global_vars()->loweststack);
+#endif
 	if (bist!=0) {
 		printk(BIOS_INFO, "BIST FAILED: %08x", bist);
 		die("");
@@ -227,6 +253,10 @@
 		die("Failed RAM init code\n");
 
 	printk(BIOS_DEBUG, "Done RAM init code\n");
+#ifdef CONFIG_CHECK_STACK_USAGE
+	printk(BIOS_DEBUG, "After RAM init, lowest stack is %p\n",
+		global_vars()->loweststack);
+#endif
 
 	/* Switch the stack location from CAR to RAM, rebuild the stack,
 	 * disable CAR and continue at stage1_phase3(). This is all wrapped in
@@ -299,6 +329,9 @@
 	mem->map[0].type = LB_MEM_RAM;
 #endif /* CONFIG_PAYLOAD_ELF_LOADER */
 
+	/* Provide an easy way to check whether RAM is available. */
+	global_vars()->ram_available = 1;
+
 	// location and size of image.
 	init_archive(&archive);
 
@@ -318,6 +351,10 @@
 #endif /* CONFIG_PAYLOAD_ELF_LOADER */
 
 	entry = load_file_segments(&archive, "normal/payload");
+#ifdef CONFIG_CHECK_STACK_USAGE
+	printk(BIOS_DEBUG, "Before handoff to payload, lowest stack is %p\n",
+		global_vars()->loweststack);
+#endif
 	if (entry != (void*)-1) {
 		/* Final coreboot call before handing off to the payload. */
 		mainboard_pre_payload();
