diff --git a/arch/x86/stage1.c b/arch/x86/stage1.c index ce3d24c135..988b8a1c7c 100644 --- a/arch/x86/stage1.c +++ b/arch/x86/stage1.c @@ -71,11 +71,21 @@ void init_archive(struct mem_file *archive) /* * The name is slightly misleading because this is the initial stack pointer, * not the address of the first element on the stack. + * NOTE: This function is very processor specific. */ void *bottom_of_stack(void) { - /* -4 because CONFIG_CARBASE + CONFIG_CARSIZE - 4 is initial %esp */ - return (void *)(CONFIG_CARBASE + CONFIG_CARSIZE - 4); + u32 onstack = (u32)&onstack; + + /* Check whether the variable onstack is inside the CAR stack area. + * If it is, assume we're still in CAR or the stack has not moved. + * Otherwise return initial %esp for the RAM-based stack location. + */ + if ((onstack >= CAR_STACK_BASE - CAR_STACK_SIZE) && + (onstack < CAR_STACK_BASE)) + return (void *)CAR_STACK_BASE; + /* OK, so current %esp is not inside the CAR stack area. */ + return (void *)RAM_STACK_BASE; } struct global_vars *global_vars(void) diff --git a/include/arch/x86/cpu.h b/include/arch/x86/cpu.h index f43d186ae2..5f91c5eef9 100644 --- a/include/arch/x86/cpu.h +++ b/include/arch/x86/cpu.h @@ -266,11 +266,17 @@ EXPORT_SYMBOL(bottom_of_stack); struct global_vars * global_vars(void); EXPORT_SYMBOL(global_vars); +#define CAR_STACK_BASE (CONFIG_CARBASE + CONFIG_CARSIZE - 4) +#define RAM_STACK_BASE 0x88ffc + #ifdef CONFIG_CONSOLE_BUFFER #define PRINTK_BUF_SIZE_CAR (CONFIG_CARSIZE / 2) #define PRINTK_BUF_ADDR_CAR CONFIG_CARBASE #define PRINTK_BUF_SIZE_RAM 65536 #define PRINTK_BUF_ADDR_RAM 0x90000 +#define CAR_STACK_SIZE ((CONFIG_CARSIZE / 2) - 4) +#else +#define CAR_STACK_SIZE (CONFIG_CARSIZE - 4) #endif /* resource maps. These started out as special for the K8 but now have more general usage */