Author: hailfinger Date: 2008-08-18 18:54:12 +0200 (Mon, 18 Aug 2008) New Revision: 785
Modified: coreboot-v3/arch/x86/amd/stage0.S coreboot-v3/arch/x86/geodelx/stage0.S coreboot-v3/arch/x86/stage0_i586.S coreboot-v3/arch/x86/stage1.c coreboot-v3/include/console.h Log: 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().
Creating global variables is now a piece of cake. You don't even have to touch any asm code, just add them to struct global_vars.
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.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Acked-by: Segher Boessenkool segher@kernel.crashing.org
Modified: coreboot-v3/arch/x86/amd/stage0.S =================================================================== --- coreboot-v3/arch/x86/amd/stage0.S 2008-08-18 16:48:27 UTC (rev 784) +++ coreboot-v3/arch/x86/amd/stage0.S 2008-08-18 16:54:12 UTC (rev 785) @@ -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
Modified: coreboot-v3/arch/x86/geodelx/stage0.S =================================================================== --- coreboot-v3/arch/x86/geodelx/stage0.S 2008-08-18 16:48:27 UTC (rev 784) +++ coreboot-v3/arch/x86/geodelx/stage0.S 2008-08-18 16:54:12 UTC (rev 785) @@ -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
Modified: coreboot-v3/arch/x86/stage0_i586.S =================================================================== --- coreboot-v3/arch/x86/stage0_i586.S 2008-08-18 16:48:27 UTC (rev 784) +++ coreboot-v3/arch/x86/stage0_i586.S 2008-08-18 16:54:12 UTC (rev 785) @@ -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 */
Modified: coreboot-v3/arch/x86/stage1.c =================================================================== --- coreboot-v3/arch/x86/stage1.c 2008-08-18 16:48:27 UTC (rev 784) +++ coreboot-v3/arch/x86/stage1.c 2008-08-18 16:54:12 UTC (rev 785) @@ -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,11 @@ /* * 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) { + struct global_vars globvars; int ret; struct mem_file archive; void *entry; @@ -150,10 +158,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
Modified: coreboot-v3/include/console.h =================================================================== --- coreboot-v3/include/console.h 2008-08-18 16:48:27 UTC (rev 784) +++ coreboot-v3/include/console.h 2008-08-18 16:54:12 UTC (rev 785) @@ -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