cpu/x86/mtrr: Simplify MTRR solution calculation on AMD systems

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 <michal.zygowski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89199
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Michał Żygowski 2025-09-16 09:15:27 +02:00 committed by Matt DeVillier
commit 04f83ff7dc
2 changed files with 39 additions and 5 deletions

View file

@ -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);
}

View file

@ -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();