[coreboot] [PATCH] v3: Move stage1 global variable management from asm to C
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Mon Aug 18 16:00:02 CEST 2008
Move stage1 global variable management from asm to C. The stage0 asm
code now unconditionally pushes an empty pointer to the stack which is a
placeholder for the pointer to global variable storage. That pointer and
the global variable storage are initialized in global_vars_init().
Build tested on all targets, boot tested on Qemu.
NOTES:
- The code is not yet MP safe, but that's due to v3 not being MP safe in
general (and the comments contradict the code regarding MP features).
- K8 code now works by accident.
- Segher needs to review which attributes globvars needs to not be
optimized away.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Index: corebootv3-global_vars_in_c/include/console.h
===================================================================
--- corebootv3-global_vars_in_c/include/console.h (Revision 782)
+++ corebootv3-global_vars_in_c/include/console.h (Arbeitskopie)
@@ -60,10 +60,10 @@
#endif
/*
- * If you change struct global_vars in any way, you have to fix all stage0 asm
- * code. The stage0 asm code modification is nontrivial (size of the struct,
- * alignment, initialization, order of struct members, initialization).
- * Depending on your compiler, real breakage may happen.
+ * struct global_vars is managed entirely from C code. Keep in mind that there
+ * is NO buffer at the end of the struct, so having zero-sized arrays at the
+ * end or similar stuff for which the compiler can't determine the final size
+ * will corrupt memory. If you don't try to be clever, everything will be fine.
*/
struct global_vars {
#ifdef CONFIG_CONSOLE_BUFFER
Index: corebootv3-global_vars_in_c/arch/x86/geodelx/stage0.S
===================================================================
--- corebootv3-global_vars_in_c/arch/x86/geodelx/stage0.S (Revision 782)
+++ corebootv3-global_vars_in_c/arch/x86/geodelx/stage0.S (Arbeitskopie)
@@ -361,13 +361,10 @@
movw %ax, %ss
lout:
-#ifdef CONFIG_CONSOLE_BUFFER
- /* Store pointer to start of printk buffer, should really use
- * PRINTK_BUF_ADDR_CAR instead.
- */
- movl $CONFIG_CARBASE, %eax
- pushl %eax /* printk buffer */
-#endif
+ /* Store zero for the pointer to the global variables. */
+ movl $0, %eax
+ pushl %eax
+
/* Restore the BIST result. */
movl %ebp, %eax
Index: corebootv3-global_vars_in_c/arch/x86/stage0_i586.S
===================================================================
--- corebootv3-global_vars_in_c/arch/x86/stage0_i586.S (Revision 782)
+++ corebootv3-global_vars_in_c/arch/x86/stage0_i586.S (Arbeitskopie)
@@ -435,13 +435,10 @@
movw %ax, %ss
lout:
-#ifdef CONFIG_CONSOLE_BUFFER
- /* Store pointer to start of printk buffer, should really use
- * PRINTK_BUF_ADDR_CAR instead.
- */
- movl $CONFIG_CARBASE, %eax
- pushl %eax /* printk buffer */
-#endif
+ /* Store zero for the pointer to the global variables. */
+ movl $0, %eax
+ pushl %eax
+
/* Restore the BIST result */
movl %ebp, %eax
/* We need to set ebp ? No need */
Index: corebootv3-global_vars_in_c/arch/x86/amd/stage0.S
===================================================================
--- corebootv3-global_vars_in_c/arch/x86/amd/stage0.S (Revision 782)
+++ corebootv3-global_vars_in_c/arch/x86/amd/stage0.S (Arbeitskopie)
@@ -23,7 +23,9 @@
#define CacheBase CONFIG_CARBASE
#define MEM_TOPK 2048
-/* leave some space for global variable to pass to RAM stage */
+/* Leave some space for a pointer to the global variables.
+ * This should most likely be 4.
+ */
#define GlobalVarSize 32
#ifdef CONFIG_CPU_AMD_K10
Index: corebootv3-global_vars_in_c/arch/x86/stage1.c
===================================================================
--- corebootv3-global_vars_in_c/arch/x86/stage1.c (Revision 783)
+++ corebootv3-global_vars_in_c/arch/x86/stage1.c (Arbeitskopie)
@@ -82,9 +82,15 @@
struct global_vars *global_vars(void)
{
- return (struct global_vars *)(bottom_of_stack() - sizeof(struct global_vars));
+ return *(struct global_vars **)(bottom_of_stack() - sizeof(struct global_vars *));
}
+void global_vars_init(struct global_vars *globvars)
+{
+ memset(globvars, 0, sizeof(struct global_vars));
+ *(struct global_vars **)(bottom_of_stack() - sizeof(struct global_vars *)) = globvars;
+}
+
void dump_mem_range(int msg_level, unsigned char *buf, int size)
{
int i;
@@ -119,9 +125,14 @@
/*
* This function is called from assembler code with its argument on the
* stack. Force the compiler to generate always correct code for this case.
+ * We have cache as ram running and can start executing code in C.
*/
void __attribute__((stdcall)) stage1_main(u32 bist)
{
+ /* FIXME: Which attributes does globvars need? GCC should not try to
+ * be clever with it. __attribute__((used,externally_visible))?
+ */
+ struct global_vars globvars;
int ret;
struct mem_file archive;
void *entry;
@@ -150,10 +161,13 @@
stop_ap();
}
- // We have cache as ram running and can start executing code in C.
+ /* Initialize global variables before we can think of using them.
+ * NEVER run this on an AP!
+ */
+ global_vars_init(&globvars);
#ifdef CONFIG_CONSOLE_BUFFER
- /* Initialize the printk buffer. */
+ /* Initialize the printk buffer. NEVER run this on an AP! */
printk_buffer_init();
#endif
--
http://www.hailfinger.org/
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: linuxbios3_global_vars_in_c.diff
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20080818/e65376db/attachment.ksh>
More information about the coreboot
mailing list