From 5dd0181f7b9733837331ef6ca37eb8f4db37693b Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Thu, 20 Mar 2025 13:54:32 -0500 Subject: [PATCH] cpu/x86/mtrr: Exclude ranges above 4G if temporary MTRRs exhausted mtrr_use_temp_range() is used to temporarily cache the area(s) of RAM to which the SPI flash is mapped, in order to speed up reading the payload out of flash in preparation for execution. On systems with more than 32GiB of RAM, there are not enough MTRRs available to map the "permanent" regions below 4GiB, these temporary regions below 4GiB, and any RAM above 4GiB due to fragmentation in the various ranges, as well as limitations on the area covered by a single MTRR due to how they are stored in the CPU registers. As a workaround, if the number of MTRRs needed for the temporary map exceeds the maximum available for the system, retry calc_var-mtrrs() with `above4gb` set to false. TEST=build/boot starlabs/starbook_mtl with > 32GB RAM, verify temporary MTRRs are able to be assigned via cbmem console log, and no boot delays in payload loading/decompression due to the SPI flash not being cached. Change-Id: Ia9f9a1537e7e0c2f7ce21067eceb1549d0f9ea5b Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/86941 Tested-by: build bot (Jenkins) Reviewed-by: Shuo Liu --- src/cpu/x86/mtrr/mtrr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index f5a0547e09..0d31cab769 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -831,7 +831,7 @@ void mtrr_use_temp_range(uintptr_t begin, size_t size, int type) const struct memranges *orig; struct var_mtrr_solution sol; struct memranges addr_space; - const bool above4gb = true; /* Cover above 4GiB by default. */ + bool above4gb = true; /* Cover above 4GiB by default. */ int address_bits; int num_mtrrs_used; static struct temp_range { @@ -888,6 +888,12 @@ void mtrr_use_temp_range(uintptr_t begin, size_t size, int type) sol.mtrr_default_type = calc_var_mtrrs(&addr_space, above4gb, address_bits, &num_mtrrs_used); + /* If we ran out of MTRRs, retry excluding ranges above 4GiB */ + if (above4gb && num_mtrrs_used > total_mtrrs) { + printk(BIOS_WARNING, "MTRR: Ran out of variable MTRRs; retrying excluding ranges above 4GiB.\n"); + above4gb = false; + sol.mtrr_default_type = calc_var_mtrrs(&addr_space, above4gb, address_bits, &num_mtrrs_used); + } if (num_mtrrs_used <= total_mtrrs) prepare_var_mtrrs(&addr_space, sol.mtrr_default_type, above4gb, address_bits, &sol); else