From 5f941893ef9901c82e09d4a79e7e1a42fbdedff3 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Mon, 5 May 2025 16:58:02 +0530 Subject: [PATCH] cpu/x86/mtrr: Introduce mtrrlib with common MTRR helper functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change refactors MTRR handling by consolidating helper functions from `earlymtrr.c` and `mtrr.c` into a new MTRR library (`mtrrlib`). This approach improves code modularity and reusability, making these utilities consistently available across different coreboot boot phases. The following functions are now part of `mtrrlib`: - `get_free_var_mtrr`: Retrieves the index of the first available variable MTRR. - `set_var_mtrr`: Configures the variable MTRR, specified by an `index`, for a memory region defined by `base`, `size`, and `type`. - `clear_var_mtrr`: Disables the variable MTRR at a given index. - `acquire_and_configure_mtrr`: Acquires a free variable MTRR, configures it with the given `base`, `size`, and `type`. BUG=b:409718202 TEST=Built and booted google/fatcat successfully. Change-Id: Iba332b7088221fd930e973fad9410833bff184b9 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/87539 Reviewed-by: Jérémy Compostella Reviewed-by: Shuo Liu Tested-by: build bot (Jenkins) Reviewed-by: Nick Vaccaro --- src/cpu/x86/mtrr/Makefile.mk | 6 +++ src/cpu/x86/mtrr/earlymtrr.c | 57 +----------------------- src/cpu/x86/mtrr/mtrr.c | 8 ---- src/cpu/x86/mtrr/mtrrlib.c | 85 ++++++++++++++++++++++++++++++++++++ src/include/cpu/x86/mtrr.h | 4 +- 5 files changed, 96 insertions(+), 64 deletions(-) create mode 100644 src/cpu/x86/mtrr/mtrrlib.c diff --git a/src/cpu/x86/mtrr/Makefile.mk b/src/cpu/x86/mtrr/Makefile.mk index c74f014531..2846280d25 100644 --- a/src/cpu/x86/mtrr/Makefile.mk +++ b/src/cpu/x86/mtrr/Makefile.mk @@ -1,5 +1,11 @@ ## SPDX-License-Identifier: GPL-2.0-only +bootblock-y += mtrrlib.c +verstage_x86-y += mtrrlib.c +romstage-y += mtrrlib.c +postcar-y += mtrrlib.c +ramstage-y += mtrrlib.c + ramstage-y += mtrr.c romstage-y += earlymtrr.c diff --git a/src/cpu/x86/mtrr/earlymtrr.c b/src/cpu/x86/mtrr/earlymtrr.c index 6c819a8c46..4ca7a0a5a4 100644 --- a/src/cpu/x86/mtrr/earlymtrr.c +++ b/src/cpu/x86/mtrr/earlymtrr.c @@ -7,67 +7,14 @@ #include #include -/* Get first available variable MTRR. - * Returns var# if available, else returns -1. - */ -int get_free_var_mtrr(void) -{ - msr_t maskm; - int vcnt; - int i; - - vcnt = get_var_mtrr_count(); - - /* Identify the first var mtrr which is not valid. */ - for (i = 0; i < vcnt; i++) { - maskm = rdmsr(MTRR_PHYS_MASK(i)); - if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0) - return i; - } - - /* No free var mtrr. */ - return -1; -} - -void set_var_mtrr( - unsigned int reg, unsigned int base, unsigned int size, - unsigned int type) -{ - /* Bit 32-35 of MTRRphysMask should be set to 1 */ - /* FIXME: It only support 4G less range */ - msr_t basem, maskm; - - if (type == MTRR_TYPE_WRBACK && !is_cache_sets_power_of_two() && ENV_CACHE_AS_RAM) - printk(BIOS_ERR, "MTRR Error: Type %x may not be supported due to NEM limitation\n", - type); - if (!IS_POWER_OF_2(size)) - printk(BIOS_ERR, "MTRR Error: size %#x is not a power of two\n", size); - if (size < 4 * KiB) - printk(BIOS_ERR, "MTRR Error: size %#x smaller than 4KiB\n", size); - if (base % size != 0) - printk(BIOS_ERR, "MTRR Error: base %#x must be aligned to size %#x\n", base, - size); - - basem.lo = base | type; - basem.hi = 0; - wrmsr(MTRR_PHYS_BASE(reg), basem); - maskm.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID; - maskm.hi = (1 << (cpu_phys_address_size() - 32)) - 1; - wrmsr(MTRR_PHYS_MASK(reg), maskm); -} - void clear_all_var_mtrr(void) { - msr_t mtrr = { .raw = 0 }; int vcnt; - int i; vcnt = get_var_mtrr_count(); - for (i = 0; i < vcnt; i++) { - wrmsr(MTRR_PHYS_MASK(i), mtrr); - wrmsr(MTRR_PHYS_BASE(i), mtrr); - } + for (int i = 0; i < vcnt; i++) + clear_var_mtrr(i); } void var_mtrr_context_init(struct var_mtrr_context *ctx) diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 0d31cab769..33fc46e362 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -369,14 +369,6 @@ struct var_mtrr_state { struct var_mtrr_regs *regs; }; -static void clear_var_mtrr(int index) -{ - msr_t msr = { .lo = 0, .hi = 0 }; - - wrmsr(MTRR_PHYS_BASE(index), msr); - wrmsr(MTRR_PHYS_MASK(index), msr); -} - static int get_os_reserved_mtrrs(void) { return CONFIG(RESERVE_MTRRS_FOR_OS) ? 2 : 0; diff --git a/src/cpu/x86/mtrr/mtrrlib.c b/src/cpu/x86/mtrr/mtrrlib.c new file mode 100644 index 0000000000..fe6bd6aef5 --- /dev/null +++ b/src/cpu/x86/mtrr/mtrrlib.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +/* + * Get first available variable MTRR. + * Returns var# if available, else returns -1. + */ +int get_free_var_mtrr(void) +{ + msr_t maskm; + int vcnt; + int i; + + vcnt = get_var_mtrr_count(); + + /* Identify the first var mtrr which is not valid. */ + for (i = 0; i < vcnt; i++) { + maskm = rdmsr(MTRR_PHYS_MASK(i)); + if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0) + return i; + } + + /* No free var mtrr. */ + return -1; +} + +/* + * Sets the specified variable MTRR (as per index) with the + * given base, size, and memory type. + */ +void set_var_mtrr( + unsigned int index, unsigned int base, unsigned int size, + unsigned int type) +{ + /* Bit 32-35 of MTRRphysMask should be set to 1 */ + /* FIXME: It only support 4G less range */ + msr_t basem, maskm; + + if (type == MTRR_TYPE_WRBACK && !is_cache_sets_power_of_two() && ENV_CACHE_AS_RAM) + printk(BIOS_ERR, "MTRR Error: Type %x may not be supported due to NEM limitation\n", + type); + if (!IS_POWER_OF_2(size)) + printk(BIOS_ERR, "MTRR Error: size %#x is not a power of two\n", size); + if (size < 4 * KiB) + printk(BIOS_ERR, "MTRR Error: size %#x smaller than 4KiB\n", size); + if (base % size != 0) + printk(BIOS_ERR, "MTRR Error: base %#x must be aligned to size %#x\n", base, + size); + + basem.lo = base | type; + basem.hi = 0; + wrmsr(MTRR_PHYS_BASE(index), basem); + maskm.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID; + maskm.hi = (1 << (cpu_phys_address_size() - 32)) - 1; + wrmsr(MTRR_PHYS_MASK(index), maskm); +} + +/* Disables the variable MTRR at the given index by clearing its base and mask MSRs. */ +void clear_var_mtrr(int index) +{ + msr_t msr = { .lo = 0, .hi = 0 }; + + wrmsr(MTRR_PHYS_BASE(index), msr); + wrmsr(MTRR_PHYS_MASK(index), msr); +} + +/* + * Acquires a free variable MTRR, configures it with the given base, size, and type. + * Returns the MTRR index if successful (>=0), or an error code (<0) if acquisition failed. + */ +int acquire_and_configure_mtrr(unsigned int base, unsigned int size, unsigned int type) +{ + int index = get_free_var_mtrr(); + + if (index >= 0) + set_var_mtrr(index, base, size, type); + + return index; +} diff --git a/src/include/cpu/x86/mtrr.h b/src/include/cpu/x86/mtrr.h index 930edfdef7..87aee95c67 100644 --- a/src/include/cpu/x86/mtrr.h +++ b/src/include/cpu/x86/mtrr.h @@ -124,9 +124,11 @@ static inline int get_var_mtrr_count(void) return rdmsr(MTRR_CAP_MSR).lo & MTRR_CAP_VCNT; } -void set_var_mtrr(unsigned int reg, unsigned int base, unsigned int size, +int acquire_and_configure_mtrr(unsigned int base, unsigned int size, unsigned int type); +void set_var_mtrr(unsigned int index, unsigned int base, unsigned int size, unsigned int type); int get_free_var_mtrr(void); +void clear_var_mtrr(int index); void clear_all_var_mtrr(void); asmlinkage void display_mtrrs(void);