[coreboot] r1012 - in coreboot-v3: arch/x86 include include/arch/x86 lib

svn at coreboot.org svn at coreboot.org
Thu Nov 13 02:28:32 CET 2008


Author: hailfinger
Date: 2008-11-13 02:28:32 +0100 (Thu, 13 Nov 2008)
New Revision: 1012

Modified:
   coreboot-v3/arch/x86/Kconfig
   coreboot-v3/arch/x86/stage1.c
   coreboot-v3/include/arch/x86/cpu.h
   coreboot-v3/include/globalvars.h
   coreboot-v3/lib/console.c
Log:
We are woefully unaware about how much stack v3 really uses.
This is a complete rewrite of my earlier stack checker proposal.
It works for CAR and RAM, has better abstraction and actually gives us
nice results.
The stack checker is default off due to its rather measurable impact on
boot speed.
Diagnostic messages are printed on first initialization, directly after
RAM init and directly before passing control to the payload. Sample qemu
log is attached. Extract from that log follows:

coreboot-3.0.986 Fri Nov  7 04:04:37 CET 2008 starting...
(console_loglevel=8)
Initial lowest stack is 0x0008fe98
Choosing fallback boot.
[...]
Done RAM init code
After RAM init, lowest stack is 0x0008fe30
Done printk() buffer move
[...]
LAR: load_file_segments: Failed for normal/payload
Before handoff to payload, lowest stack is 0x0008bf50
FATAL: No usable payload found.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Acked-by: Peter Stuge <peter at stuge.se>


Modified: coreboot-v3/arch/x86/Kconfig
===================================================================
--- coreboot-v3/arch/x86/Kconfig	2008-11-13 01:04:35 UTC (rev 1011)
+++ coreboot-v3/arch/x86/Kconfig	2008-11-13 01:28:32 UTC (rev 1012)
@@ -239,4 +239,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

Modified: coreboot-v3/arch/x86/stage1.c
===================================================================
--- coreboot-v3/arch/x86/stage1.c	2008-11-13 01:04:35 UTC (rev 1011)
+++ coreboot-v3/arch/x86/stage1.c	2008-11-13 01:28:32 UTC (rev 1012)
@@ -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();

Modified: coreboot-v3/include/arch/x86/cpu.h
===================================================================
--- coreboot-v3/include/arch/x86/cpu.h	2008-11-13 01:04:35 UTC (rev 1011)
+++ coreboot-v3/include/arch/x86/cpu.h	2008-11-13 01:28:32 UTC (rev 1012)
@@ -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: 

Modified: coreboot-v3/include/globalvars.h
===================================================================
--- coreboot-v3/include/globalvars.h	2008-11-13 01:04:35 UTC (rev 1011)
+++ coreboot-v3/include/globalvars.h	2008-11-13 01:28:32 UTC (rev 1012)
@@ -63,6 +63,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 */

Modified: coreboot-v3/lib/console.c
===================================================================
--- coreboot-v3/lib/console.c	2008-11-13 01:04:35 UTC (rev 1011)
+++ coreboot-v3/lib/console.c	2008-11-13 01:28:32 UTC (rev 1012)
@@ -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;
 }
 





More information about the coreboot mailing list