CBMEM: Add cbmem_locate_table()

For both romstage and ramstage, this calls an arch-specific function
get_cbmem_table() to resolve the base and size of CBMEM region. In ramstage,
the result is cached as the query may be relatively slow involving multiple PCI
configuration reads.

For x86 CBMEM tables are located right below top of low ram and
have fixed size of HIGH_MEMORY_SIZE in EARLY_CBMEM_INIT implementation.

Change-Id: Ie8d16eb30cd5c3860fff243f36bd4e7d8827a782
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/3558
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
This commit is contained in:
Kyösti Mälkki 2013-09-04 13:31:39 +03:00
parent dcb688e5ec
commit c04afd6433
5 changed files with 61 additions and 24 deletions

View File

@ -29,6 +29,13 @@
#define MAX_COREBOOT_TABLE_SIZE (8 * 1024) #define MAX_COREBOOT_TABLE_SIZE (8 * 1024)
void __attribute__((weak)) get_cbmem_table(uint64_t *base, uint64_t *size)
{
printk(BIOS_WARNING, "WARNING: you need to define get_cbmem_table for your board\n");
*base = 0;
*size = 0;
}
void cbmem_arch_init(void) void cbmem_arch_init(void)
{ {
} }

View File

@ -1,3 +1,5 @@
romstage-y += cbmem.c
ramstage-y += boot.c ramstage-y += boot.c
ramstage-$(CONFIG_MULTIBOOT) += multiboot.c ramstage-$(CONFIG_MULTIBOOT) += multiboot.c
ramstage-y += gdt.c ramstage-y += gdt.c

View File

@ -18,7 +18,28 @@
#include <console/console.h> #include <console/console.h>
#include <cbmem.h> #include <cbmem.h>
unsigned long __attribute__((weak)) get_top_of_ram(void)
{
printk(BIOS_WARNING, "WARNING: you need to define get_top_of_ram() for your chipset\n");
return 0;
}
#if !CONFIG_DYNAMIC_CBMEM #if !CONFIG_DYNAMIC_CBMEM
void get_cbmem_table(uint64_t *base, uint64_t *size)
{
uint64_t top_of_ram = get_top_of_ram();
if (top_of_ram >= HIGH_MEMORY_SIZE) {
*base = top_of_ram - HIGH_MEMORY_SIZE;
*size = HIGH_MEMORY_SIZE;
} else {
*base = 0;
*size = 0;
}
}
#endif
#if !CONFIG_DYNAMIC_CBMEM && !defined(__PRE_RAM__)
/* This is for compatibility with old boards only. Any new chipset and board /* 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 * must implement get_top_of_ram() for both romstage and ramstage to support
* features like CAR_MIGRATION and CBMEM_CONSOLE. * features like CAR_MIGRATION and CBMEM_CONSOLE.

View File

@ -140,6 +140,7 @@ int cbmem_base_check(void);
void cbmem_init(u64 baseaddr, u64 size); void cbmem_init(u64 baseaddr, u64 size);
int cbmem_reinit(u64 baseaddr); int cbmem_reinit(u64 baseaddr);
void get_cbmem_table(uint64_t *base, uint64_t *size);
extern struct cbmem_entry *get_cbmem_toc(void); extern struct cbmem_entry *get_cbmem_toc(void);
#endif /* CONFIG_DYNAMIC_CBMEM */ #endif /* CONFIG_DYNAMIC_CBMEM */

View File

