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