xref: /openbmc/u-boot/cmd/x86/mtrr.c (revision 3d5ced9e22d32112a20f9dc0f5fb1f22ef088079)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28e18f34cSTom Rini /*
38e18f34cSTom Rini  * (C) Copyright 2014 Google, Inc
48e18f34cSTom Rini  */
58e18f34cSTom Rini 
68e18f34cSTom Rini #include <common.h>
78e18f34cSTom Rini #include <asm/msr.h>
88e18f34cSTom Rini #include <asm/mtrr.h>
98e18f34cSTom Rini 
108e18f34cSTom Rini static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
118e18f34cSTom Rini 	"Uncacheable",
128e18f34cSTom Rini 	"Combine",
138e18f34cSTom Rini 	"2",
148e18f34cSTom Rini 	"3",
158e18f34cSTom Rini 	"Through",
168e18f34cSTom Rini 	"Protect",
178e18f34cSTom Rini 	"Back",
188e18f34cSTom Rini };
198e18f34cSTom Rini 
do_mtrr_list(void)208e18f34cSTom Rini static int do_mtrr_list(void)
218e18f34cSTom Rini {
228e18f34cSTom Rini 	int i;
238e18f34cSTom Rini 
248e18f34cSTom Rini 	printf("Reg Valid Write-type   %-16s %-16s %-16s\n", "Base   ||",
258e18f34cSTom Rini 	       "Mask   ||", "Size   ||");
268e18f34cSTom Rini 	for (i = 0; i < MTRR_COUNT; i++) {
278e18f34cSTom Rini 		const char *type = "Invalid";
288e18f34cSTom Rini 		uint64_t base, mask, size;
298e18f34cSTom Rini 		bool valid;
308e18f34cSTom Rini 
318e18f34cSTom Rini 		base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
328e18f34cSTom Rini 		mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
338e18f34cSTom Rini 		size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
348e18f34cSTom Rini 		size |= (1 << 12) - 1;
358e18f34cSTom Rini 		size += 1;
368e18f34cSTom Rini 		valid = mask & MTRR_PHYS_MASK_VALID;
378e18f34cSTom Rini 		type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
388e18f34cSTom Rini 		printf("%d   %-5s %-12s %016llx %016llx %016llx\n", i,
398e18f34cSTom Rini 		       valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
408e18f34cSTom Rini 		       mask & ~MTRR_PHYS_MASK_VALID, size);
418e18f34cSTom Rini 	}
428e18f34cSTom Rini 
438e18f34cSTom Rini 	return 0;
448e18f34cSTom Rini }
458e18f34cSTom Rini 
do_mtrr_set(uint reg,int argc,char * const argv[])468e18f34cSTom Rini static int do_mtrr_set(uint reg, int argc, char * const argv[])
478e18f34cSTom Rini {
488e18f34cSTom Rini 	const char *typename = argv[0];
498e18f34cSTom Rini 	struct mtrr_state state;
508e18f34cSTom Rini 	uint32_t start, size;
518e18f34cSTom Rini 	uint64_t base, mask;
528e18f34cSTom Rini 	int i, type = -1;
538e18f34cSTom Rini 	bool valid;
548e18f34cSTom Rini 
558e18f34cSTom Rini 	if (argc < 3)
568e18f34cSTom Rini 		return CMD_RET_USAGE;
578e18f34cSTom Rini 	for (i = 0; i < MTRR_TYPE_COUNT; i++) {
588e18f34cSTom Rini 		if (*typename == *mtrr_type_name[i])
598e18f34cSTom Rini 			type = i;
608e18f34cSTom Rini 	}
618e18f34cSTom Rini 	if (type == -1) {
628e18f34cSTom Rini 		printf("Invalid type name %s\n", typename);
638e18f34cSTom Rini 		return CMD_RET_USAGE;
648e18f34cSTom Rini 	}
658e18f34cSTom Rini 	start = simple_strtoul(argv[1], NULL, 16);
668e18f34cSTom Rini 	size = simple_strtoul(argv[2], NULL, 16);
678e18f34cSTom Rini 
688e18f34cSTom Rini 	base = start | type;
698e18f34cSTom Rini 	valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
708e18f34cSTom Rini 	mask = ~((uint64_t)size - 1);
718e18f34cSTom Rini 	mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
728e18f34cSTom Rini 	if (valid)
738e18f34cSTom Rini 		mask |= MTRR_PHYS_MASK_VALID;
748e18f34cSTom Rini 
758e18f34cSTom Rini 	printf("base=%llx, mask=%llx\n", base, mask);
76*590cee83SSimon Glass 	mtrr_open(&state, true);
778e18f34cSTom Rini 	wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
788e18f34cSTom Rini 	wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
79*590cee83SSimon Glass 	mtrr_close(&state, true);
808e18f34cSTom Rini 
818e18f34cSTom Rini 	return 0;
828e18f34cSTom Rini }
838e18f34cSTom Rini 
mtrr_set_valid(int reg,bool valid)848e18f34cSTom Rini static int mtrr_set_valid(int reg, bool valid)
858e18f34cSTom Rini {
868e18f34cSTom Rini 	struct mtrr_state state;
878e18f34cSTom Rini 	uint64_t mask;
888e18f34cSTom Rini 
89*590cee83SSimon Glass 	mtrr_open(&state, true);
908e18f34cSTom Rini 	mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
918e18f34cSTom Rini 	if (valid)
928e18f34cSTom Rini 		mask |= MTRR_PHYS_MASK_VALID;
938e18f34cSTom Rini 	else
948e18f34cSTom Rini 		mask &= ~MTRR_PHYS_MASK_VALID;
958e18f34cSTom Rini 	wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
96*590cee83SSimon Glass 	mtrr_close(&state, true);
978e18f34cSTom Rini 
988e18f34cSTom Rini 	return 0;
998e18f34cSTom Rini }
1008e18f34cSTom Rini 
do_mtrr(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])1018e18f34cSTom Rini static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1028e18f34cSTom Rini {
1038e18f34cSTom Rini 	const char *cmd;
1048e18f34cSTom Rini 	uint reg;
1058e18f34cSTom Rini 
1068e18f34cSTom Rini 	cmd = argv[1];
1078e18f34cSTom Rini 	if (argc < 2 || *cmd == 'l')
1088e18f34cSTom Rini 		return do_mtrr_list();
1098e18f34cSTom Rini 	argc -= 2;
1108e18f34cSTom Rini 	argv += 2;
1118e18f34cSTom Rini 	if (argc <= 0)
1128e18f34cSTom Rini 		return CMD_RET_USAGE;
1138e18f34cSTom Rini 	reg = simple_strtoul(argv[0], NULL, 16);
1148e18f34cSTom Rini 	if (reg >= MTRR_COUNT) {
1158e18f34cSTom Rini 		printf("Invalid register number\n");
1168e18f34cSTom Rini 		return CMD_RET_USAGE;
1178e18f34cSTom Rini 	}
1188e18f34cSTom Rini 	if (*cmd == 'e')
1198e18f34cSTom Rini 		return mtrr_set_valid(reg, true);
1208e18f34cSTom Rini 	else if (*cmd == 'd')
1218e18f34cSTom Rini 		return mtrr_set_valid(reg, false);
1228e18f34cSTom Rini 	else if (*cmd == 's')
1238e18f34cSTom Rini 		return do_mtrr_set(reg, argc - 1, argv + 1);
1248e18f34cSTom Rini 	else
1258e18f34cSTom Rini 		return CMD_RET_USAGE;
1268e18f34cSTom Rini 
1278e18f34cSTom Rini 	return 0;
1288e18f34cSTom Rini }
1298e18f34cSTom Rini 
1308e18f34cSTom Rini U_BOOT_CMD(
1318e18f34cSTom Rini 	mtrr,	6,	1,	do_mtrr,
1328e18f34cSTom Rini 	"Use x86 memory type range registers (32-bit only)",
1338e18f34cSTom Rini 	"[list]        - list current registers\n"
1348e18f34cSTom Rini 	"set <reg> <type> <start> <size>   - set a register\n"
1358e18f34cSTom Rini 	"\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
1368e18f34cSTom Rini 	"disable <reg>      - disable a register\n"
1378e18f34cSTom Rini 	"ensable <reg>      - enable a register"
1388e18f34cSTom Rini );
139