Marshall Dawson has uploaded this change for review. ( https://review.coreboot.org/25458
Change subject: soc/amd: Add agesa_HeapRebase callout ......................................................................
soc/amd: Add agesa_HeapRebase callout
One of AGESA's optional callout functions allows it to use a heap area managed by coreboot. Add the function here; note that AGESA does not yet call out to agesa_HeapRebase.
AGESA treats the heap as follows: * It assumes an initial heap base address of 4 MB. An abstracted call to AgesaHeapRebase is made for an opportunity to override the base. * If necessary, AGESA programs a variable MTRR in order to keep its heap in CAR. * At the end of AmdInitPost, AGESA migrates the heap to 0xb0000 (temp mem) and removes blocks that will not be used later. * After AmdInitPost, coreboot initializes cbmem and uses a region there for requested heap space. * During AmdInitEnv, AGESA migrates its heap information from temp mem to the cbmem region (main ram).
To support this callout, define a region that may be used while CAR is still present. The heap base may then either be in CAR or cbmem. Make the default cbmem (i.e. for postcar, ramstage). Add a function that can indicate the base should be in CAR instead. This currently needs to be called before an AGESA Entry Point call in bootblock and romstage. (Only a single one will be required once AGESA moves out of bootblock.) Add a call from EmptyHeap that switches the heap base to cbmem.
Future work may include: * The AMD standard CAR setup code doesn't allow enough space to use a a CAR_GLOBAL variable. Consider redoing the AMD CAR setup and teardown functionality, and use a CAR_GLOBAL region instead. * Move the heap migration and reduction from the AGESA blob into coreboot (eliminate the concept of temp ram).
BUG=b:74518368 TEST=Boot Kahlee with experimental PI blob
Change-Id: Ieda202a6064302b21707bd7ddfabc132cd85ed45 Signed-off-by: Marshall Dawson marshalldawson3rd@gmail.com --- M src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h M src/soc/amd/common/block/include/amdblocks/agesawrapper.h M src/soc/amd/common/block/pi/Kconfig M src/soc/amd/common/block/pi/def_callouts.c M src/soc/amd/common/block/pi/heapmanager.c M src/soc/amd/stoneyridge/bootblock/bootblock.c M src/soc/amd/stoneyridge/include/soc/cpu.h M src/soc/amd/stoneyridge/romstage.c 8 files changed, 86 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/58/25458/1
diff --git a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h index 34131cf..d317c66 100644 --- a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h +++ b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h @@ -33,6 +33,7 @@ UINT32 NextNodeOffset; } BIOS_BUFFER_NODE;
+AGESA_STATUS agesa_HeapRebase(UINT32 Func, UINTN Data, VOID *ConfigPtr); AGESA_STATUS agesa_AllocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr); AGESA_STATUS agesa_DeallocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr); AGESA_STATUS agesa_LocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr); diff --git a/src/soc/amd/common/block/include/amdblocks/agesawrapper.h b/src/soc/amd/common/block/include/amdblocks/agesawrapper.h index 986d6f8..00452dd4 100644 --- a/src/soc/amd/common/block/include/amdblocks/agesawrapper.h +++ b/src/soc/amd/common/block/include/amdblocks/agesawrapper.h @@ -63,4 +63,8 @@ void SetFchMidParams(FCH_INTERFACE *params); void SetNbMidParams(GNB_MID_CONFIGURATION *params);
+#define AGESA_HEAP_IN_CAR 1 +#define AGESA_HEAP_IN_DRAM 0 +void set_agesa_heap_loc(int premem); + #endif /* __AGESAWRAPPER_H__ */ diff --git a/src/soc/amd/common/block/pi/Kconfig b/src/soc/amd/common/block/pi/Kconfig index bd5926f..5c4a00b 100644 --- a/src/soc/amd/common/block/pi/Kconfig +++ b/src/soc/amd/common/block/pi/Kconfig @@ -4,3 +4,32 @@ default n help This option builds functions that interface AMD's AGESA. + +if SOC_AMD_COMMON_BLOCK_PI + +config PI_AGESA_CAR_HEAP_BASE + hex + default 0x400000 + help + The AGESA PI blob may be built to allow an optional callout for + AgesaHeapRebase. If called, this option determines the location + for the heap prior to DRAM availability. + +config PI_AGESA_CAR_HEAP_SIZE + hex + default 0x20000 + help + This option determines the amount of space allowed for AGESA heap + prior to DRAM availability. + +config PI_AGESA_HEAP_SET_MTRR + bool + default n if PI_AGESA_CAR_HEAP_BASE = 0x400000 + default y + help + AGESA is compiled with a default pre-DRAM heap base of 4 MB. It + will set a variable MTRR for this range if not overridden by + coreboot. If coreboot indicates a heap base of 4MB, AGESA can't + detect the override and will still program an MTRR. + +endif diff --git a/src/soc/amd/common/block/pi/def_callouts.c b/src/soc/amd/common/block/pi/def_callouts.c index beb2d18..bc8a2f6 100644 --- a/src/soc/amd/common/block/pi/def_callouts.c +++ b/src/soc/amd/common/block/pi/def_callouts.c @@ -30,6 +30,7 @@ { AGESA_DO_RESET, agesa_Reset }, { AGESA_FCH_OEM_CALLOUT, agesa_fch_initreset }, { AGESA_HALT_THIS_AP, agesa_HaltThisAp }, + { AGESA_HEAP_REBASE, agesa_HeapRebase }, { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl } }; #else @@ -49,6 +50,7 @@ #endif /* ENV_RAMSTAGE */
/* Optional callouts */ + { AGESA_HEAP_REBASE, agesa_HeapRebase }, { AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData }, //AgesaHeapRebase - Hook ID? { AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopUnsupported }, diff --git a/src/soc/amd/common/block/pi/heapmanager.c b/src/soc/amd/common/block/pi/heapmanager.c index a469a45..5545b00 100644 --- a/src/soc/amd/common/block/pi/heapmanager.c +++ b/src/soc/amd/common/block/pi/heapmanager.c @@ -11,7 +11,10 @@ * GNU General Public License for more details. */
- +#include <arch/early_variables.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/mtrr.h> +#include <soc/cpu.h> #include <amdblocks/agesawrapper.h> #include <amdlib.h> #include <arch/acpi.h> @@ -19,13 +22,38 @@ #include <cbmem.h> #include <string.h>
+static int use_pre_cbmem_heap CAR_GLOBAL; + static void *agesa_heap_base(void) { - return cbmem_add(CBMEM_ID_RESUME_SCRATCH, BIOS_HEAP_SIZE); + /* todo: remove ENV_BOOTBLOCK when AGESA is out of bootblock */ + if (ENV_BOOTBLOCK || car_get_var(use_pre_cbmem_heap)) + return (void *)CONFIG_PI_AGESA_CAR_HEAP_BASE; + else + return cbmem_add(CBMEM_ID_RESUME_SCRATCH, BIOS_HEAP_SIZE); +} + +/* Setting is 0 automatically. No need to initialize with AGESA_HEAP_IN_DRAM. */ +void set_agesa_heap_loc(int loc) +{ + msr_t mtrr_cap = rdmsr(MTRR_CAP_MSR); + int mtrr; + + car_set_var(use_pre_cbmem_heap, loc); + if (loc == AGESA_HEAP_IN_DRAM) + return; + + if (!IS_ENABLED(CONFIG_PI_AGESA_HEAP_SET_MTRR)) + return; + + mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_AGESA_HEAP; + set_var_mtrr(mtrr, CONFIG_PI_AGESA_CAR_HEAP_BASE, + CONFIG_PI_AGESA_CAR_HEAP_SIZE, MTRR_TYPE_WRBACK); }
static void EmptyHeap(int unused) { + set_agesa_heap_loc(AGESA_HEAP_IN_DRAM); void *BiosManagerPtr = agesa_heap_base(); memset(BiosManagerPtr, 0, BIOS_HEAP_SIZE); } @@ -35,6 +63,21 @@ #endif ROMSTAGE_CBMEM_INIT_HOOK(EmptyHeap)
+AGESA_STATUS agesa_HeapRebase(UINT32 Func, UINTN Data, VOID *ConfigPtr) +{ + AGESA_REBASE_PARAMS *RebaseParams; + + RebaseParams = (AGESA_REBASE_PARAMS *)ConfigPtr; + RebaseParams->HeapAddress = (UINTN)agesa_heap_base(); + + if (RebaseParams->HeapAddress) { + return AGESA_SUCCESS; + } else { + printk(BIOS_ERR, "Error: AGESA heap has no base\n"); + return AGESA_ERROR; + } +} + AGESA_STATUS agesa_AllocateBuffer (UINT32 Func, UINTN Data, VOID *ConfigPtr) { UINT32 AvailableHeapSize; diff --git a/src/soc/amd/stoneyridge/bootblock/bootblock.c b/src/soc/amd/stoneyridge/bootblock/bootblock.c index db5c9b6..6fa9239 100644 --- a/src/soc/amd/stoneyridge/bootblock/bootblock.c +++ b/src/soc/amd/stoneyridge/bootblock/bootblock.c @@ -121,6 +121,8 @@ if (boot_cpu() && IS_ENABLED(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW)) load_smu_fw1();
+ set_agesa_heap_loc(AGESA_HEAP_IN_CAR); + post_code(0x37); do_agesawrapper(agesawrapper_amdinitreset, "amdinitreset");
diff --git a/src/soc/amd/stoneyridge/include/soc/cpu.h b/src/soc/amd/stoneyridge/include/soc/cpu.h index bf8ed49..d4acae7 100644 --- a/src/soc/amd/stoneyridge/include/soc/cpu.h +++ b/src/soc/amd/stoneyridge/include/soc/cpu.h @@ -26,6 +26,7 @@ * todo: Revisit this once AGESA no longer programs MTRRs. */ #define SOC_EARLY_VMTRR_FLASH 2 +#define SOC_EARLY_VMTRR_AGESA_HEAP 1
void stoney_init_cpus(struct device *dev);
diff --git a/src/soc/amd/stoneyridge/romstage.c b/src/soc/amd/stoneyridge/romstage.c index 490fd9e..fc50d98 100644 --- a/src/soc/amd/stoneyridge/romstage.c +++ b/src/soc/amd/stoneyridge/romstage.c @@ -47,6 +47,8 @@
console_init();
+ set_agesa_heap_loc(AGESA_HEAP_IN_CAR); /* Re-init for romstage */ + if (!s3_resume) { post_code(0x40); do_agesawrapper(agesawrapper_amdinitpost, "amdinitpost");