diff options
-rw-r--r-- | src/cpu/x86/Kconfig | 5 | ||||
-rw-r--r-- | src/cpu/x86/mtrr/mtrr.c | 59 | ||||
-rw-r--r-- | src/include/cpu/x86/mtrr.h | 16 |
3 files changed, 79 insertions, 1 deletions
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 8f05bf3b04..4c5176b693 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -56,8 +56,11 @@ config LOGICAL_CPUS default y config CACHE_ROM - bool + bool "Allow for caching system ROM." default n + help + When selected a variable range MTRR is allocated for coreboot and + the bootloader enables caching of the system ROM for faster access. config SMM_TSEG bool diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 74aae64a89..dad10292a9 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -163,6 +163,16 @@ static struct memranges *get_physical_address_space(void) memranges_add_resources(addr_space, mask, match, MTRR_TYPE_WRCOMB); +#if CONFIG_CACHE_ROM + /* Add a write-protect region covering the ROM size + * when CONFIG_CACHE_ROM is enabled. The ROM is assumed + * to be located at 4GiB - rom size. */ + resource_t rom_base = RANGE_TO_PHYS_ADDR( + RANGE_4GB - PHYS_TO_RANGE_ADDR(CONFIG_ROM_SIZE)); + memranges_insert(addr_space, rom_base, CONFIG_ROM_SIZE, + MTRR_TYPE_WRPROT); +#endif + /* The address space below 4GiB is special. It needs to be * covered entirly by range entries so that MTRR calculations * can be properly done for the full 32-bit address space. @@ -335,6 +345,44 @@ void x86_setup_fixed_mtrrs(void) enable_fixed_mtrr(); } +/* Keep track of the MTRR that covers the ROM for caching purposes. */ +#if CONFIG_CACHE_ROM +static long rom_cache_mtrr = -1; + +void x86_mtrr_enable_rom_caching(void) +{ + msr_t msr_val; + unsigned long index; + + if (rom_cache_mtrr < 0) + return; + + index = rom_cache_mtrr; + disable_cache(); + msr_val = rdmsr(MTRRphysBase_MSR(index)); + msr_val.lo &= ~0xff; + msr_val.lo |= MTRR_TYPE_WRPROT; + wrmsr(MTRRphysBase_MSR(index), msr_val); + enable_cache(); +} + +void x86_mtrr_disable_rom_caching(void) +{ + msr_t msr_val; + unsigned long index; + + if (rom_cache_mtrr < 0) + return; + + index = rom_cache_mtrr; + disable_cache(); + msr_val = rdmsr(MTRRphysBase_MSR(index)); + msr_val.lo &= ~0xff; + wrmsr(MTRRphysBase_MSR(index), msr_val); + enable_cache(); +} +#endif + struct var_mtrr_state { struct memranges *addr_space; int above4gb; @@ -382,6 +430,17 @@ static void write_var_mtrr(struct var_mtrr_state *var_state, mask = (1ULL << var_state->address_bits) - 1; rsize = rsize & mask; +#if CONFIG_CACHE_ROM + /* CONFIG_CACHE_ROM allocates an MTRR specifically for allowing + * one to turn on caching for faster ROM access. However, it is + * left to the MTRR callers to enable it. */ + if (mtrr_type == MTRR_TYPE_WRPROT) { + mtrr_type = MTRR_TYPE_UNCACHEABLE; + if (rom_cache_mtrr < 0) + rom_cache_mtrr = var_state->mtrr_index; + } +#endif + printk(BIOS_DEBUG, "MTRR: %d base 0x%016llx mask 0x%016llx type %d\n", var_state->mtrr_index, rbase, rsize, mtrr_type); diff --git a/src/include/cpu/x86/mtrr.h b/src/include/cpu/x86/mtrr.h index 618a93c44e..bff736d296 100644 --- a/src/include/cpu/x86/mtrr.h +++ b/src/include/cpu/x86/mtrr.h @@ -52,6 +52,10 @@ * of the nature of the global MTRR enable flag. Therefore, all direct * or indirect callers of enable_fixed_mtrr() should ensure that the * variable MTRR MSRs do not contain bad ranges. + * 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling + * the caching of the ROM. However, it is set to uncacheable (UC). It + * is the responsiblity of the caller to enable it by calling + * x86_mtrr_enable_rom_caching(). */ void x86_setup_mtrrs(void); /* @@ -67,6 +71,18 @@ void x86_setup_fixed_mtrrs(void); /* Set up fixed MTRRs but do not enable them. */ void x86_setup_fixed_mtrrs_no_enable(void); int x86_mtrr_check(void); +/* ROM caching can be used after variable MTRRs are set up. Beware that + * enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on + * one's IO hole size and WRCOMB resources. Be sure to check the console + * log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. */ +#if CONFIG_CACHE_ROM +void x86_mtrr_enable_rom_caching(void); +void x86_mtrr_disable_rom_caching(void); +#else +static inline void x86_mtrr_enable_rom_caching(void) {} +static inline void x86_mtrr_disable_rom_caching(void) {} +#endif /* CONFIG_CACHE_ROM */ + #endif #if !defined(CONFIG_RAMTOP) |