1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2014 Google, Inc 4 */ 5 6#include <common.h> 7#include <command.h> 8#include <log.h> 9#include <asm/msr.h> 10#include <asm/mp.h> 11#include <asm/mtrr.h> 12 13static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[]) 14{ 15 const char *typename = argv[0]; 16 uint32_t start, size; 17 uint64_t base, mask; 18 int type = -1; 19 bool valid; 20 int ret; 21 22 if (argc < 3) 23 return CMD_RET_USAGE; 24 type = mtrr_get_type_by_name(typename); 25 if (type < 0) { 26 printf("Invalid type name %s\n", typename); 27 return CMD_RET_USAGE; 28 } 29 start = hextoul(argv[1], NULL); 30 size = hextoul(argv[2], NULL); 31 32 base = start | type; 33 valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID; 34 mask = ~((uint64_t)size - 1); 35 mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; 36 if (valid) 37 mask |= MTRR_PHYS_MASK_VALID; 38 39 ret = mtrr_set(cpu_select, reg, base, mask); 40 if (ret) 41 return CMD_RET_FAILURE; 42 43 return 0; 44} 45 46static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, 47 char *const argv[]) 48{ 49 int reg_count = mtrr_get_var_count(); 50 int cmd; 51 int cpu_select; 52 uint reg; 53 int ret; 54 55 cpu_select = MP_SELECT_BSP; 56 if (argc >= 3 && !strcmp("-c", argv[1])) { 57 const char *cpustr; 58 59 cpustr = argv[2]; 60 if (*cpustr == 'a') 61 cpu_select = MP_SELECT_ALL; 62 else 63 cpu_select = simple_strtol(cpustr, NULL, 16); 64 argc -= 2; 65 argv += 2; 66 } 67 argc--; 68 argv++; 69 cmd = argv[0] ? *argv[0] : 0; 70 if (argc < 1 || !cmd) { 71 cmd = 'l'; 72 reg = 0; 73 } 74 if (cmd != 'l') { 75 if (argc < 2) 76 return CMD_RET_USAGE; 77 reg = hextoul(argv[1], NULL); 78 if (reg >= reg_count) { 79 printf("Invalid register number\n"); 80 return CMD_RET_USAGE; 81 } 82 } 83 if (cmd == 'l') { 84 bool first; 85 int i; 86 87 i = mp_first_cpu(cpu_select); 88 if (i < 0) { 89 printf("Invalid CPU (err=%d)\n", i); 90 return CMD_RET_FAILURE; 91 } 92 first = true; 93 for (; i >= 0; i = mp_next_cpu(cpu_select, i)) { 94 if (!first) 95 printf("\n"); 96 printf("CPU %d:\n", i); 97 ret = mtrr_list(reg_count, i); 98 if (ret) { 99 printf("Failed to read CPU %s (err=%d)\n", 100 i < MP_SELECT_ALL ? simple_itoa(i) : "", 101 ret); 102 return CMD_RET_FAILURE; 103 } 104 first = false; 105 } 106 } else { 107 switch (cmd) { 108 case 'e': 109 ret = mtrr_set_valid(cpu_select, reg, true); 110 break; 111 case 'd': 112 ret = mtrr_set_valid(cpu_select, reg, false); 113 break; 114 case 's': 115 ret = do_mtrr_set(cpu_select, reg, argc - 2, argv + 2); 116 break; 117 default: 118 return CMD_RET_USAGE; 119 } 120 if (ret) { 121 printf("Operation failed (err=%d)\n", ret); 122 return CMD_RET_FAILURE; 123 } 124 } 125 126 return 0; 127} 128 129U_BOOT_CMD( 130 mtrr, 8, 1, do_mtrr, 131 "Use x86 memory type range registers (32-bit only)", 132 "[list] - list current registers\n" 133 "set <reg> <type> <start> <size> - set a register\n" 134 "\t<type> is Uncacheable, Combine, Through, Protect, Back\n" 135 "disable <reg> - disable a register\n" 136 "enable <reg> - enable a register\n" 137 "\n" 138 "Precede command with '-c <n>|all' to access a particular hex CPU, e.g.\n" 139 " mtrr -c all list; mtrr -c 2e list" 140); 141