AGESA: Implement POSTCAR_STAGE

Move all boards that have moved away from AGESA_LEGACY_WRAPPER
or BINARYPI_LEGACY_WRAPPER to use POSTCAR_STAGE.

We use POSTCAR_STAGE as a conditional in CAR teardown to tell
our MTRR setup is prepared such that invalidation without
writeback is a valid operation.

Change-Id: I3f4e2170054bdb84c72d2f7c956f8d51a6d7f0ca
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/21384
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Kyösti Mälkki
2017-09-02 16:41:43 +03:00
parent 8bf978c2aa
commit 63fac81fc8
22 changed files with 213 additions and 12 deletions

View File

@@ -29,6 +29,7 @@ config CPU_AMD_AGESA
select UDELAY_LAPIC
select LAPIC_MONOTONIC_TIMER
select SPI_FLASH if HAVE_ACPI_RESUME
select POSTCAR_STAGE if !AGESA_LEGACY_WRAPPER
if CPU_AMD_AGESA

View File

@@ -24,11 +24,13 @@ ifeq ($(CONFIG_AGESA_LEGACY), y)
cpu_incs-y += $(src)/cpu/amd/agesa/cache_as_ram_legacy.inc
else
cpu_incs-y += $(src)/cpu/amd/agesa/cache_as_ram.S
romstage-y += romstage.c
romstage-y += romstage.c mtrr_fixme.c
endif
romstage-$(CONFIG_AGESA_LEGACY_WRAPPER) += heapmanager.c
postcar-y += cache_as_ram.S
ramstage-y += heapmanager.c
ramstage-$(CONFIG_AGESA_LEGACY_WRAPPER) += amd_late_init.c

View File

@@ -29,6 +29,7 @@
.code32
.globl _cache_as_ram_setup, _cache_as_ram_setup_end
.globl chipset_teardown_car
_cache_as_ram_setup:
@@ -105,20 +106,44 @@ _cache_as_ram_setup:
movd %mm0, %eax /* bist */
pushl %eax
call romstage_main
#if IS_ENABLED(CONFIG_POSTCAR_STAGE)
/* We do not return. Execution continues with run_postcar_phase()
* calling to chipset_teardown_car below.
*/
jmp postcar_entry_failure
chipset_teardown_car:
/*
* Retrieve return address from stack as it will get trashed below if
* execution is utilizing the cache-as-ram stack.
*/
pop %esp
#else
movl %eax, %esp
/* Register %esp is new stacktop for remaining of romstage.
* It is the only register preserved in AMD_DISABLE_STACK.
*/
/* Register %esp is new stacktop for remaining of romstage. */
#endif
disable_cache_as_ram:
/* Disable cache */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
/* Register %esp is preserved in AMD_DISABLE_STACK. */
AMD_DISABLE_STACK
#if IS_ENABLED(CONFIG_POSTCAR_STAGE)
jmp *%esp
#else
/* enable cache */
movl %cr0, %eax
andl $0x9fffffff, %eax
@@ -126,9 +151,22 @@ disable_cache_as_ram:
call romstage_after_car
#endif
/* Should never see this postcode */
post_code(0xaf)
stop:
hlt
jmp stop
/* These are here for linking purposes. */
.weak early_all_cores, romstage_main
early_all_cores:
romstage_main:
postcar_entry_failure:
/* Should never see this postcode */
post_code(0xae)
jmp stop
_cache_as_ram_setup_end:

View File

@@ -0,0 +1,100 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#include <arch/cpu.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/amd/mtrr.h>
#include <cpu/cpu.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <northbridge/amd/agesa/agesa_helper.h>
static void set_range_uc(u32 base, u32 size)
{
int i, max_var_mtrrs;
msr_t msr;
msr = rdmsr(MTRR_CAP_MSR);
max_var_mtrrs = msr.lo & MTRR_CAP_VCNT;
for (i = 0; i < max_var_mtrrs; i++) {
msr = rdmsr(MTRR_PHYS_MASK(i));
if (!(msr.lo & MTRR_PHYS_MASK_VALID))
break;
}
if (i == max_var_mtrrs)
die("Run out of unused MTRRs\n");
msr.hi = 0;
msr.lo = base | MTRR_TYPE_UNCACHEABLE;
wrmsr(MTRR_PHYS_BASE(i), msr);
msr.hi = (1 << (cpu_phys_address_size() - 32)) - 1;
msr.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID;
wrmsr(MTRR_PHYS_MASK(i), msr);
}
void fixup_cbmem_to_UC(int s3resume)
{
if (s3resume)
return;
/* For normal path, INIT_POST has returned with all
* memory set WB cacheable. But we need CBMEM as UC
* to make CAR teardown with invalidation without
* writeback possible.
*/
uintptr_t top_of_ram = (uintptr_t) cbmem_top();
top_of_ram = ALIGN_UP(top_of_ram, 4 * MiB);
set_range_uc(top_of_ram - 4 * MiB, 4 * MiB);
set_range_uc(top_of_ram - 8 * MiB, 4 * MiB);
}
void recover_postcar_frame(struct postcar_frame *pcf, int s3resume)
{
msr_t base, mask;
int i;
/* Replicate non-UC MTRRs as left behind by AGESA.
*/
for (i = 0; i < pcf->max_var_mtrrs; i++) {
mask = rdmsr(MTRR_PHYS_MASK(i));
base = rdmsr(MTRR_PHYS_BASE(i));
u32 size = ~(mask.lo & ~0xfff) + 1;
u8 type = base.lo & 0x7;
base.lo &= ~0xfff;
if (!(mask.lo & MTRR_PHYS_MASK_VALID) ||
(type == MTRR_TYPE_UNCACHEABLE))
continue;
postcar_frame_add_mtrr(pcf, base.lo, size, type);
}
/* For S3 resume path, INIT_RESUME does not return with
* memory covering CBMEM set as WB cacheable. For better
* speed make them WB after CAR teardown.
*/
if (s3resume) {
uintptr_t top_of_ram = (uintptr_t) cbmem_top();
top_of_ram = ALIGN_DOWN(top_of_ram, 4*MiB);
postcar_frame_add_mtrr(pcf, top_of_ram - 4*MiB, 4*MiB,
MTRR_TYPE_WRBACK);
postcar_frame_add_mtrr(pcf, top_of_ram - 8*MiB, 4*MiB,
MTRR_TYPE_WRBACK);
}
}