@ -45,30 +45,46 @@ struct cbmem_entry {
#ifndef __PRE_RAM__ #ifndef __PRE_RAM__
uint64_t high_tables_base = 0; uint64_t high_tables_base = 0;
uint64_t high_tables_size = 0; uint64_t high_tables_size = 0;
static struct cbmem_entry *bss_cbmem_toc;
struct cbmem_entry *__attribute__((weak)) get_cbmem_toc(void)
{
return bss_cbmem_toc;
}
void __attribute__((weak)) set_cbmem_toc(struct cbmem_entry * x) void __attribute__((weak)) set_cbmem_toc(struct cbmem_entry * x)
{ {
/* do nothing, this should be called by chipset to save TOC in NVRAM */ /* do nothing, this should be called by chipset to save TOC in NVRAM */
} }
static void cbmem_trace_location(uint64_t base, uint64_t size, const char *s)
{
if (base && size && s) {
printk(BIOS_DEBUG, "CBMEM region %llx-%llx (%s)\n",
base, base + size - 1, s);
}
}
#endif
static void cbmem_locate_table(uint64_t *base, uint64_t *size)
{
#ifdef __PRE_RAM__
get_cbmem_table(base, size);
#else #else
if (!(high_tables_base && high_tables_size)) {
get_cbmem_table(&high_tables_base, &high_tables_size);
cbmem_trace_location(high_tables_base, high_tables_size, __FUNCTION__);
}
*base = high_tables_base;
*size = high_tables_size;
#endif
}
struct cbmem_entry *__attribute__((weak)) get_cbmem_toc(void) struct cbmem_entry *__attribute__((weak)) get_cbmem_toc(void)
{ {
printk(BIOS_WARNING, "WARNING: you need to define get_cbmem_toc() for your chipset\n"); uint64_t base, size;
return NULL; cbmem_locate_table(&base, &size);
return (struct cbmem_entry *)(unsigned long)base;
} }
#endif
#if !defined(__PRE_RAM__) #if !defined(__PRE_RAM__)
void cbmem_late_set_table(uint64_t base, uint64_t size) void cbmem_late_set_table(uint64_t base, uint64_t size)
{ {
printk(BIOS_DEBUG, "CBMEM region %llx-%llx (%s)\n", base, base+size-1, __FUNCTION__); cbmem_trace_location(base, size, __FUNCTION__);
high_tables_base = base; high_tables_base = base;
high_tables_size = size; high_tables_size = size;
} }
@ -89,10 +105,6 @@ void cbmem_init(u64 baseaddr, u64 size)
struct cbmem_entry *cbmem_toc; struct cbmem_entry *cbmem_toc;
cbmem_toc = (struct cbmem_entry *)(unsigned long)baseaddr; cbmem_toc = (struct cbmem_entry *)(unsigned long)baseaddr;
#ifndef __PRE_RAM__
bss_cbmem_toc = cbmem_toc;
#endif
printk(BIOS_DEBUG, "Initializing CBMEM area to 0x%llx (%lld bytes)\n", printk(BIOS_DEBUG, "Initializing CBMEM area to 0x%llx (%lld bytes)\n",
baseaddr, size); baseaddr, size);
@ -123,10 +135,6 @@ int cbmem_reinit(u64 baseaddr)
printk(BIOS_DEBUG, "Re-Initializing CBMEM area to 0x%lx\n", printk(BIOS_DEBUG, "Re-Initializing CBMEM area to 0x%lx\n",
(unsigned long)baseaddr); (unsigned long)baseaddr);
#ifndef __PRE_RAM__
bss_cbmem_toc = cbmem_toc;
#endif
return (cbmem_toc[0].magic == CBMEM_MAGIC); return (cbmem_toc[0].magic == CBMEM_MAGIC);
} }
@ -219,21 +227,19 @@ void *cbmem_find(u32 id)
/* Returns True if it was not initialized before. */ /* Returns True if it was not initialized before. */
int cbmem_initialize(void) int cbmem_initialize(void)
{ {
uint64_t base = 0, size = 0;
int rv = 0; int rv = 0;
#ifdef __PRE_RAM__ cbmem_locate_table(&base, &size);
uint64_t high_tables_base = get_top_of_ram() - HIGH_MEMORY_SIZE;
uint64_t high_tables_size = HIGH_MEMORY_SIZE;
#endif
/* We expect the romstage to always initialize it. */ /* We expect the romstage to always initialize it. */
if (!cbmem_reinit(high_tables_base)) { if (!cbmem_reinit(base)) {
#if CONFIG_HAVE_ACPI_RESUME && !defined(__PRE_RAM__) #if CONFIG_HAVE_ACPI_RESUME && !defined(__PRE_RAM__)
/* Something went wrong, our high memory area got wiped */ /* Something went wrong, our high memory area got wiped */
if (acpi_slp_type == 3 || acpi_slp_type == 2) if (acpi_slp_type == 3 || acpi_slp_type == 2)
acpi_slp_type = 0; acpi_slp_type = 0;
#endif #endif
cbmem_init(high_tables_base, high_tables_size); cbmem_init(base, size);
rv = 1; rv = 1;
} }
#ifndef __PRE_RAM__ #ifndef __PRE_RAM__