summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2023-07-14 22:37:03 +0200
committerFelix Held <felix-coreboot@felixheld.de>2023-12-12 18:26:09 +0000
commit5f6cf6105c701f017c1a194710b05bba2756d003 (patch)
tree74bc955ad24adec6923c71b35ab961c98c143ebc
parenta31b28cb230d21a57b6f0a3104d03ff9aa7ee795 (diff)
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 <arthur@aheymans.xyz> Change-Id: If89b08a31a9b9f8e7d2959d1bc45e91763fe565b Reviewed-on: https://review.coreboot.org/c/coreboot/+/78922 Reviewed-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--src/vendorcode/amd/opensil/genoa_poc/Makefile.inc1
-rw-r--r--src/vendorcode/amd/opensil/genoa_poc/memmap.c150
-rw-r--r--src/vendorcode/amd/opensil/genoa_poc/opensil.h14
-rw-r--r--src/vendorcode/amd/opensil/genoa_poc/ramstage.c3
4 files changed, 167 insertions, 1 deletions
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 <bootstate.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <SilCommon.h>
+#include <Sil-api.h> // needed above ApobCmn.h
+#include <ApobCmn.h>
+#include <device/device.h>
+#include <xPRF-api.h>
+#include <cpu/amd/mtrr.h>
+#include <cbmem.h>
+#include <amdblocks/memmap.h>
+
+#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 <acpi/acpi.h>
+
+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 <soc/soc_chip.h>
#include <xSIM-api.h>
#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";