diff options
Diffstat (limited to 'src/cpu/x86')
-rw-r--r-- | src/cpu/x86/Kconfig | 5 | ||||
-rw-r--r-- | src/cpu/x86/mtrr/mtrr.c | 59 |
2 files changed, 63 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); |