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_phase1() and stage1_phase2() and stage1_phase3(). stage1_phase1() is the new entry point in stage1 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 stage1_phase2() function. stage1_phase2() calls disable_car() which then calls stage1_phase3(). stage1_phase3() is the former second half of stage1_main(). 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@gmx.net> Acked-by: Ronald G. Minnich <rminnich@gmail.com> git-svn-id: svn://coreboot.org/repository/coreboot-v3@932 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
parent
8b2f6c4c4a
commit
33de3b2fb5
10 changed files with 81 additions and 24 deletions
|
|
@ -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 @@ void disable_car(void)
|
|||
/* 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ CAR_FAM10_ap_out:
|
|||
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 */
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ lout:
|
|||
pushl $0
|
||||
/* First parameter: bist */
|
||||
pushl %eax
|
||||
call stage1_main
|
||||
call stage1_phase1
|
||||
/* We will not go back. */
|
||||
|
||||
#include "../stage0_common.S"
|
||||
|
|
|
|||
|
|
@ -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 @@ void disable_car(void)
|
|||
banner(BIOS_DEBUG, "Disable_car: done wbinvd");
|
||||
northbridge_init_early();
|
||||
banner(BIOS_DEBUG, "disable_car: done");
|
||||
stage1_phase3();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ lout:
|
|||
pushl $0
|
||||
/* First parameter: bist */
|
||||
pushl %eax
|
||||
call stage1_main
|
||||
call stage1_phase1
|
||||
/* We will not go back. */
|
||||
|
||||
fixed_mtrr_msr:
|
||||
|
|
|
|||
|
|
@ -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,28 +155,12 @@ static int run_address_multiboot(void *f)
|
|||
* 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);
|
||||
|
||||
|
|
@ -234,13 +219,76 @@ void __attribute__((stdcall)) stage1_main(u32 bist, u32 init_detected)
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ lout:
|
|||
pushl $0
|
||||
/* First parameter: bist */
|
||||
pushl %eax
|
||||
call stage1_main
|
||||
call stage1_phase1
|
||||
/* We will not go back. */
|
||||
|
||||
fixed_mtrr_msr:
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ Stage 1: C, in arch/{architecture}
|
|||
\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
|
||||
|
|
|
|||
2
include/arch/x86/stage1.h
Normal file
2
include/arch/x86/stage1.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
void stage1_phase2(void);
|
||||
void __attribute__((stdcall)) stage1_phase3(void);
|
||||
|
|
@ -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 stop_ap(void)
|
|||
|
||||
void disable_car(void)
|
||||
{
|
||||
stage1_phase3();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue