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

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Thu Oct 16 04:17:43 CEST 2008


On 15.10.2008 19:06, ron minnich wrote:
> On Wed, Oct 15, 2008 at 10:04 AM, Carl-Daniel Hailfinger
> <c-d.hailfinger.devel.2006 at gmx.net> wrote:
>   
>> I'll be back in ~3 hours. If you have acked this in the meanwhile, I
>> will commit, otherwise I'll rework.
>>     
>
> let's get a complete patch set, then I will test on geode and simnow
> tonight. This all looks fine, but it makes me nervous.
>   

Sure. Final version with lots and lots of comments follows. Test booted
in Qemu.
The patch even fixes up the documentation!

Notes about this patch:
- Code flow is almost unchanged for Qemu, K8 and Geode. No extensive new
testing required.
- We can support stack-keeping and stack-relocating architectures at the
same time, so C7 is definitely supportable
- The comment in stage1_phase2 says "some of this is not yet done". That
refers to the nonexisting code for stack switching on C7.
- "Minimal changes, maximum benefit".

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

Index: corebootv3-stackrebuild/include/arch/x86/stage1.h
===================================================================
--- corebootv3-stackrebuild/include/arch/x86/stage1.h	(Revision 0)
+++ corebootv3-stackrebuild/include/arch/x86/stage1.h	(Revision 0)
@@ -0,0 +1,2 @@
+void stage1_phase2(void);
+void __attribute__((stdcall)) stage1_phase3(void);
Index: corebootv3-stackrebuild/mainboard/emulation/qemu-x86/stage1.c
===================================================================
--- corebootv3-stackrebuild/mainboard/emulation/qemu-x86/stage1.c	(Revision 931)
+++ corebootv3-stackrebuild/mainboard/emulation/qemu-x86/stage1.c	(Arbeitskopie)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <stage1.h>
+
 /* printk() will not yet output anything. */
 
 /** 
@@ -34,6 +36,7 @@
 
 void disable_car(void)
 {
+	stage1_phase3();
 }
 
 
Index: corebootv3-stackrebuild/doc/design/newboot.lyx
===================================================================
--- corebootv3-stackrebuild/doc/design/newboot.lyx	(Revision 931)
+++ corebootv3-stackrebuild/doc/design/newboot.lyx	(Arbeitskopie)
@@ -759,7 +759,7 @@
 \end_layout
 
 \begin_layout Standard
-Initial entry point for stage 1 is arch/{architecture}/stage1.c:stage1_main().
+Initial entry point for stage 1 is arch/{architecture}/stage1.c:stage1_phase1().
 \end_layout
 
 \begin_layout Standard
Index: corebootv3-stackrebuild/arch/x86/via/stage0.S
===================================================================
--- corebootv3-stackrebuild/arch/x86/via/stage0.S	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/via/stage0.S	(Arbeitskopie)
@@ -189,7 +189,7 @@
 	pushl	$0
 	/* First parameter: bist */
 	pushl	%eax
-	call	stage1_main
+	call	stage1_phase1
 	/* We will not go back. */
 
 fixed_mtrr_msr:
Index: corebootv3-stackrebuild/arch/x86/geodelx/stage0.S
===================================================================
--- corebootv3-stackrebuild/arch/x86/geodelx/stage0.S	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/geodelx/stage0.S	(Arbeitskopie)
@@ -271,7 +271,7 @@
 	pushl	$0
 	/* First parameter: bist */
 	pushl	%eax
-	call	stage1_main
+	call	stage1_phase1
 	/* We will not go back. */
 
 #include "../stage0_common.S"
Index: corebootv3-stackrebuild/arch/x86/geodelx/stage1.c
===================================================================
--- corebootv3-stackrebuild/arch/x86/geodelx/stage1.c	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/geodelx/stage1.c	(Arbeitskopie)
@@ -24,6 +24,7 @@
 #include <amd_geodelx.h>
 #include <console.h>
 #include <msr.h>
+#include <stage1.h>
 
 static const struct msrinit msr_table[] = {
   /* Setup access to cache under 1MB. */
@@ -93,4 +94,5 @@
 	banner(BIOS_DEBUG, "Disable_car: done wbinvd");
 	northbridge_init_early();
 	banner(BIOS_DEBUG, "disable_car: done");
+	stage1_phase3();
 }
