Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/36144 )
Change subject: [RFC,POF] pass cbmem_top via the stack to ramstage ......................................................................
[RFC,POF] pass cbmem_top via the stack to ramstage
Currently all stages that need cbmem need an implementation of a cbmem_top function. On FSP and AGESA platforms this proves to be painful and using the top of lower memory if often passed via lower memory or via a PCI scratchpad register.
The problem with writing to lower memory is that also need to be written on S3 as one cannot assume it to be still there. Writing things on S3 is always a fragile thing to do.
A very generic solution is to pass cbmem_top via the program argument. It should be possible to implement this solution on every architecture.
TODO this can be done on all arch
TESTED on qemu-x86.
Change-Id: I6d5a366d6f1bc76f26d459628237e6b2c8ae03ea Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/arch/x86/c_start.S M src/arch/x86/cbmem.c M src/lib/prog_loaders.c M src/mainboard/emulation/qemu-i440fx/memmap.c M src/northbridge/intel/i945/memmap.c 5 files changed, 28 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/44/36144/1
diff --git a/src/arch/x86/c_start.S b/src/arch/x86/c_start.S index 32b848d..6177773 100644 --- a/src/arch/x86/c_start.S +++ b/src/arch/x86/c_start.S @@ -18,6 +18,7 @@ .section .bss, "aw", @nobits .global _stack .global _estack +.global _cbmem_top_ptr
/* Stack alignment is not enforced with rmodule loader, reserve one * extra CPU such that alignment can be enforced on entry. */ @@ -30,6 +31,8 @@ thread_stacks: .space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS #endif +_cbmem_top_ptr: + .long 0
.section ".text._start", "ax", @progbits #ifdef __x86_64__ @@ -59,6 +62,9 @@
cld
+ pop %eax + movl %eax, _cbmem_top_ptr + /** poison the stack. Code should not count on the * stack being full of zeros. This stack poisoning * recently uncovered a bug in the broadcast SIPI diff --git a/src/arch/x86/cbmem.c b/src/arch/x86/cbmem.c index 16c35b5..6b1581c 100644 --- a/src/arch/x86/cbmem.c +++ b/src/arch/x86/cbmem.c @@ -13,6 +13,7 @@
#include <stdlib.h> #include <cbmem.h> +#include <console/console.h>
#if CONFIG(CBMEM_TOP_BACKUP)
@@ -34,3 +35,13 @@ }
#endif /* CBMEM_TOP_BACKUP */ + +extern const uintptr_t _cbmem_top_ptr; + +#if ENV_RAMSTAGE +void *cbmem_top(void) +{ + printk(BIOS_DEBUG, "_cbmem_top_ptr: 0x%08x\n", (u32)_cbmem_top_ptr); + return (void *)_cbmem_top_ptr; +} +#endif diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c index 2ef6bdf..a806f41 100644 --- a/src/lib/prog_loaders.c +++ b/src/lib/prog_loaders.c @@ -142,6 +142,10 @@
timestamp_add_now(TS_END_COPYRAM);
+ ramstage.arg = cbmem_top(); + + printk(BIOS_DEBUG, "ramstage arg: 0x%08x\n", (u32)ramstage.arg); + prog_run(&ramstage);
fail: diff --git a/src/mainboard/emulation/qemu-i440fx/memmap.c b/src/mainboard/emulation/qemu-i440fx/memmap.c index 8209379..5ec6a9f 100644 --- a/src/mainboard/emulation/qemu-i440fx/memmap.c +++ b/src/mainboard/emulation/qemu-i440fx/memmap.c @@ -16,6 +16,7 @@ #include <cbmem.h> #include <arch/io.h> #include <arch/romstage.h> +#include <console/console.h> #include "memory.h" #include "fw_cfg.h"
@@ -52,6 +53,7 @@ return tomk; }
+#if !ENV_RAMSTAGE void *cbmem_top(void) { uintptr_t top = 0; @@ -60,8 +62,10 @@ if (!top) top = (uintptr_t)qemu_get_memory_size() * 1024;
+ printk(BIOS_DEBUG, "cbmem_top(): 0x%08x\n", (u32)top); return (void *)top; } +#endif
/* Nothing to do, MTRRs are no-op on QEMU. */ void fill_postcar_frame(struct postcar_frame *pcf) diff --git a/src/northbridge/intel/i945/memmap.c b/src/northbridge/intel/i945/memmap.c index 8207d06..c7e5d39 100644 --- a/src/northbridge/intel/i945/memmap.c +++ b/src/northbridge/intel/i945/memmap.c @@ -71,11 +71,14 @@ * 1 MiB alignment. As this may cause very greedy MTRR setup, push * CBMEM top downwards to 4 MiB boundary. */ + +#if !ENV_RAMSTAGE void *cbmem_top(void) { uintptr_t top_of_ram = ALIGN_DOWN(northbridge_get_tseg_base(), 4*MiB); return (void *) top_of_ram; } +#endif
/** Decodes used Graphics Mode Select (GMS) to kilobytes. */ u32 decode_igd_memory_size(const u32 gms)