View File

@@ -18,7 +18,6 @@
#include <cbmem.h>
#include <cpu/amd/car.h>
#include <cpu/x86/bist.h>
#include <cpu/x86/mtrr.h>
#include <console/console.h>
#include <halt.h>
#include <program_loading.h>
@@ -54,6 +53,7 @@ static void fill_sysinfo(struct sysinfo *cb)
void * asmlinkage romstage_main(unsigned long bist)
{
struct postcar_frame pcf;
struct sysinfo romstage_state;
struct sysinfo *cb = &romstage_state;
u8 initial_apic_id = (u8) (cpuid_ebx(1) >> 24);
@@ -100,6 +100,9 @@ void * asmlinkage romstage_main(unsigned long bist)
}
if (IS_ENABLED(CONFIG_POSTCAR_STAGE))
fixup_cbmem_to_UC(cb->s3resume);
cbmem_initted = !cbmem_recovery(cb->s3resume);
if (cb->s3resume && !cbmem_initted) {
@@ -107,16 +110,25 @@ void * asmlinkage romstage_main(unsigned long bist)
halt();
}
uintptr_t stack_top = romstage_ram_stack_base(HIGH_ROMSTAGE_STACK_SIZE,
ROMSTAGE_STACK_CBMEM);
stack_top += HIGH_ROMSTAGE_STACK_SIZE;
romstage_handoff_init(cb->s3resume);
printk(BIOS_DEBUG, "Move CAR stack.\n");
return (void*)stack_top;
if (!IS_ENABLED(CONFIG_POSTCAR_STAGE)) {
uintptr_t stack_top = romstage_ram_stack_base(
HIGH_ROMSTAGE_STACK_SIZE, ROMSTAGE_STACK_CBMEM);
stack_top += HIGH_ROMSTAGE_STACK_SIZE;
printk(BIOS_DEBUG, "Move CAR stack.\n");
return (void*)stack_top;
}
postcar_frame_init(&pcf, HIGH_ROMSTAGE_STACK_SIZE);
recover_postcar_frame(&pcf, cb->s3resume);
run_postcar_phase(&pcf);
/* We do not return. */
return NULL;
}
#if !IS_ENABLED(CONFIG_POSTCAR_STAGE)
void asmlinkage romstage_after_car(void)
{
struct sysinfo romstage_state;
@@ -131,3 +143,4 @@ void asmlinkage romstage_after_car(void)
run_ramstage();
}
#endif

View File

@@ -27,6 +27,7 @@ config CPU_AMD_PI
select UDELAY_LAPIC
select LAPIC_MONOTONIC_TIMER
select SPI_FLASH if HAVE_ACPI_RESUME
select POSTCAR_STAGE if !BINARYPI_LEGACY_WRAPPER
if CPU_AMD_PI

View File

@@ -18,6 +18,7 @@ subdirs-$(CONFIG_CPU_AMD_PI_00730F01) += 00730F01
subdirs-$(CONFIG_CPU_AMD_PI_00660F01) += 00660F01
cpu_incs-y += $(src)/cpu/amd/agesa/cache_as_ram.S
postcar-y += ../agesa/cache_as_ram.S
ifeq ($(CONFIG_BINARYPI_LEGACY_WRAPPER), y)
romstage-y += romstage.c
@@ -25,6 +26,7 @@ ramstage-y += amd_late_init.c
romstage-y += ../agesa/heapmanager.c
else
romstage-y += ../agesa/romstage.c
romstage-y += ../agesa/mtrr_fixme.c
endif
ramstage-y += ../agesa/heapmanager.c