Aaron Durbin (adurbin@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8944
-gerrit
commit 79786142aed39a9409c1e1a204a17b9d2dc01ddd Author: Aaron Durbin adurbin@chromium.org Date: Thu Mar 5 21:18:33 2015 -0600
coreboot: add cbmem based on imd library
Utilize the newly introduced imd library for an alternative implemenation of the cbmem API. It relies on PLATFORM_HAS_EARLY_WRITABLE_GLOBALS to use the imd library.
Change-Id: Icfa8eae91d18072cc023ac05639360f3b1d5fa93 Signed-off-by: Aaron Durbin adurbin@chromium.org --- src/include/cbmem.h | 13 --- src/lib/Makefile.inc | 9 +- src/lib/cbmem_common.c | 59 +++++++------- src/lib/dynamic_cbmem.c | 54 ++++++------ src/lib/imd_cbmem.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ util/cbmem/cbmem.c | 4 + 6 files changed, 281 insertions(+), 70 deletions(-)
diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 81e5f12..9b3ca7d 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -84,11 +84,6 @@ #include <stddef.h> #include <stdint.h>
-struct cbmem_id_to_name { - u32 id; - const char *name; -}; - #define CBMEM_ID_TO_NAME_TABLE \ { CBMEM_ID_FREESPACE, "FREE SPACE " }, \ { CBMEM_ID_GDT, "GDT " }, \ @@ -136,13 +131,6 @@ struct cbmem_entry; * dynamic cbmem infrastructure allocates new regions below the last allocated * region. Regions are defined by a cbmem_entry struct that is opaque. Regions * may be removed, but the last one added is the only that can be removed. - * - * Dynamic cbmem has two allocators within it. All allocators use a top down - * allocation scheme. However, there are 2 modes for each allocation depending - * on the requested size. There are large allocations and small allocations. - * An allocation is considered to be small when it is less than or equal to - * DYN_CBMEM_ALIGN_SIZE / 2. The smaller allocations are fit into a larger - * allocation region. */
#define DYN_CBMEM_ALIGN_SIZE (4096) @@ -196,7 +184,6 @@ void cbmem_fail_resume(void); /* Add the cbmem memory used to the memory map at boot. */ void cbmem_add_bootmem(void); 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 diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 736fa9b..f49cf8b 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -89,8 +89,13 @@ ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c ramstage-$(CONFIG_TIMER_QUEUE) += timer_queue.c ramstage-$(CONFIG_TERTIARY_BOARD_ID) += tristate_gpios.c
-romstage-y += cbmem_common.c dynamic_cbmem.c -ramstage-y += cbmem_common.c dynamic_cbmem.c +romstage-y += cbmem_common.c +romstage-$(CONFIG_PLATFORM_NO_EARLY_WRITABLE_GLOBALS) += dynamic_cbmem.c +romstage-$(CONFIG_PLATFORM_HAS_EARLY_WRITABLE_GLOBALS) += imd_cbmem.c + +ramstage-y += cbmem_common.c +ramstage-$(CONFIG_PLATFORM_NO_EARLY_WRITABLE_GLOBALS) += dynamic_cbmem.c +ramstage-$(CONFIG_PLATFORM_HAS_EARLY_WRITABLE_GLOBALS) += imd_cbmem.c
romstage-y += imd.c ramstage-y += imd.c diff --git a/src/lib/cbmem_common.c b/src/lib/cbmem_common.c index c3e8383..51f61a9 100644 --- a/src/lib/cbmem_common.c +++ b/src/lib/cbmem_common.c @@ -18,39 +18,15 @@ */ #include <console/console.h> #include <cbmem.h> -#include <stdlib.h> +#include <bootstate.h> +#if IS_ENABLED(CONFIG_ARCH_X86) && !IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) +#include <arch/acpi.h> +#endif
/* FIXME: Remove after CBMEM_INIT_HOOKS. */ #include <console/cbmem_console.h> #include <timestamp.h>
-#ifndef __PRE_RAM__ - -static const struct cbmem_id_to_name cbmem_ids[] = { CBMEM_ID_TO_NAME_TABLE }; - -void cbmem_print_entry(int n, u32 id, u64 base, u64 size) -{ - int i; - const char *name; - - name = NULL; - for (i = 0; i < ARRAY_SIZE(cbmem_ids); i++) { - if (cbmem_ids[i].id == id) { - name = cbmem_ids[i].name; - break; - } - } - - if (name == NULL) - printk(BIOS_DEBUG, "%08x ", id); - else - printk(BIOS_DEBUG, "%s", name); - printk(BIOS_DEBUG, "%2d. ", n); - printk(BIOS_DEBUG, "%08llx ", base); - printk(BIOS_DEBUG, "%08llx\n", size); -} - -#endif /* !__PRE_RAM__ */
/* FIXME: Replace with CBMEM_INIT_HOOKS API. */ #if !IS_ENABLED(CONFIG_ARCH_X86) @@ -67,3 +43,30 @@ void __attribute__((weak)) cbmem_fail_resume(void) { } #endif + +#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. */ +static void init_cbmem_pre_device(void *unused) +{ + cbmem_initialize(); +} + +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, 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_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY, + init_cbmem_post_device, NULL); +#endif +#endif /* !defined(__PRE_RAM__) */ diff --git a/src/lib/dynamic_cbmem.c b/src/lib/dynamic_cbmem.c index 3b008c7..cff8f7d 100644 --- a/src/lib/dynamic_cbmem.c +++ b/src/lib/dynamic_cbmem.c @@ -24,9 +24,6 @@ #include <string.h> #include <stdlib.h> #include <arch/early_variables.h> -#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 @@ -426,30 +423,6 @@ 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. */ -static void init_cbmem_pre_device(void *unused) -{ - cbmem_initialize(); -} - -BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, 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_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY, - init_cbmem_post_device, NULL); -#endif - void cbmem_add_bootmem(void) { uintptr_t base; @@ -460,6 +433,33 @@ void cbmem_add_bootmem(void) bootmem_add_range(base, top - base, LB_MEM_TABLE); }
+static const struct { + u32 id; + const char *name; +} cbmem_ids[] = { CBMEM_ID_TO_NAME_TABLE }; + +static void cbmem_print_entry(int n, u32 id, u64 base, u64 size) +{ + int i; + const char *name; + + name = NULL; + for (i = 0; i < ARRAY_SIZE(cbmem_ids); i++) { + if (cbmem_ids[i].id == id) { + name = cbmem_ids[i].name; + break; + } + } + + if (name == NULL) + printk(BIOS_DEBUG, "%08x ", id); + else + printk(BIOS_DEBUG, "%s", name); + printk(BIOS_DEBUG, "%2d. ", n); + printk(BIOS_DEBUG, "%08llx ", base); + printk(BIOS_DEBUG, "%08llx\n", size); +} + void cbmem_list(void) { unsigned int i; diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c new file mode 100644 index 0000000..bdce86f --- /dev/null +++ b/src/lib/imd_cbmem.c @@ -0,0 +1,212 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <bootstate.h> +#include <bootmem.h> +#include <console/console.h> +#include <cbmem.h> +#include <imd.h> +#include <rules.h> +#include <string.h> +#include <stdlib.h> +#include <arch/early_variables.h> +#if IS_ENABLED(CONFIG_ARCH_X86) && !IS_ENABLED(CONFIG_EARLY_CBMEM_INIT) +#include <arch/acpi.h> +#endif + +/* The root region is at least DYN_CBMEM_ALIGN_SIZE . */ +#define ROOT_MIN_SIZE DYN_CBMEM_ALIGN_SIZE +#define LG_ALIGN ROOT_MIN_SIZE + +static struct imd imd_cbmem CAR_GLOBAL = { }; + +static inline struct imd *cbmem_get_imd(void) +{ + return car_get_var_ptr(&imd_cbmem); +} + +#if ENV_RAMSTAGE +void cbmem_set_top(void *ramtop) +{ + struct imd *imd = cbmem_get_imd(); + + imd_handle_init(imd, ramtop); +} +#endif + +static inline const struct cbmem_entry *imd_to_cbmem(const struct imd_entry *e) +{ + return (const struct cbmem_entry *)e; +} + +static inline const struct imd_entry *cbmem_to_imd(const struct cbmem_entry *e) +{ + return (const struct imd_entry *)e; +} + +void cbmem_initialize_empty(void) +{ + struct imd *imd; + + imd = cbmem_get_imd(); + + imd_handle_init(imd, cbmem_top()); + + printk(BIOS_DEBUG, "CBMEM: "); + + if (imd_create_empty(imd, ROOT_MIN_SIZE, LG_ALIGN)) + return; + + /* Complete migration to CBMEM. */ + cbmem_run_init_hooks(); +} + +static inline int cbmem_fail_recovery(void) +{ + cbmem_initialize_empty(); + cbmem_fail_resume(); + return 1; +} + +int cbmem_initialize(void) +{ + struct imd *imd; + + imd = cbmem_get_imd(); + + imd_handle_init(imd, cbmem_top()); + + if (imd_recover(imd) != 0) + return cbmem_fail_recovery(); + +#if defined(__PRE_RAM__) + /* + * Lock the imd in romstage on a recovery. The assumption is that + * if the imd area was recovered in romstage then S3 resume path + * is being taken. + */ + imd_lockdown(imd); +#endif + + /* Complete migration to CBMEM. */ + cbmem_run_init_hooks(); + + /* Recovery successful. */ + return 0; +} + +int cbmem_recovery(int is_wakeup) +{ + int rv = 0; + if (!is_wakeup) + cbmem_initialize_empty(); + else + rv = cbmem_initialize(); + return rv; +} + +const struct cbmem_entry *cbmem_entry_add(u32 id, u64 size64) +{ + struct imd *imd; + const struct imd_entry *e; + + imd = cbmem_get_imd(); + + e = imd_entry_find_or_add(imd, id, size64); + + return imd_to_cbmem(e); +} + +void *cbmem_add(u32 id, u64 size) +{ + const struct cbmem_entry *entry; + + entry = cbmem_entry_add(id, size); + + if (entry == NULL) + return NULL; + + return cbmem_entry_start(entry); +} + +/* Retrieve a region provided a given id. */ +const struct cbmem_entry *cbmem_entry_find(u32 id) +{ + struct imd *imd; + const struct imd_entry *e; + + imd = cbmem_get_imd(); + + e = imd_entry_find(imd, id); + + return imd_to_cbmem(e); +} + +void *cbmem_find(u32 id) +{ + const struct cbmem_entry *entry; + + entry = cbmem_entry_find(id); + + if (entry == NULL) + return NULL; + + return cbmem_entry_start(entry); +} + +/* Remove a reserved region. Returns 0 on success, < 0 on error. Note: A region + * cannot be removed unless it was the last one added. */ +int cbmem_entry_remove(const struct cbmem_entry *entry) +{ + const struct imd_entry *e = cbmem_to_imd(entry); + + return imd_entry_remove(cbmem_get_imd(), e); +} + +u64 cbmem_entry_size(const struct cbmem_entry *entry) +{ + const struct imd_entry *e = cbmem_to_imd(entry); + + return imd_entry_size(cbmem_get_imd(), e); +} + +void *cbmem_entry_start(const struct cbmem_entry *entry) +{ + const struct imd_entry *e = cbmem_to_imd(entry); + + return imd_entry_at(cbmem_get_imd(), e); +} + +#if ENV_RAMSTAGE +void cbmem_add_bootmem(void) +{ + void *base = NULL; + size_t size = 0; + + imd_region_used(cbmem_get_imd(), &base, &size); + bootmem_add_range((uintptr_t)base, size, LB_MEM_TABLE); +} + +void cbmem_list(void) +{ + static const struct imd_lookup lookup[] = { CBMEM_ID_TO_NAME_TABLE }; + + imd_print_entries(cbmem_get_imd(), lookup, ARRAY_SIZE(lookup)); +} +#endif /* __PRE_RAM__ */ diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 4314d30..afcc98f 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -598,6 +598,10 @@ struct cbmem_entry { uint64_t size; } __attribute__((packed));
+struct cbmem_id_to_name { + uint32_t id; + const char *name; +}; static const struct cbmem_id_to_name cbmem_ids[] = { CBMEM_ID_TO_NAME_TABLE };
void cbmem_print_entry(int n, uint32_t id, uint64_t base, uint64_t size)