From 5f6cf6105c701f017c1a194710b05bba2756d003 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Fri, 14 Jul 2023 22:37:03 +0200 Subject: vendorcode/amd/genoa: Parse APOB for DRAM layout Use the xPRF call to report holes in memory to report those regions as reserved. Signed-off-by: Arthur Heymans Change-Id: If89b08a31a9b9f8e7d2959d1bc45e91763fe565b Reviewed-on: https://review.coreboot.org/c/coreboot/+/78922 Reviewed-by: Matt DeVillier Tested-by: build bot (Jenkins) --- src/vendorcode/amd/opensil/genoa_poc/Makefile.inc | 1 + src/vendorcode/amd/opensil/genoa_poc/memmap.c | 150 ++++++++++++++++++++++ src/vendorcode/amd/opensil/genoa_poc/opensil.h | 14 ++ src/vendorcode/amd/opensil/genoa_poc/ramstage.c | 3 +- 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/vendorcode/amd/opensil/genoa_poc/memmap.c create mode 100644 src/vendorcode/amd/opensil/genoa_poc/opensil.h (limited to 'src/vendorcode/amd') diff --git a/src/vendorcode/amd/opensil/genoa_poc/Makefile.inc b/src/vendorcode/amd/opensil/genoa_poc/Makefile.inc index cccb006686..b09299b976 100644 --- a/src/vendorcode/amd/opensil/genoa_poc/Makefile.inc +++ b/src/vendorcode/amd/opensil/genoa_poc/Makefile.inc @@ -8,6 +8,7 @@ CPPFLAGS_romstage += -I$(opensil_dir)/Include -I$(opensil_dir)/xUSL -I$(opensil_ romstage-y += opensil_console.c romstage-y += romstage.c +ramstage-y += memmap.c ramstage-y += opensil_console.c ramstage-y += ramstage.c diff --git a/src/vendorcode/amd/opensil/genoa_poc/memmap.c b/src/vendorcode/amd/opensil/genoa_poc/memmap.c new file mode 100644 index 0000000000..4e5b4576f3 --- /dev/null +++ b/src/vendorcode/amd/opensil/genoa_poc/memmap.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include // needed above ApobCmn.h +#include +#include +#include +#include +#include +#include + +#include "opensil.h" + +static const char *hole_info_type(MEMORY_HOLE_TYPES type) +{ + const struct hole_type { + MEMORY_HOLE_TYPES type; + const char *string; + } types[] = { + {UMA, "UMA"}, + {MMIO, "MMIO"}, + {PrivilegedDRAM, "PrivilegedDRAM"}, + {Reserved1TbRemap, "Reserved1TbRemap"}, + {ReservedSLink, "ReservedSLink"}, + {ReservedSLinkAlignment, "ReservedSLinkAlignment"}, + {ReservedDrtm, "ReservedDrtm"}, + {ReservedCvip, "ReservedCvip"}, + {ReservedSmuFeatures, "ReservedSmuFeatures"}, + {ReservedFwtpm, "ReservedFwtpm"}, + {ReservedMpioC20, "ReservedMpioC20"}, + {ReservedNbif, "ReservedNbif"}, + {ReservedCxl, "ReservedCxl"}, + {ReservedCxlAlignment, "ReservedCxlAlignment"}, + {ReservedCpuTmr, "ReservedCpuTmr"}, + {ReservedRasEinj, "ReservedRasEinj"}, + {MaxMemoryHoleTypes, "MaxMemoryHoleTypes"}, + }; + + int i; + for (i = 0; i < ARRAY_SIZE(types); i++) + if (type == types[i].type) + break; + if (i == ARRAY_SIZE(types)) + return "Unknown type"; + return types[i].string; +} + +static uint64_t top_of_mem; +static uint32_t n_holes; +static MEMORY_HOLE_DESCRIPTOR *hole_info; + +static void get_hole_info(void) +{ + static bool done; + if (done) + return; + SIL_STATUS status = xPrfGetSystemMemoryMap(&n_holes, &top_of_mem, (void **)&hole_info); + SIL_STATUS_report("xPrfGetSystemMemoryMap", status); + // Make sure hole_info does not get initialized to something odd by xPRF on failure + if (status != SilPass) + hole_info = NULL; + done = true; +} + + +static void print_memory_holes(void *unused) +{ + get_hole_info(); + if (hole_info == NULL) + return; + + printk(BIOS_DEBUG, "APOB: top of memory 0x%016llx\n", top_of_mem); + printk(BIOS_DEBUG, "The following holes are reported in APOB\n"); + for (int hole = 0; hole < n_holes; hole++) { + printk(BIOS_DEBUG, " Base: 0x%016llx, Size: 0x%016llx, Type: %02d:%s\n", + hole_info[hole].Base, hole_info[hole].Size, hole_info[hole].Type, + hole_info_type(hole_info[hole].Type)); + } +} + +BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, print_memory_holes, NULL); + +// This assumes holes are allocated +int add_opensil_memmap(struct device *dev, int idx) +{ + ram_from_to(dev, idx++, 0, 0xa0000); + mmio_from_to(dev, idx++, 0xa0000, 0xc0000); // legacy VGA + reserved_ram_from_to(dev, idx++, 0xc0000, 1 * MiB); // Option ROM + + uint32_t mem_usable = (uintptr_t)cbmem_top(); + uintptr_t early_reserved_dram_start, early_reserved_dram_end; + const struct memmap_early_dram *e = memmap_get_early_dram_usage(); + + early_reserved_dram_start = e->base; + early_reserved_dram_end = e->base + e->size; + + // 1MB - bottom of DRAM reserved for early coreboot usage + ram_from_to(dev, idx++, 1 * MiB, early_reserved_dram_start); + + // DRAM reserved for early coreboot usage + reserved_ram_from_to(dev, idx++, early_reserved_dram_start, + early_reserved_dram_end); + + // top of DRAM consumed early - low top usable RAM + // cbmem_top() accounts for low UMA and TSEG if they are used. + ram_from_to(dev, idx++, early_reserved_dram_end, + mem_usable); + + // Account for UMA and TSEG + const uint32_t top_mem = ALIGN_DOWN(rdmsr(TOP_MEM).lo, 1 * MiB); + if (mem_usable != top_mem) + reserved_ram_from_to(dev, idx++, mem_usable, top_mem); + + mmconf_resource(dev, idx++); + + // Check if we're done + if (top_of_mem <= 0x100000000) + return idx; + + // Holes in upper DRAM + // This assumes all the holes in upper DRAM are continuous + get_hole_info(); + if (hole_info == NULL) + return idx; + uint64_t lowest_upper_hole_base = top_of_mem; + uint64_t highest_upper_hole_end = 0x100000000; + for (int hole = 0; hole < n_holes; hole++) { + if (hole_info[hole].Type == MMIO) + continue; + if (hole_info[hole].Base < 0x100000000) + continue; + lowest_upper_hole_base = MIN(lowest_upper_hole_base, hole_info[hole].Base); + highest_upper_hole_end = MAX(highest_upper_hole_end, hole_info[hole].Base + hole_info[hole].Size); + if (hole_info[hole].Type == UMA) + mmio_range(dev, idx++, hole_info[hole].Base, hole_info[hole].Size); + else + reserved_ram_range(dev, idx++, hole_info[hole].Base, hole_info[hole].Size); + } + + ram_from_to(dev, idx++, 0x100000000, lowest_upper_hole_base); + + // Do we need this? + if (top_of_mem > highest_upper_hole_end) + ram_from_to(dev, idx++, highest_upper_hole_end, top_of_mem); + + return idx; +} diff --git a/src/vendorcode/amd/opensil/genoa_poc/opensil.h b/src/vendorcode/amd/opensil/genoa_poc/opensil.h new file mode 100644 index 0000000000..ecde809ca7 --- /dev/null +++ b/src/vendorcode/amd/opensil/genoa_poc/opensil.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _OPENSIL_H_ +#define _OPENSIL_H_ + +#include + +void SIL_STATUS_report(const char *function, const int status); +// Add the memory map to dev, starting at index idx, returns last use idx +int add_opensil_memmap(struct device *dev, int idx); +// Fill in FADT from opensil +void opensil_fill_fadt(acpi_fadt_t *fadt); + +#endif diff --git a/src/vendorcode/amd/opensil/genoa_poc/ramstage.c b/src/vendorcode/amd/opensil/genoa_poc/ramstage.c index d9c8add8d8..ab551999d8 100644 --- a/src/vendorcode/amd/opensil/genoa_poc/ramstage.c +++ b/src/vendorcode/amd/opensil/genoa_poc/ramstage.c @@ -11,8 +11,9 @@ #include #include #include "opensil_console.h" +#include "opensil.h" -static void SIL_STATUS_report(const char *function, const int status) +void SIL_STATUS_report(const char *function, const int status) { const int log_level = status == SilPass ? BIOS_DEBUG : BIOS_ERR; const char *error_string = "Unkown error"; -- cgit v1.2.3