Index: corebootv3-stackrebuild/arch/x86/i586/stage0.S
===================================================================
--- corebootv3-stackrebuild/arch/x86/i586/stage0.S	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/i586/stage0.S	(Arbeitskopie)
@@ -339,7 +339,7 @@
 	pushl	$0
 	/* First parameter: bist */
 	pushl	%eax
-	call	stage1_main
+	call	stage1_phase1
 	/* We will not go back. */
 
 fixed_mtrr_msr:
Index: corebootv3-stackrebuild/arch/x86/amd/k8/stage1.c
===================================================================
--- corebootv3-stackrebuild/arch/x86/amd/k8/stage1.c	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/amd/k8/stage1.c	(Arbeitskopie)
@@ -26,6 +26,7 @@
 #include <macros.h>
 #include <cpu.h>
 #include <amd/k8/k8.h>
+#include <stage1.h>
 
 /**
  * Set the MTRR for initial ram access. 
@@ -73,4 +74,5 @@
 	/* we're now running in ram. Although this will be called again, it does no harm to call it here. */
 	set_init_ram_access();
 	banner(BIOS_DEBUG, "disable_car: done");
+	stage1_phase3();
 }
Index: corebootv3-stackrebuild/arch/x86/amd/stage0.S
===================================================================
--- corebootv3-stackrebuild/arch/x86/amd/stage0.S	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/amd/stage0.S	(Arbeitskopie)
@@ -341,7 +341,7 @@
 	pushl	%ebx
 	/* First parameter: bist */
 	pushl	%eax
-	call	stage1_main
+	call	stage1_phase1
 	/* We will not go back. */
 
 	movb	$0xAF, %al		/* Should never see this postcode */
Index: corebootv3-stackrebuild/arch/x86/stage1.c
===================================================================
--- corebootv3-stackrebuild/arch/x86/stage1.c	(Revision 931)
+++ corebootv3-stackrebuild/arch/x86/stage1.c	(Arbeitskopie)
@@ -30,6 +30,7 @@
 #include <mc146818rtc.h>
 #include <cpu.h>
 #include <multiboot.h>
+#include <stage1.h>
 
 #ifdef CONFIG_PAYLOAD_ELF_LOADER
 /* ah, well, what a mess! This is a hard code. FIX ME but how? 
@@ -154,29 +155,13 @@
  * that we are restarting after some sort of reconfiguration. Note that we could use it on geode but 
  * do not at present. 
  */
-void __attribute__((stdcall)) stage1_main(u32 bist, u32 init_detected)
+void __attribute__((stdcall)) stage1_phase1(u32 bist, u32 init_detected)
 {
 	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,14 +219,77 @@
 
 	printk(BIOS_DEBUG, "Done RAM init code\n");
 
-	/* Turn off Cache-As-Ram */
-	disable_car();
+	/* Switch the stack location from CAR to RAM, rebuild the stack,
+	 * disable CAR and continue at stage1_phase3(). This is all wrapped in
+	 * stage1_phase2() to make the code easier to follow.
+	 * We will NEVER return.
+	 */
+	stage1_phase2();
 
+	/* If we reach this point, something went terribly wrong. */
+	die("The world is broken.\n");
+}
+
+/**
+ * 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.
+ * This function handles everything related to switching off CAR and moving
+ * important data from CAR to RAM.
+ * 1.  Perform all work which can be done while CAR and RAM are both active.
+ *     That's mainly moving the printk buffer around.
+ * 2a. Optionally back up the new stack location (desirable for S3).
+ * 2b. Optionally rebuild the stack at another location.
+ * 2c. Switch stack pointer to the new stack if the stack was rebuilt.
+ * 3.  Disable CAR.
+ * 4.  Call or jump to stage1_phase3.
+ * Steps 2a-4 have to be done in asm. That's what the oddly named disable_car()
+ * function does.
+ *
+ * TODO: Some parts of the list above are not yet done, so the code will not
+ * yet work on C7.
+ */
+void stage1_phase2()
+{
 #ifdef CONFIG_CONSOLE_BUFFER
 	/* Move the printk buffer to PRINTK_BUF_ADDR_RAM */
 	printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM);
 #endif
+	/* Turn off Cache-As-Ram */
+	disable_car();
 
+	/* If we reach this point, something went terribly wrong. */
+	die("The world is broken.\n");
+}
+
+/**
+ * This function is the second part of the former stage1_main() after
+ * switching the stack and disabling CAR.
+ */
+void __attribute__((stdcall)) stage1_phase3()
+{
+	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