x86: Update mtrr functions to allow leaving cache alone

At present the mtrr functions disable the cache before making changes and
enable it again afterwards. This is fine in U-Boot, but does not work if
running in CAR (such as we are in SPL).

Update the functions so that the caller can request that caches be left
alone.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
lime2-spi
Simon Glass 6 years ago
parent 6f1c0430e8
commit 590cee8315
  1. 4
      arch/x86/cpu/coreboot/coreboot.c
  2. 31
      arch/x86/cpu/mtrr.c
  3. 6
      arch/x86/include/asm/mtrr.h
  4. 8
      cmd/x86/mtrr.c

@ -55,10 +55,10 @@ static void board_final_cleanup(void)
if (top_type == MTRR_TYPE_WRPROT) { if (top_type == MTRR_TYPE_WRPROT) {
struct mtrr_state state; struct mtrr_state state;
mtrr_open(&state); mtrr_open(&state, true);
wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0); wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0);
wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0); wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0);
mtrr_close(&state); mtrr_close(&state, true);
} }
if (!fdtdec_get_config_bool(gd->fdt_blob, "u-boot,no-apm-finalize")) { if (!fdtdec_get_config_bool(gd->fdt_blob, "u-boot,no-apm-finalize")) {

@ -11,6 +11,11 @@
* System Programming * System Programming
*/ */
/*
* Note that any console output (e.g. debug()) in this file will likely fail
* since the MTRR registers are sometimes in flux.
*/
#include <common.h> #include <common.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/msr.h> #include <asm/msr.h>
@ -19,27 +24,29 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
/* Prepare to adjust MTRRs */ /* Prepare to adjust MTRRs */
void mtrr_open(struct mtrr_state *state) void mtrr_open(struct mtrr_state *state, bool do_caches)
{ {
if (!gd->arch.has_mtrr) if (!gd->arch.has_mtrr)
return; return;
state->enable_cache = dcache_status(); if (do_caches) {
state->enable_cache = dcache_status();
if (state->enable_cache) if (state->enable_cache)
disable_caches(); disable_caches();
}
state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
} }
/* Clean up after adjusting MTRRs, and enable them */ /* Clean up after adjusting MTRRs, and enable them */
void mtrr_close(struct mtrr_state *state) void mtrr_close(struct mtrr_state *state, bool do_caches)
{ {
if (!gd->arch.has_mtrr) if (!gd->arch.has_mtrr)
return; return;
wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
if (state->enable_cache) if (do_caches && state->enable_cache)
enable_caches(); enable_caches();
} }
@ -50,10 +57,14 @@ int mtrr_commit(bool do_caches)
uint64_t mask; uint64_t mask;
int i; int i;
debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr,
gd->arch.mtrr_req_count);
if (!gd->arch.has_mtrr) if (!gd->arch.has_mtrr)
return -ENOSYS; return -ENOSYS;
mtrr_open(&state); debug("open\n");
mtrr_open(&state, do_caches);
debug("open done\n");
for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
mask = ~(req->size - 1); mask = ~(req->size - 1);
mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
@ -62,9 +73,12 @@ int mtrr_commit(bool do_caches)
} }
/* Clear the ones that are unused */ /* Clear the ones that are unused */
debug("clear\n");
for (; i < MTRR_COUNT; i++) for (; i < MTRR_COUNT; i++)
wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
mtrr_close(&state); debug("close\n");
mtrr_close(&state, do_caches);
debug("mtrr done\n");
return 0; return 0;
} }
@ -74,6 +88,7 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size)
struct mtrr_request *req; struct mtrr_request *req;
uint64_t mask; uint64_t mask;
debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
if (!gd->arch.has_mtrr) if (!gd->arch.has_mtrr)
return -ENOSYS; return -ENOSYS;

@ -77,8 +77,9 @@ struct mtrr_state {
* possibly the cache. * possibly the cache.
* *
* @state: Empty structure to pass in to hold settings * @state: Empty structure to pass in to hold settings
* @do_caches: true to disable caches before opening
*/ */
void mtrr_open(struct mtrr_state *state); void mtrr_open(struct mtrr_state *state, bool do_caches);
/** /**
* mtrr_open() - Clean up after adjusting MTRRs, and enable them * mtrr_open() - Clean up after adjusting MTRRs, and enable them
@ -86,8 +87,9 @@ void mtrr_open(struct mtrr_state *state);
* This uses the structure containing information returned from mtrr_open(). * This uses the structure containing information returned from mtrr_open().
* *
* @state: Structure from mtrr_open() * @state: Structure from mtrr_open()
* @state: true to restore cache state to that before mtrr_open()
*/ */
void mtrr_close(struct mtrr_state *state); void mtrr_close(struct mtrr_state *state, bool do_caches);
/** /**
* mtrr_add_request() - Add a new MTRR request * mtrr_add_request() - Add a new MTRR request

@ -73,10 +73,10 @@ static int do_mtrr_set(uint reg, int argc, char * const argv[])
mask |= MTRR_PHYS_MASK_VALID; mask |= MTRR_PHYS_MASK_VALID;
printf("base=%llx, mask=%llx\n", base, mask); printf("base=%llx, mask=%llx\n", base, mask);
mtrr_open(&state); mtrr_open(&state, true);
wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
mtrr_close(&state); mtrr_close(&state, true);
return 0; return 0;
} }
@ -86,14 +86,14 @@ static int mtrr_set_valid(int reg, bool valid)
struct mtrr_state state; struct mtrr_state state;
uint64_t mask; uint64_t mask;
mtrr_open(&state); mtrr_open(&state, true);
mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
if (valid) if (valid)
mask |= MTRR_PHYS_MASK_VALID; mask |= MTRR_PHYS_MASK_VALID;
else else
mask &= ~MTRR_PHYS_MASK_VALID; mask &= ~MTRR_PHYS_MASK_VALID;
wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
mtrr_close(&state); mtrr_close(&state, true);
return 0; return 0;
} }

Loading…
Cancel
Save