diff options
author | Jonathan Zhang <jonzhang@meta.com> | 2022-12-19 15:42:56 -0800 |
---|---|---|
committer | Martin L Roth <gaumless@gmail.com> | 2023-01-08 01:31:29 +0000 |
commit | 43b0ed708963110368d6cf1a048f79d3a09817ea (patch) | |
tree | 1162d6b9f5eec9cc503687195b06f9e331f41166 /src/soc/intel/xeon_sp | |
parent | aa990125b8c8add886762013acb159571d34b3bf (diff) |
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/intel/xeon_sp')
-rw-r--r-- | src/soc/intel/xeon_sp/uncore.c | 33 |
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 1a60b60e25..d4cf4bcc29 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]); |