On Fri, Jan 2, 2015 at 7:18 AM, Simon Glass <s...@chromium.org> wrote: > It is useful to be able to see the MTRR setup in U-Boot. Add a command > to list the state of the variable MTRR registers and allow them to be > changed. > > Update the documentation to list some of the available commands. > > This does not support fixed MTRRs as yet. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > Changes in v2: > - Move cmd_mtrr to arch/x86/lib > - Correct 'platform' typo > > arch/x86/lib/Makefile | 1 + > arch/x86/lib/cmd_mtrr.c | 138 > ++++++++++++++++++++++++++++++++++++++++++++++++ > doc/README.x86 | 18 ++++++- > 3 files changed, 156 insertions(+), 1 deletion(-) > create mode 100644 arch/x86/lib/cmd_mtrr.c > > diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile > index 73262d7..32d7b98 100644 > --- a/arch/x86/lib/Makefile > +++ b/arch/x86/lib/Makefile > @@ -14,6 +14,7 @@ obj-$(CONFIG_HAVE_FSP) += cmd_hob.o > obj-y += gcc.o > obj-y += init_helpers.o > obj-y += interrupts.o > +obj-y += cmd_mtrr.o > obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o > obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o > obj-$(CONFIG_PCI) += pci_type1.o > diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c > new file mode 100644 > index 0000000..7e0506b > --- /dev/null > +++ b/arch/x86/lib/cmd_mtrr.c > @@ -0,0 +1,138 @@ > +/* > + * (C) Copyright 2014 Google, Inc > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <asm/msr.h> > +#include <asm/mtrr.h> > + > +static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { > + "Uncacheable", > + "Combine", > + "2", > + "3", > + "Through", > + "Protect", > + "Back", > +}; > + > +static int do_mtrr_list(void) > +{ > + int i; > + > + printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", > + "Mask ||", "Size ||"); > + for (i = 0; i < MTRR_COUNT; i++) { > + const char *type = "Invalid"; > + uint64_t base, mask, size; > + bool valid; > + > + base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); > + mask = native_read_msr(MTRR_PHYS_MASK_MSR(i)); > + size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); > + size |= (1 << 12) - 1; > + size += 1; > + valid = mask & MTRR_PHYS_MASK_VALID; > + type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; > + printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, > + valid ? "Y" : "N", type, base, mask, size); > + } > + > + return 0; > +} > + > +static int do_mtrr_set(uint reg, int argc, char * const argv[]) > +{ > + const char *typename = argv[0]; > + struct mtrr_state state; > + uint32_t start, size; > + uint64_t base, mask; > + int i, type = -1; > + bool valid; > + > + if (argc < 3) > + return CMD_RET_USAGE; > + for (i = 0; i < MTRR_TYPE_COUNT; i++) { > + if (*typename == *mtrr_type_name[i]) > + type = i; > + } > + if (type == -1) { > + printf("Invalid type name %s\n", typename); > + return CMD_RET_USAGE; > + } > + start = simple_strtoul(argv[1], NULL, 16); > + size = simple_strtoul(argv[2], NULL, 16); > + > + base = start | type; > + valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & > MTRR_PHYS_MASK_VALID; > + mask = ~((uint64_t)size - 1); > + mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; > + if (valid) > + mask |= MTRR_PHYS_MASK_VALID; > + > + printf("base=%llx, mask=%llx\n", base, mask); > + mtrr_open(&state); > + wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); > + wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); > + mtrr_close(&state); > + > + return 0; > +} > + > +static int mtrr_set_valid(int reg, bool valid) > +{ > + struct mtrr_state state; > + uint64_t mask; > + > + mtrr_open(&state); > + mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); > + if (valid) > + mask |= MTRR_PHYS_MASK_VALID; > + else > + mask &= ~MTRR_PHYS_MASK_VALID; > + wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); > + mtrr_close(&state); > + > + return 0; > +} > + > +static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + const char *cmd; > + uint reg; > + > + cmd = argv[1]; > + if (argc < 2 || *cmd == 'l') > + return do_mtrr_list(); > + argc -= 2; > + argv += 2; > + if (argc <= 0) > + return CMD_RET_USAGE; > + reg = simple_strtoul(argv[0], NULL, 16); > + if (reg >= MTRR_COUNT) { > + printf("Invalid register number\n"); > + return CMD_RET_USAGE; > + } > + if (*cmd == 'e') > + return mtrr_set_valid(reg, true); > + else if (*cmd == 'd') > + return mtrr_set_valid(reg, false); > + else if (*cmd == 's') > + return do_mtrr_set(reg, argc - 1, argv + 1); > + else > + return CMD_RET_USAGE; > + > + return 0; > +} > + > +U_BOOT_CMD( > + mtrr, 6, 1, do_mtrr, > + "Use x86 memory type range registers (32-bit only)", > + "[list] - list current registers\n" > + "set <reg> <type> <start> <size> - set a register\n" > + "\t<type> is Uncacheable, Combine, Through, Protect, Back\n" > + "disable <reg> - disable a register\n" > + "ensable <reg> - enable a register" > +); > diff --git a/doc/README.x86 b/doc/README.x86 > index 5fab044..b474161 100644 > --- a/doc/README.x86 > +++ b/doc/README.x86 > @@ -110,9 +110,25 @@ be turned on. Not every device on the board is > configured via devie tree, but > more and more devices will be added as time goes by. Check out the directory > arch/x86/dts/ for these device tree source files. > > +Useful Commands > +--------------- > + > +In keeping with the U-Boot philosophy of providing functions to check and > +adjust internal settings, there are several x86-specific commands that may be > +useful: > + > +hob - Display information about Firmware Support Package (FSP) Hand-off > + Block. This is only available on platforms which use FSP, mostly > + Atom. > +iod - Display I/O memory > +iow - Write I/O memory > +mtrr - List and set the Memory Type Range Registers (MTRR). These are used to > + tell the CPU whether memory is cacheable and if so the cache write > + mode to use. U-Boot sets up some reasonable values but you can > + adjust then with this command. > + > TODO List > --------- > -- MTRR support (for performance) > - Audio > - Chrome OS verified boot > - SMI and ACPI support, to provide platform info and facilities to Linux > --
Tested-by: Bin Meng <bmeng...@gmail.com> _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot