From cff3efa1e35c8edaceca4ff5d76d28f597b6b27c Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Thu, 20 Mar 2025 13:54:32 -0500 Subject: [PATCH] cpu/x86/mtrr: Return number of MTRRs used via calc_var_mtrrs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calc_var_mtrrs() calculates the number of MTRRs needed for both WB and UC default memory types, and returns the type that uses fewer MTRRs. Modify it to return the number of MTRRs used as well, and if that count exceeeds the number available on the system, throw an error and skip calling prepare_var_mtrrs() as we know it will fail. TEST=tested with rest of patch train Change-Id: I2be7c5b3385731f4dc9ef62de15dcf6d4cceb5d3 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/86955 Reviewed-by: Jérémy Compostella Tested-by: build bot (Jenkins) --- src/cpu/x86/mtrr/mtrr.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index edc6fc602e..f5a0547e09 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -660,8 +660,8 @@ static void __calc_var_mtrrs(struct memranges *addr_space, *num_def_uc_mtrrs = uc_deftype_count; } -static int calc_var_mtrrs(struct memranges *addr_space, - bool above4gb, int address_bits) +static int calc_var_mtrrs(struct memranges *addr_space, bool above4gb, int address_bits, + int *num_mtrrs_used) { int wb_deftype_count = 0; int uc_deftype_count = 0; @@ -685,9 +685,11 @@ static int calc_var_mtrrs(struct memranges *addr_space, 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 @@ void x86_setup_var_mtrrs(unsigned int address_bits, bool above4gb) { 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); } @@ -830,6 +833,7 @@ void mtrr_use_temp_range(uintptr_t begin, size_t size, int type) struct memranges addr_space; const bool above4gb = true; /* Cover above 4GiB by default. */ int address_bits; + int num_mtrrs_used; static struct temp_range { uintptr_t begin; size_t size; @@ -882,14 +886,16 @@ void mtrr_use_temp_range(uintptr_t begin, size_t size, int type) 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); + calc_var_mtrrs(&addr_space, above4gb, address_bits, &num_mtrrs_used); - 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", - (long long)begin, (long long)begin + size - 1, - (long long)size, type); + if (num_mtrrs_used <= total_mtrrs) + prepare_var_mtrrs(&addr_space, sol.mtrr_default_type, above4gb, address_bits, &sol); + else + printk(BIOS_ERR, "Not enough MTRRs: %d needed vs %d available\n", num_mtrrs_used, total_mtrrs); + + if (num_mtrrs_used > total_mtrrs || commit_var_mtrrs(&sol) < 0) + printk(BIOS_ERR, "Unable to insert temporary MTRR range: 0x%016llx - 0x%016llx size 0x%08llx type %d\n", + (long long)begin, (long long)begin + size - 1, (long long)size, type); else put_back_original_solution = true;