haswell: use dynamic cbmem
Convert the existing haswell code to support reloctable ramstage to use dynamic cbmem. This patch always selects DYNAMIC_CBMEM as this option is a hard requirement for relocatable ramstage. Aside from converting a few new API calls, a cbmem_top() implementation is added which is defined to be at the begining of the TSEG region. Also, use the dynamic cbmem library for allocating a stack in ram for romstage after CAR is torn down. Utilizing dynamic cbmem does mean that the cmem field in the gnvs chromeos acpi table is now 0. Also, the memconsole driver in the kernel won't be able to find the memconsole because the cbmem structure changed. Change-Id: I7cf98d15b97ad82abacfb36ec37b004ce4605c38 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/2850 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
dd4a6d2357
commit
c0cbd6e8c2
|
@ -12,6 +12,7 @@ config CPU_SPECIFIC_OPTIONS
|
||||||
select SMM_TSEG
|
select SMM_TSEG
|
||||||
select SMM_MODULES
|
select SMM_MODULES
|
||||||
select RELOCATABLE_MODULES
|
select RELOCATABLE_MODULES
|
||||||
|
select DYNAMIC_CBMEM
|
||||||
select CPU_MICROCODE_IN_CBFS
|
select CPU_MICROCODE_IN_CBFS
|
||||||
#select AP_IN_SIPI_WAIT
|
#select AP_IN_SIPI_WAIT
|
||||||
select TSC_SYNC_MFENCE
|
select TSC_SYNC_MFENCE
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <arch/stages.h>
|
#include <arch/stages.h>
|
||||||
#include <device/pci_def.h>
|
#include <device/pci_def.h>
|
||||||
#include <cpu/x86/lapic.h>
|
#include <cpu/x86/lapic.h>
|
||||||
#include <cbmem.h>
|
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
#include <romstage_handoff.h>
|
#include <romstage_handoff.h>
|
||||||
#include <reset.h>
|
#include <reset.h>
|
||||||
|
@ -70,13 +69,17 @@ static inline u32 *stack_push(u32 *stack, u32 value)
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Romstage needs quite a bit of stack for decompressing images since the lzma
|
||||||
|
* lib keeps its state on the stack during romstage. */
|
||||||
|
#define ROMSTAGE_RAM_STACK_SIZE 0x5000
|
||||||
static unsigned long choose_top_of_stack(void)
|
static unsigned long choose_top_of_stack(void)
|
||||||
{
|
{
|
||||||
unsigned long stack_top;
|
unsigned long stack_top;
|
||||||
#if CONFIG_RELOCATABLE_RAMSTAGE
|
#if CONFIG_DYNAMIC_CBMEM
|
||||||
stack_top = (unsigned long)cbmem_add(CBMEM_ID_RESUME_SCRATCH,
|
/* cbmem_add() does a find() before add(). */
|
||||||
CONFIG_HIGH_SCRATCH_MEMORY_SIZE);
|
stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK,
|
||||||
stack_top += CONFIG_HIGH_SCRATCH_MEMORY_SIZE;
|
ROMSTAGE_RAM_STACK_SIZE);
|
||||||
|
stack_top += ROMSTAGE_RAM_STACK_SIZE;
|
||||||
#else
|
#else
|
||||||
stack_top = ROMSTAGE_STACK;
|
stack_top = ROMSTAGE_STACK;
|
||||||
#endif
|
#endif
|
||||||
|
@ -197,7 +200,6 @@ void romstage_common(const struct romstage_params *params)
|
||||||
{
|
{
|
||||||
int boot_mode;
|
int boot_mode;
|
||||||
int wake_from_s3;
|
int wake_from_s3;
|
||||||
int cbmem_was_initted;
|
|
||||||
struct romstage_handoff *handoff;
|
struct romstage_handoff *handoff;
|
||||||
|
|
||||||
#if CONFIG_COLLECT_TIMESTAMPS
|
#if CONFIG_COLLECT_TIMESTAMPS
|
||||||
|
@ -265,23 +267,16 @@ void romstage_common(const struct romstage_params *params)
|
||||||
quick_ram_check();
|
quick_ram_check();
|
||||||
post_code(0x3e);
|
post_code(0x3e);
|
||||||
|
|
||||||
#if CONFIG_EARLY_CBMEM_INIT
|
if (!wake_from_s3) {
|
||||||
cbmem_was_initted = !cbmem_initialize();
|
cbmem_initialize_empty();
|
||||||
#else
|
/* Save data returned from MRC on non-S3 resumes. */
|
||||||
cbmem_was_initted = cbmem_reinit((uint64_t) (get_top_of_ram()
|
|
||||||
- HIGH_MEMORY_SIZE));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Save data returned from MRC on non-S3 resumes. */
|
|
||||||
if (!wake_from_s3)
|
|
||||||
save_mrc_data(params->pei_data);
|
save_mrc_data(params->pei_data);
|
||||||
|
} else if (cbmem_initialize()) {
|
||||||
#if CONFIG_HAVE_ACPI_RESUME
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
if (wake_from_s3 && !cbmem_was_initted) {
|
|
||||||
/* Failed S3 resume, reset to come up cleanly */
|
/* Failed S3 resume, reset to come up cleanly */
|
||||||
reset_system();
|
reset_system();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
handoff = romstage_handoff_find_or_add();
|
handoff = romstage_handoff_find_or_add();
|
||||||
if (handoff != NULL)
|
if (handoff != NULL)
|
||||||
|
@ -330,11 +325,16 @@ void romstage_after_car(void)
|
||||||
|
|
||||||
#if CONFIG_RELOCATABLE_RAMSTAGE
|
#if CONFIG_RELOCATABLE_RAMSTAGE
|
||||||
void cache_loaded_ramstage(struct romstage_handoff *handoff,
|
void cache_loaded_ramstage(struct romstage_handoff *handoff,
|
||||||
void *ramstage_base, uint32_t ramstage_size,
|
const struct cbmem_entry *ramstage,
|
||||||
void *entry_point)
|
void *entry_point)
|
||||||
{
|
{
|
||||||
struct ramstage_cache *cache;
|
struct ramstage_cache *cache;
|
||||||
uint32_t total_size;
|
uint32_t total_size;
|
||||||
|
uint32_t ramstage_size;
|
||||||
|
void *ramstage_base;
|
||||||
|
|
||||||
|
ramstage_size = cbmem_entry_size(ramstage);
|
||||||
|
ramstage_base = cbmem_entry_start(ramstage);
|
||||||
|
|
||||||
/* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
|
/* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
|
||||||
* The top of ram is defined to be the TSEG base address. */
|
* The top of ram is defined to be the TSEG base address. */
|
||||||
|
@ -358,19 +358,14 @@ void cache_loaded_ramstage(struct romstage_handoff *handoff,
|
||||||
/* Copy over the program. */
|
/* Copy over the program. */
|
||||||
memcpy(&cache->program[0], ramstage_base, ramstage_size);
|
memcpy(&cache->program[0], ramstage_base, ramstage_size);
|
||||||
|
|
||||||
/* Do not update reserve region if the handoff structure is not
|
|
||||||
* available. Perhaps the ramstage will fix things up for the resume
|
|
||||||
* path. */
|
|
||||||
if (handoff == NULL)
|
if (handoff == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Update entry and reserve region. */
|
|
||||||
handoff->reserve_base = (uint32_t)ramstage_base;
|
|
||||||
handoff->reserve_size = ramstage_size;
|
|
||||||
handoff->ramstage_entry_point = (uint32_t)entry_point;
|
handoff->ramstage_entry_point = (uint32_t)entry_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *load_cached_ramstage(struct romstage_handoff *handoff)
|
void *load_cached_ramstage(struct romstage_handoff *handoff,
|
||||||
|
const struct cbmem_entry *ramstage)
|
||||||
{
|
{
|
||||||
struct ramstage_cache *cache;
|
struct ramstage_cache *cache;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ static void acpi_create_gnvs(global_nvs_t *gnvs)
|
||||||
gnvs->s5u1 = 1;
|
gnvs->s5u1 = 1;
|
||||||
|
|
||||||
/* CBMEM TOC */
|
/* CBMEM TOC */
|
||||||
gnvs->cmem = (u32)get_cbmem_toc();
|
gnvs->cmem = 0;
|
||||||
|
|
||||||
/* IGD Displays */
|
/* IGD Displays */
|
||||||
gnvs->ndid = 3;
|
gnvs->ndid = 3;
|
||||||
|
|
|
@ -84,7 +84,7 @@ static void acpi_create_gnvs(global_nvs_t *gnvs)
|
||||||
gnvs->s5u1 = 0;
|
gnvs->s5u1 = 0;
|
||||||
|
|
||||||
/* CBMEM TOC */
|
/* CBMEM TOC */
|
||||||
gnvs->cmem = (u32)get_cbmem_toc();
|
gnvs->cmem = 0;
|
||||||
|
|
||||||
/* IGD Displays */
|
/* IGD Displays */
|
||||||
gnvs->ndid = 3;
|
gnvs->ndid = 3;
|
||||||
|
|
|
@ -84,7 +84,7 @@ static void acpi_create_gnvs(global_nvs_t *gnvs)
|
||||||
gnvs->s5u1 = 0;
|
gnvs->s5u1 = 0;
|
||||||
|
|
||||||
/* CBMEM TOC */
|
/* CBMEM TOC */
|
||||||
gnvs->cmem = (u32)get_cbmem_toc();
|
gnvs->cmem = 0;
|
||||||
|
|
||||||
/* IGD Displays */
|
/* IGD Displays */
|
||||||
gnvs->ndid = 3;
|
gnvs->ndid = 3;
|
||||||
|
|
|
@ -543,6 +543,16 @@ static void northbridge_init(struct device *dev)
|
||||||
MCHBAR32(0x5500) = 0x00100001;
|
MCHBAR32(0x5500) = 0x00100001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *cbmem_top(void)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
/* The top the reserve regions fall just below the TSEG region. */
|
||||||
|
reg = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0, 0)), TSEG);
|
||||||
|
|
||||||
|
return (void *)(reg & ~((1 << 20) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
static void northbridge_enable(device_t dev)
|
static void northbridge_enable(device_t dev)
|
||||||
{
|
{
|
||||||
#if CONFIG_HAVE_ACPI_RESUME
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
|
|
|
@ -202,9 +202,10 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
report_memory_config();
|
report_memory_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
void *cbmem_top(void)
|
||||||
{
|
{
|
||||||
return (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
|
/* Top of cbmem is at lowest usable DRAM address below 4GiB. */
|
||||||
|
return (void *)get_top_of_ram();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long get_top_of_ram(void)
|
unsigned long get_top_of_ram(void)
|
||||||
|
|
Loading…
Reference in New Issue