Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7861
-gerrit
commit 7bc5f0b326e129580aa92250ec323c67ae8de0e8 Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Fri Dec 19 08:20:45 2014 +0200
CBMEM: Support DYNAMIC_CBMEM with LATE_CBMEM_INIT
We can now create CBMEM with dynamic allocation even if CBMEM location is resolved late in ramstage.
Change-Id: I8529ccbcd4a0e567ebe0a46232ac5d16476e81a8 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- src/Kconfig | 3 +-- src/arch/x86/boot/cbmem.c | 14 +++++++++----- src/include/cbmem.h | 19 +++++++++++++------ src/lib/cbmem_console.c | 2 +- src/lib/dynamic_cbmem.c | 38 ++++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index a58e04a..560f9e5 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -162,7 +162,6 @@ config EARLY_CBMEM_INIT config DYNAMIC_CBMEM bool default n - select EARLY_CBMEM_INIT help Instead of reserving a static amount of CBMEM space the CBMEM area grows dynamically. CBMEM can be used both in romstage (after @@ -201,7 +200,7 @@ config RELOCATABLE_MODULES loaded anywhere and all the relocations are handled automatically.
config RELOCATABLE_RAMSTAGE - depends on (RELOCATABLE_MODULES && DYNAMIC_CBMEM) + depends on (RELOCATABLE_MODULES && DYNAMIC_CBMEM && EARLY_CBMEM_INIT) bool "Build the ramstage to be relocatable in 32-bit address space." default n help diff --git a/src/arch/x86/boot/cbmem.c b/src/arch/x86/boot/cbmem.c index a145223..1036adc 100644 --- a/src/arch/x86/boot/cbmem.c +++ b/src/arch/x86/boot/cbmem.c @@ -39,6 +39,9 @@ void get_cbmem_table(uint64_t *base, uint64_t *size) *size = 0; } } +#endif /* !DYNAMIC_CBMEM */ + +#if IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
#if !defined(__PRE_RAM__) void __attribute__((weak)) backup_top_of_ram(uint64_t ramtop) @@ -46,14 +49,14 @@ void __attribute__((weak)) backup_top_of_ram(uint64_t ramtop) /* Do nothing. Chipset may have implementation to save ramtop in NVRAM. */ }
-/* This is for compatibility with old boards only. Any new chipset and board - * must implement get_top_of_ram() for both romstage and ramstage to support - * early features like COLLECT_TIMESTAMPS and CBMEM_CONSOLE. - */ void set_top_of_ram(uint64_t ramtop) { backup_top_of_ram(ramtop); +#if !CONFIG_DYNAMIC_CBMEM cbmem_late_set_table(ramtop - HIGH_MEMORY_SIZE, HIGH_MEMORY_SIZE); +#else + cbmem_set_top((void*)(uintptr_t)ramtop); +#endif } #endif /* !__PRE_RAM__ */
@@ -70,7 +73,8 @@ void *cbmem_top(void) return (void *)get_top_of_ram(); } #endif -#endif /* !DYNAMIC_CBMEM */ + +#endif /* LATE_CBMEM_INIT */
void cbmem_run_init_hooks(void) { diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 05708da..c2e7314 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -151,6 +151,9 @@ void cbmem_initialize_empty(void); * below 4GiB. */ void *cbmem_top(void);
+/* Set the top address for dynamic cbmem. Not for new designs. */ +void cbmem_set_top(void *ramtop); + /* Add a cbmem entry of a given size and id. These return NULL on failure. The * add function performs a find first and do not check against the original * size. */ @@ -168,7 +171,6 @@ int cbmem_entry_remove(const struct cbmem_entry *entry); void *cbmem_entry_start(const struct cbmem_entry *entry); u64 cbmem_entry_size(const struct cbmem_entry *entry);
- #else /* !CONFIG_DYNAMIC_CBMEM */
/* Allocation with static CBMEM is resolved at build time. We start @@ -183,15 +185,10 @@ u64 cbmem_entry_size(const struct cbmem_entry *entry);
#define HIGH_MEMORY_SIZE ALIGN_UP(_CBMEM_SZ_TOTAL, 0x10000)
- #ifndef __PRE_RAM__ -void set_top_of_ram(uint64_t ramtop); -void backup_top_of_ram(uint64_t ramtop); void cbmem_late_set_table(uint64_t base, uint64_t size); #endif
-unsigned long get_top_of_ram(void); - void get_cbmem_table(uint64_t *base, uint64_t *size); struct cbmem_entry *get_cbmem_toc(void);
@@ -224,6 +221,16 @@ void cbmem_list(void); void cbmem_print_entry(int n, u32 id, u64 start, u64 size); #endif /* __PRE_RAM__ */
+/* These are for compatibility with old boards only. Any new chipset and board + * must implement cbmem_top() for both romstage and ramstage to support + * early features like COLLECT_TIMESTAMPS and CBMEM_CONSOLE. + */ +#if IS_ENABLED(CONFIG_ARCH_X86) && IS_ENABLED(CONFIG_LATE_CBMEM_INIT) +unsigned long get_top_of_ram(void); +void set_top_of_ram(uint64_t ramtop); +void backup_top_of_ram(uint64_t ramtop); +#endif + #endif /* __ASSEMBLER__ */
diff --git a/src/lib/cbmem_console.c b/src/lib/cbmem_console.c index 6783b30..0c2722c 100644 --- a/src/lib/cbmem_console.c +++ b/src/lib/cbmem_console.c @@ -58,7 +58,7 @@ extern struct cbmem_console preram_cbmem_console; * during the ROM stage, once CBMEM becomes available at RAM stage. */
-#if CONFIG_DYNAMIC_CBMEM +#if IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) #define STATIC_CONSOLE_SIZE 1024 #else #define STATIC_CONSOLE_SIZE CONFIG_CONSOLE_CBMEM_BUFFER_SIZE diff --git a/src/lib/dynamic_cbmem.c b/src/lib/dynamic_cbmem.c index 1b46745..6ec56c7 100644 --- a/src/lib/dynamic_cbmem.c +++ b/src/lib/dynamic_cbmem.c @@ -24,10 +24,9 @@ #include <string.h> #include <stdlib.h> #include <arch/early_variables.h> -#if CONFIG_HAVE_ACPI_RESUME && !defined(__PRE_RAM__) +#if IS_ENABLED(CONFIG_ARCH_X86) && !IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) #include <arch/acpi.h> #endif - #ifndef UINT_MAX #define UINT_MAX 4294967295U #endif @@ -69,11 +68,18 @@ struct cbmem_root { } __attribute__((packed));
+#if !defined(__PRE_RAM__) +static void *cached_cbmem_top; + +void cbmem_set_top(void * ramtop) +{ + cached_cbmem_top = ramtop; +} +#endif + static inline void *cbmem_top_cached(void) { #if !defined(__PRE_RAM__) - static void *cached_cbmem_top; - if (cached_cbmem_top == NULL) cached_cbmem_top = cbmem_top();
@@ -100,6 +106,9 @@ static inline void *get_root(void) struct cbmem_root_pointer *pointer;
pointer_addr = get_top_aligned(); + if (pointer_addr == 0) + return NULL; + pointer_addr -= sizeof(struct cbmem_root_pointer);
pointer = (void *)pointer_addr; @@ -146,6 +155,9 @@ void cbmem_initialize_empty(void) * DYN_CBMEM_ALIGN_SIZE. The pointer falls just below the * address returned by get_top_aligned(). */ pointer_addr = get_top_aligned(); + if (pointer_addr == 0) + return; + root_addr = pointer_addr - ROOT_MIN_SIZE; root_addr &= ~(DYN_CBMEM_ALIGN_SIZE - 1); pointer_addr -= sizeof(struct cbmem_root_pointer); @@ -413,6 +425,8 @@ void *cbmem_entry_start(const struct cbmem_entry *entry)
#if !defined(__PRE_RAM__) + +#if IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) /* selected cbmem can be initialized early in ramstage. Additionally, that * means cbmem console can be reinitialized early as well. The post_device * function is empty since cbmem was initialized early in ramstage. */ @@ -426,6 +440,22 @@ BOOT_STATE_INIT_ENTRIES(cbmem_bscb) = { init_cbmem_pre_device, NULL), };
+#else + +static void init_cbmem_post_device(void *unused) +{ + if (acpi_is_wakeup()) + cbmem_initialize(); + else + cbmem_initialize_empty(); +} + +BOOT_STATE_INIT_ENTRIES(cbmem_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY, + init_cbmem_post_device, NULL), +}; +#endif + void cbmem_add_bootmem(void) { uintptr_t base;