[coreboot] [RFC] v3: Stack switching abstraction for C7 and later Intel processors

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Tue Oct 14 14:20:26 CEST 2008


Right now we face the problem that we can't support processors which
have a CAR area outside the usual RAM area. For those processors, we
have to implement a stack copying and switching mechanism. Since gcc
can't be told that the stack just moved, split stage1_main() into
stage1_main() and stage1_late().
stage1_main() is still the entry point and will handle everything up to
the point where we want to disable CAR. Switching the stack, disabling
CAR and handling other tasks related to the stack switch (printk buffer
move) is all wrapped in the switch_stack() function. switch_stack() will
then call stage1_late() which is the second part of the old stage1_main().

Test booted on qemu only.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: corebootv3-stackrebuild/arch/x86/stage1.c
===================================================================
--- corebootv3-stackrebuild/arch/x86/stage1.c	(Revision 925)
+++ corebootv3-stackrebuild/arch/x86/stage1.c	(Arbeitskopie)
@@ -143,6 +143,9 @@
 	return ret;
 }
 
+void switch_stack(void);
+void __attribute__((stdcall)) stage1_late(void);
+
 /**
  * This function is called from assembler code with its argument on the
  * stack. Force the compiler to generate always correct code for this case.
@@ -159,24 +162,8 @@
 	struct global_vars globvars;
 	int ret;
 	struct mem_file archive;
-	void *entry;
 	struct node_core_id me;
-#ifdef CONFIG_PAYLOAD_ELF_LOADER
-	struct mem_file result;
-	int elfboot_mem(struct lb_memory *mem, void *where, int size);
 
-	/* Why can't we statically init this hack? */
-	unsigned char faker[64];
-	struct lb_memory *mem = (struct lb_memory*) faker;
-
-	mem->tag = LB_TAG_MEMORY;
-	mem->size = 28;
-	mem->map[0].start.lo = mem->map[0].start.hi = 0;
-	mem->map[0].size.lo = (32*1024*1024);
-	mem->map[0].size.hi = 0;
-	mem->map[0].type = LB_MEM_RAM;
-#endif /* CONFIG_PAYLOAD_ELF_LOADER */
-
 	post_code(POST_STAGE1_MAIN);
 
 	/* before we do anything, we want to stop if we do not run
@@ -234,6 +221,25 @@
 
 	printk(BIOS_DEBUG, "Done RAM init code\n");
 
+	/* Switch the stack location from CAR to RAM, rebuild the stack,
+	 * disable CAR and continue at stage1_late(). This is all wrapped in
+	 * switch_stack to make the code easier to follow.
+	 */
+	switch_stack();
+}
+
+/**
+ * This function is called to take care of switching and rebuilding the stack
+ * so that we can cope with processors which don't support a CAR area at low
+ * addresses where CAR could be copied to RAM without problems.
+ * After the stack has been rebuilt, we switch the stack pointer to the new
+ * location, move the printk buffer and cotinue at stage1_late().
+ *
+ * NOTE: switch_stack may need to be reimplemented in processor-specific asm.
+ * TODO: Reevaluate whether printk_buffer_move should come before disable_car()
+ */
+void switch_stack()
+{
 	/* Turn off Cache-As-Ram */
 	disable_car();
 
@@ -241,7 +247,37 @@
 	/* Move the printk buffer to PRINTK_BUF_ADDR_RAM */
 	printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM);
 #endif
+	stage1_late();
+}
 
+/**
+ * This function is the second part of stage1_main() after switching the stack
+ * and disabling CAR.
+ */
+void __attribute__((stdcall)) stage1_late()
+{
+	void *entry;
+	int ret;
+	struct mem_file archive;
+#ifdef CONFIG_PAYLOAD_ELF_LOADER
+	struct mem_file result;
+	int elfboot_mem(struct lb_memory *mem, void *where, int size);
+
+	/* Why can't we statically init this hack? */
+	unsigned char faker[64];
+	struct lb_memory *mem = (struct lb_memory*) faker;
+
+	mem->tag = LB_TAG_MEMORY;
+	mem->size = 28;
+	mem->map[0].start.lo = mem->map[0].start.hi = 0;
+	mem->map[0].size.lo = (32*1024*1024);
+	mem->map[0].size.hi = 0;
+	mem->map[0].type = LB_MEM_RAM;
+#endif /* CONFIG_PAYLOAD_ELF_LOADER */
+
+	// location and size of image.
+	init_archive(&archive);
+
 	entry = load_file_segments(&archive, "normal/stage2");
 	if (entry == (void *)-1)
 		die("FATAL: Failed loading stage2.");


-- 
http://www.hailfinger.org/





More information about the coreboot mailing list