From 04f83ff7dcae1977daa14ea1555e376a453a9e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Tue, 16 Sep 2025 09:15:27 +0200 Subject: [PATCH] cpu/x86/mtrr: Simplify MTRR solution calculation on AMD systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AMD systems have a TOM2WB bit in SYS_CFG MSR to forcefully cover the address space between 4GB-TOM2 as WB. Any WB MTRR that falls into that range may be skipped from programming. It can save a lot of MTRRs when calculating the MTRR solution. It is especially needed when using a temporary MTRR to cover the flash as WP, as the MTRR space gets more fragmented. Add checks for SYS_CFG TOM2WB in the MTRR driver and skip the WB MTRR ranges when possible. TEST=Successfully enable temporary MTRR range for flash on Gigabyte MZ33-AR1. Change-Id: Ie9af9b54a1037c843d8f019506af761a8d8769d0 Signed-off-by: Michał Żygowski Reviewed-on: https://review.coreboot.org/c/coreboot/+/89199 Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/cpu/x86/mtrr/mtrr.c | 38 +++++++++++++++++++ .../amd/common/block/cpu/smm/smm_relocate.c | 6 +-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 33fc46e362..72727861de 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -598,6 +598,25 @@ static void calc_var_mtrrs_with_hole(struct var_mtrr_state *var_state, } } +static bool is_tom2_wb_active(void) +{ + msr_t syscfg = rdmsr(SYSCFG_MSR); + syscfg.lo &= (SYSCFG_MSR_TOM2WB | SYSCFG_MSR_TOM2En); + return (syscfg.lo == (SYSCFG_MSR_TOM2WB | SYSCFG_MSR_TOM2En)); +} + +static bool is_range_in_tom2_wb(struct range_entry *r) +{ + const msr_t tom2_msr = rdmsr(TOP_MEM2_MSR); + const uint64_t tom2 = tom2_msr.lo | ((uint64_t)tom2_msr.hi << 32); + const int mtrr_type = range_entry_mtrr_type(r); + + if ((r->begin >= (4ULL * GiB)) && (r->end < tom2)) + return (mtrr_type == MTRR_TYPE_WRBACK); + + return false; +} + static void __calc_var_mtrrs(struct memranges *addr_space, bool above4gb, int address_bits, int *num_def_wb_mtrrs, int *num_def_uc_mtrrs) @@ -633,6 +652,15 @@ static void __calc_var_mtrrs(struct memranges *addr_space, mtrr_type = range_entry_mtrr_type(r); + /* + * WB MTRRs inside [4G - TOM2] range can be skipped on AMD, if + * TOM2 WB is active. + */ + if (CONFIG(X86_AMD_FIXED_MTRRS) && above4gb) { + if (is_tom2_wb_active() && is_range_in_tom2_wb(r)) + continue; + } + if (mtrr_type != MTRR_TYPE_UNCACHEABLE) { var_state.mtrr_index = 0; var_state.def_mtrr_type = MTRR_TYPE_UNCACHEABLE; @@ -704,6 +732,16 @@ static void prepare_var_mtrrs(struct memranges *addr_space, int def_type, memranges_each_entry(r, var_state.addr_space) { if (range_entry_mtrr_type(r) == def_type) continue; + + /* + * WB MTRRs inside [4G - TOM2] range can be skipped on AMD, if + * TOM2 WB is active. + */ + if (CONFIG(X86_AMD_FIXED_MTRRS) && above4gb) { + if (is_tom2_wb_active() && is_range_in_tom2_wb(r)) + continue; + } + calc_var_mtrrs_with_hole(&var_state, r); } diff --git a/src/soc/amd/common/block/cpu/smm/smm_relocate.c b/src/soc/amd/common/block/cpu/smm/smm_relocate.c index d01f4c3e2d..e5b8d9d17a 100644 --- a/src/soc/amd/common/block/cpu/smm/smm_relocate.c +++ b/src/soc/amd/common/block/cpu/smm/smm_relocate.c @@ -17,11 +17,7 @@ /* AP MTRRs will be synced to the BSP in the SIPI vector so set them up before MP init. */ static void pre_mp_init(void) { - const msr_t syscfg = rdmsr(SYSCFG_MSR); - if (syscfg.lo & SYSCFG_MSR_TOM2WB) - x86_setup_mtrrs_with_detect_no_above_4gb(); - else - x86_setup_mtrrs_with_detect(); + x86_setup_mtrrs_with_detect(); x86_mtrr_check(); if (CONFIG(SOC_AMD_COMMON_BLOCK_UCODE)) amd_load_microcode_from_cbfs();