Matt DeVillier has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/86941?usp=email )
Change subject: cpu/x86/mtrr: Exclude ranges above 4G if temporary MTRRs exhausted ......................................................................
cpu/x86/mtrr: Exclude ranges above 4G if temporary MTRRs exhausted
mtrr_use_temp_range() is used to temporarily cache the 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 > 32MB of RAM, there are not enough MTRRs available to map these regions as well as any RAM above 4GB.
As a workaround, modify calc_var_mtrrs() to return the number of MTRRs needed in addition to the default type, and if that number exceeds the max available, retry with `above4gb` set to 0.
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 matt.devillier@gmail.com --- M src/cpu/x86/mtrr/mtrr.c 1 file changed, 16 insertions(+), 7 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/41/86941/1
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 64ab829..a911f9d 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -661,7 +661,7 @@ }
static int calc_var_mtrrs(struct memranges *addr_space, - int above4gb, int address_bits) + int above4gb, int address_bits, int *num_mtrrs_used) { int wb_deftype_count = 0; int uc_deftype_count = 0; @@ -685,9 +685,11 @@
if (wb_deftype_count < uc_deftype_count) { printk(BIOS_DEBUG, "MTRR: WB selected as default type.\n"); + *num_mtrrs_used = wb_deftype_count; return MTRR_TYPE_WRBACK; } printk(BIOS_DEBUG, "MTRR: UC selected as default type.\n"); + *num_mtrrs_used = uc_deftype_count; return MTRR_TYPE_UNCACHEABLE; }
@@ -746,13 +748,14 @@ { static struct var_mtrr_solution *sol = NULL; struct memranges *addr_space; + int num_mtrrs_used;
addr_space = get_physical_address_space();
if (sol == NULL) { sol = &mtrr_global_solution; sol->mtrr_default_type = - calc_var_mtrrs(addr_space, !!above4gb, address_bits); + calc_var_mtrrs(addr_space, !!above4gb, address_bits, &num_mtrrs_used); prepare_var_mtrrs(addr_space, sol->mtrr_default_type, !!above4gb, address_bits, sol); } @@ -827,8 +830,9 @@ const struct memranges *orig; struct var_mtrr_solution sol; struct memranges addr_space; - const int above4gb = 1; /* Cover above 4GiB by default. */ + int above4gb = 1; /* Cover above 4GiB by default. */ int address_bits; + int num_mtrrs_used; static struct temp_range { uintptr_t begin; size_t size; @@ -880,10 +884,15 @@ /* Calculate a new solution with the updated address space. */ address_bits = cpu_phys_address_size(); memset(&sol, 0, sizeof(sol)); - sol.mtrr_default_type = - calc_var_mtrrs(&addr_space, above4gb, address_bits); - prepare_var_mtrrs(&addr_space, sol.mtrr_default_type, - above4gb, address_bits, &sol); + 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 = 0; + sol.mtrr_default_type = calc_var_mtrrs(&addr_space, above4gb, address_bits, &num_mtrrs_used); + } + prepare_var_mtrrs(&addr_space, sol.mtrr_default_type, above4gb, address_bits, &sol);
if (commit_var_mtrrs(&sol) < 0) printk(BIOS_WARNING, "Unable to insert temporary MTRR range: 0x%016llx - 0x%016llx size 0x%08llx type %d\n",