summaryrefslogtreecommitdiffstats
path: root/src/soc
diff options
context:
space:
mode:
authorJonathan Zhang <jonzhang@meta.com>2022-12-19 15:42:56 -0800
committerMartin L Roth <gaumless@gmail.com>2023-01-08 01:31:29 +0000
commit43b0ed708963110368d6cf1a048f79d3a09817ea (patch)
tree1162d6b9f5eec9cc503687195b06f9e331f41166 /src/soc
parentaa990125b8c8add886762013acb159571d34b3bf (diff)
downloadcoreboot-43b0ed708963110368d6cf1a048f79d3a09817ea.tar.gz
coreboot-43b0ed708963110368d6cf1a048f79d3a09817ea.tar.bz2
coreboot-43b0ed708963110368d6cf1a048f79d3a09817ea.zip
soc/intel/xeon_sp: Improve final MTRR solution
If cbmem_top is not 1M aligned there will be a hole between DPR base and cbmem_top that the allocator will consider as unassigned memory. Resources could incorrectly be assigned to that region and the final MTRR solution will also try to skip that hole, therefore using a lot more variable MTRRs than needed. TESTED on Archer City 2S system: Uses 1 variable MTRR in the final setup instead of 7. Change-Id: I198f8d83bcfcdca3a770bd7f9a7060d5782a49fe Signed-off-by: Arthur Heymans <arthur.heymans@9elements.com> Signed-off-by: Jonathan Zhang <jonzhang@meta.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/71142 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Marc Jones <marc@marcjonesconsulting.com>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/xeon_sp/uncore.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/soc/intel/xeon_sp/uncore.c b/src/soc/intel/xeon_sp/uncore.c
index 1a60b60e2579..d4cf4bcc2910 100644
--- a/src/soc/intel/xeon_sp/uncore.c
+++ b/src/soc/intel/xeon_sp/uncore.c
@@ -146,6 +146,8 @@ static void configure_dpr(struct device *dev)
* | Tseg (relocatable) | N x 8MB (0x70000000 - 0x77ffffff, 0x20000)
* +--------------------------+
* | DPR |
+ * +--------------------------+ 1M aligned DPR base
+ * | Unused memory |
* +--------------------------+ cbmem_top
* | Reserved - CBMEM | (0x6fffe000 - 0x6fffffff, 0x2000)
* +--------------------------+
@@ -168,7 +170,9 @@ static void mc_add_dram_resources(struct device *dev, int *res_count)
{
const struct resource *res;
uint64_t mc_values[NUM_MAP_ENTRIES];
+ uint64_t top_of_ram;
int index = *res_count;
+ struct range_entry fsp_mem;
/* Only add dram resources once. */
if (dev->bus->secondary != 0)
@@ -182,24 +186,41 @@ static void mc_add_dram_resources(struct device *dev, int *res_count)
res = ram_from_to(dev, index++, 0, 0xa0000);
LOG_RESOURCE("legacy_ram", dev, res);
- /* 1MB -> top_of_ram i.e., cbmem_top */
- res = ram_from_to(dev, index++, 1 * MiB, (uintptr_t)cbmem_top());
+ /* 1MB -> top_of_ram */
+ fsp_find_reserved_memory(&fsp_mem);
+ top_of_ram = range_entry_base(&fsp_mem) - 1;
+ res = ram_from_to(dev, index++, 1 * MiB, top_of_ram);
LOG_RESOURCE("low_ram", dev, res);
- /* Mark TSEG/SMM region as reserved */
- res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
- mc_values[TSEG_LIMIT_REG] + 1);
- LOG_RESOURCE("mmio_tseg", dev, res);
+ /* top_of_ram -> cbmem_top */
+ res = ram_from_to(dev, index++, top_of_ram, (uintptr_t)cbmem_top());
+ LOG_RESOURCE("cbmem_ram", dev, res);
/* Reserve and set up DPR */
configure_dpr(dev);
union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) };
if (dpr.size) {
+ /*
+ * cbmem_top -> DPR base:
+ * DPR has a 1M granularity so it's possible if cbmem_top is not 1M
+ * aligned that some memory does not get marked as assigned.
+ */
+ res = reserved_ram_from_to(dev, index++, (uintptr_t)cbmem_top(),
+ (dpr.top - dpr.size) * MiB);
+ LOG_RESOURCE("unused_dram", dev, res);
+
+ /* DPR base -> DPR top */
res = reserved_ram_from_to(dev, index++, (dpr.top - dpr.size) * MiB,
dpr.top * MiB);
LOG_RESOURCE("dpr", dev, res);
+
}
+ /* Mark TSEG/SMM region as reserved */
+ res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
+ mc_values[TSEG_LIMIT_REG] + 1);
+ LOG_RESOURCE("mmio_tseg", dev, res);
+
/* Mark region between TSEG - TOLM (eg. MESEG) as reserved */
res = reserved_ram_from_to(dev, index++, mc_values[TSEG_LIMIT_REG] + 1,
mc_values[TOLM_REG]);