diff --git a/src/cpu/intel/slot_1/Kconfig b/src/cpu/intel/slot_1/Kconfig index cc24833fcf..c30e066444 100644 --- a/src/cpu/intel/slot_1/Kconfig +++ b/src/cpu/intel/slot_1/Kconfig @@ -17,6 +17,7 @@ config SLOT_SPECIFIC_OPTIONS select TSC_MONOTONIC_TIMER select UNKNOWN_TSC_RATE select SETUP_XIP_CACHE + select RESERVE_MTRRS_FOR_OS config DCACHE_RAM_BASE hex diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 5394cd023d..bcaf0bfad7 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -160,3 +160,13 @@ config SOC_SETS_MSRS help The SoC requires different access methods for reading and writing the MSRs. Use SoC specific routines to handle the MSR access. + +config RESERVE_MTRRS_FOR_OS + bool + default n + help + This option allows a platform to reserve 2 MTRRs for the OS usage. + The Intel SDM documents that the the first 6 MTRRs are intended for + the system BIOS and the last 2 are to be reserved for OS usage. + However, modern OSes use PAT to control cacheability instead of + using MTRRs. diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index cb7ecdc963..f1d36dac1d 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -28,10 +28,8 @@ #define MTRR_FIXED_WRBACK_BITS 0 #endif -/* 2 MTRRS are reserved for the operating system */ -#define BIOS_MTRRS 6 -#define OS_MTRRS 2 -#define MTRRS (BIOS_MTRRS + OS_MTRRS) +#define MIN_MTRRS 8 + /* * Static storage size for variable MTRRs. It's sized sufficiently large to * handle different types of CPUs. Empirically, 16 variable MTRRs has not @@ -39,8 +37,7 @@ */ #define NUM_MTRR_STATIC_STORAGE 16 -static int total_mtrrs = MTRRS; -static int bios_mtrrs = BIOS_MTRRS; +static int total_mtrrs; static void detect_var_mtrrs(void) { @@ -56,7 +53,6 @@ static void detect_var_mtrrs(void) total_mtrrs, NUM_MTRR_STATIC_STORAGE); total_mtrrs = NUM_MTRR_STATIC_STORAGE; } - bios_mtrrs = total_mtrrs - OS_MTRRS; } void enable_fixed_mtrr(void) @@ -399,6 +395,11 @@ static void clear_var_mtrr(int index) wrmsr(MTRR_PHYS_MASK(index), msr); } +static int get_os_reserved_mtrrs(void) +{ + return CONFIG(RESERVE_MTRRS_FOR_OS) ? 2 : 0; +} + static void prep_var_mtrr(struct var_mtrr_state *var_state, uint64_t base, uint64_t size, int mtrr_type) { @@ -407,17 +408,20 @@ static void prep_var_mtrr(struct var_mtrr_state *var_state, resource_t rsize; resource_t mask; - /* Some variable MTRRs are attempted to be saved for the OS use. - * However, it's more important to try to map the full address space - * properly. */ - if (var_state->mtrr_index >= bios_mtrrs) - printk(BIOS_WARNING, "Taking a reserved OS MTRR.\n"); if (var_state->mtrr_index >= total_mtrrs) { printk(BIOS_ERR, "ERROR: Not enough MTRRs available! MTRR index is %d with %d MTRRs in total.\n", var_state->mtrr_index, total_mtrrs); return; } + /* + * If desired, 2 variable MTRRs are attempted to be saved for the OS to + * use. However, it's more important to try to map the full address + * space properly. + */ + if (var_state->mtrr_index >= total_mtrrs - get_os_reserved_mtrrs()) + printk(BIOS_WARNING, "Taking a reserved OS MTRR.\n"); + rbase = base; rsize = size; @@ -710,6 +714,7 @@ static int calc_var_mtrrs(struct memranges *addr_space, __calc_var_mtrrs(addr_space, above4gb, address_bits, &wb_deftype_count, &uc_deftype_count); + const int bios_mtrrs = total_mtrrs - get_os_reserved_mtrrs(); if (wb_deftype_count > bios_mtrrs && uc_deftype_count > bios_mtrrs) { printk(BIOS_DEBUG, "MTRR: Removing WRCOMB type. " "WB/UC MTRR counts: %d/%d > %d.\n", @@ -813,6 +818,8 @@ static void _x86_setup_mtrrs(unsigned int above4gb) void x86_setup_mtrrs(void) { + /* Without detect, assume the minimum */ + total_mtrrs = MIN_MTRRS; /* Always handle addresses above 4GiB. */ _x86_setup_mtrrs(1); }