diff options
author | Simon Glass <sjg@chromium.org> | 2015-01-01 23:18:07 (GMT) |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2015-01-13 15:25:00 (GMT) |
commit | aff2523f6998dca1f667aa0d26cc8f351c5628dc (patch) | |
tree | ae1694272e3fd7124f83e2a5730755943d041dbd /arch/x86/cpu/mtrr.c | |
parent | 3a5659f7cfc0fd99b57fe2ed9e4a9ebde7cf8491 (diff) | |
download | u-boot-aff2523f6998dca1f667aa0d26cc8f351c5628dc.tar.xz |
x86: Add support for MTRRs
Memory Type Range Registers are used to tell the CPU whether memory is
cacheable and if so the cache write mode to use.
Clean up the existing header file to follow style, and remove the unneeded
code.
These can speed up booting so should be supported. Add these to global_data
so they can be requested while booting. We will apply the changes during
relocation (in a later commit).
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86/cpu/mtrr.c')
-rw-r--r-- | arch/x86/cpu/mtrr.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c new file mode 100644 index 0000000..d5a825d --- /dev/null +++ b/arch/x86/cpu/mtrr.c @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Memory Type Range Regsters - these are used to tell the CPU whether + * memory is cacheable and if so the cache write mode to use. + * + * These can speed up booting. See the mtrr command. + * + * Reference: Intel Architecture Software Developer's Manual, Volume 3: + * System Programming + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/msr.h> +#include <asm/mtrr.h> + +/* Prepare to adjust MTRRs */ +void mtrr_open(struct mtrr_state *state) +{ + state->enable_cache = dcache_status(); + + if (state->enable_cache) + disable_caches(); + state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); + wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); +} + +/* Clean up after adjusting MTRRs, and enable them */ +void mtrr_close(struct mtrr_state *state) +{ + wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); + if (state->enable_cache) + enable_caches(); +} + +int mtrr_commit(bool do_caches) +{ + struct mtrr_request *req = gd->arch.mtrr_req; + struct mtrr_state state; + uint64_t mask; + int i; + + mtrr_open(&state); + for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { + mask = ~(req->size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type); + wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID); + } + + /* Clear the ones that are unused */ + for (; i < MTRR_COUNT; i++) + wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); + mtrr_close(&state); + + return 0; +} + +int mtrr_add_request(int type, uint64_t start, uint64_t size) +{ + struct mtrr_request *req; + uint64_t mask; + + if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS) + return -ENOSPC; + req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++]; + req->type = type; + req->start = start; + req->size = size; + debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1, + req->type, req->start, req->size); + mask = ~(req->size - 1); + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; + mask |= MTRR_PHYS_MASK_VALID; + debug(" %016llx %016llx\n", req->start | req->type, mask); + + return 0; +} |