1 /* 2 * (C) Copyright 2014 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/msr.h> 9 #include <asm/mtrr.h> 10 11 static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { 12 "Uncacheable", 13 "Combine", 14 "2", 15 "3", 16 "Through", 17 "Protect", 18 "Back", 19 }; 20 21 static int do_mtrr_list(void) 22 { 23 int i; 24 25 printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", 26 "Mask ||", "Size ||"); 27 for (i = 0; i < MTRR_COUNT; i++) { 28 const char *type = "Invalid"; 29 uint64_t base, mask, size; 30 bool valid; 31 32 base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); 33 mask = native_read_msr(MTRR_PHYS_MASK_MSR(i)); 34 size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); 35 size |= (1 << 12) - 1; 36 size += 1; 37 valid = mask & MTRR_PHYS_MASK_VALID; 38 type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; 39 printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, 40 valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK, 41 mask & ~MTRR_PHYS_MASK_VALID, size); 42 } 43 44 return 0; 45 } 46 47 static int do_mtrr_set(uint reg, int argc, char * const argv[]) 48 { 49 const char *typename = argv[0]; 50 struct mtrr_state state; 51 uint32_t start, size; 52 uint64_t base, mask; 53 int i, type = -1; 54 bool valid; 55 56 if (argc < 3) 57 return CMD_RET_USAGE; 58 for (i = 0; i < MTRR_TYPE_COUNT; i++) { 59 if (*typename == *mtrr_type_name[i]) 60 type = i; 61 } 62 if (type == -1) { 63 printf("Invalid type name %s\n", typename); 64 return CMD_RET_USAGE; 65 } 66 start = simple_strtoul(argv[1], NULL, 16); 67 size = simple_strtoul(argv[2], NULL, 16); 68 69 base = start | type; 70 valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID; 71 mask = ~((uint64_t)size - 1); 72 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 73 if (valid) 74 mask |= MTRR_PHYS_MASK_VALID; 75 76 printf("base=%llx, mask=%llx\n", base, mask); 77 mtrr_open(&state); 78 wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); 79 wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); 80 mtrr_close(&state); 81 82 return 0; 83 } 84 85 static int mtrr_set_valid(int reg, bool valid) 86 { 87 struct mtrr_state state; 88 uint64_t mask; 89 90 mtrr_open(&state); 91 mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); 92 if (valid) 93 mask |= MTRR_PHYS_MASK_VALID; 94 else 95 mask &= ~MTRR_PHYS_MASK_VALID; 96 wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); 97 mtrr_close(&state); 98 99 return 0; 100 } 101 102 static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 103 { 104 const char *cmd; 105 uint reg; 106 107 cmd = argv[1]; 108 if (argc < 2 || *cmd == 'l') 109 return do_mtrr_list(); 110 argc -= 2; 111 argv += 2; 112 if (argc <= 0) 113 return CMD_RET_USAGE; 114 reg = simple_strtoul(argv[0], NULL, 16); 115 if (reg >= MTRR_COUNT) { 116 printf("Invalid register number\n"); 117 return CMD_RET_USAGE; 118 } 119 if (*cmd == 'e') 120 return mtrr_set_valid(reg, true); 121 else if (*cmd == 'd') 122 return mtrr_set_valid(reg, false); 123 else if (*cmd == 's') 124 return do_mtrr_set(reg, argc - 1, argv + 1); 125 else 126 return CMD_RET_USAGE; 127 128 return 0; 129 } 130 131 U_BOOT_CMD( 132 mtrr, 6, 1, do_mtrr, 133 "Use x86 memory type range registers (32-bit only)", 134 "[list] - list current registers\n" 135 "set <reg> <type> <start> <size> - set a register\n" 136 "\t<type> is Uncacheable, Combine, Through, Protect, Back\n" 137 "disable <reg> - disable a register\n" 138 "ensable <reg> - enable a register" 139 ); 140