cpu/x86/mtrr: Introduce mtrrlib with common MTRR helper functions
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 <subratabanik@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/87539 Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com> Reviewed-by: Shuo Liu <shuo.liu@intel.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nick Vaccaro <nvaccaro@google.com>
This commit is contained in:
parent
e180971560
commit
5f941893ef
5 changed files with 96 additions and 64 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,67 +7,14 @@
|
|||
#include <commonlib/bsd/helpers.h>
|
||||
#include <types.h>
|
||||
|
||||
/* 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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
85
src/cpu/x86/mtrr/mtrrlib.c
Normal file
85
src/cpu/x86/mtrr/mtrrlib.c
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <console/console.h>
|
||||
#include <commonlib/bsd/helpers.h>
|
||||
#include <types.h>
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue