Browse Source

x86: Add support for more than 8 MTRRs

At present the mtrr command only support 8 MTRRs. Some SoCs have more than
that. Update the implementation to support up to 10. Read the number of
MTRRs dynamically instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Simon Glass 3 years ago
parent
commit
29d2d64ed5
3 changed files with 24 additions and 12 deletions
  1. 7 5
      arch/x86/cpu/mtrr.c
  2. 12 3
      arch/x86/include/asm/mtrr.h
  3. 5 4
      cmd/x86/mtrr.c

+ 7 - 5
arch/x86/cpu/mtrr.c

@@ -67,9 +67,10 @@ static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
 
 void mtrr_read_all(struct mtrr_info *info)
 {
+	int reg_count = mtrr_get_var_count();
 	int i;
 
-	for (i = 0; i < MTRR_COUNT; i++) {
+	for (i = 0; i < reg_count; i++) {
 		info->mtrr[i].base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
 		info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
 	}
@@ -77,10 +78,11 @@ void mtrr_read_all(struct mtrr_info *info)
 
 void mtrr_write_all(struct mtrr_info *info)
 {
+	int reg_count = mtrr_get_var_count();
 	struct mtrr_state state;
 	int i;
 
-	for (i = 0; i < MTRR_COUNT; i++) {
+	for (i = 0; i < reg_count; i++) {
 		mtrr_open(&state, true);
 		wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base);
 		wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask);
@@ -156,7 +158,7 @@ int mtrr_commit(bool do_caches)
 
 	/* Clear the ones that are unused */
 	debug("clear\n");
-	for (; i < MTRR_COUNT; i++)
+	for (; i < MTRR_MAX_COUNT; i++)
 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
 	debug("close\n");
 	mtrr_close(&state, do_caches);
@@ -196,7 +198,7 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size)
 	return 0;
 }
 
-static int get_var_mtrr_count(void)
+int mtrr_get_var_count(void)
 {
 	return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT;
 }
@@ -207,7 +209,7 @@ static int get_free_var_mtrr(void)
 	int vcnt;
 	int i;
 
-	vcnt = get_var_mtrr_count();
+	vcnt = mtrr_get_var_count();
 
 	/* Identify the first var mtrr which is not valid */
 	for (i = 0; i < vcnt; i++) {

+ 12 - 3
arch/x86/include/asm/mtrr.h

@@ -36,8 +36,8 @@
 
 #define MTRR_BASE_TYPE_MASK	0x7
 
-/* Number of MTRRs supported */
-#define MTRR_COUNT		8
+/* Maximum number of MTRRs supported - see also mtrr_get_var_count() */
+#define MTRR_MAX_COUNT		10
 
 #define NUM_FIXED_MTRRS		11
 #define RANGES_PER_FIXED_MTRR	8
@@ -87,7 +87,7 @@ struct mtrr {
  * @mtrr: Information about each mtrr
  */
 struct mtrr_info {
-	struct mtrr mtrr[MTRR_COUNT];
+	struct mtrr mtrr[MTRR_MAX_COUNT];
 };
 
 /**
@@ -180,6 +180,15 @@ int mtrr_set_valid(int cpu_select, int reg, bool valid);
  */
 int mtrr_set(int cpu_select, int reg, u64 base, u64 mask);
 
+/**
+ * mtrr_get_var_count() - Get the number of variable MTRRs
+ *
+ * Some CPUs have more than 8 MTRRs. This function returns the actual number
+ *
+ * @return number of variable MTRRs
+ */
+int mtrr_get_var_count(void);
+
 #endif
 
 #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)

+ 5 - 4
cmd/x86/mtrr.c

@@ -27,7 +27,7 @@ static void read_mtrrs(void *arg)
 	mtrr_read_all(info);
 }
 
-static int do_mtrr_list(int cpu_select)
+static int do_mtrr_list(int reg_count, int cpu_select)
 {
 	struct mtrr_info info;
 	int ret;
@@ -39,7 +39,7 @@ static int do_mtrr_list(int cpu_select)
 	ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info);
 	if (ret)
 		return log_msg_ret("run", ret);
-	for (i = 0; i < MTRR_COUNT; i++) {
+	for (i = 0; i < reg_count; i++) {
 		const char *type = "Invalid";
 		uint64_t base, mask, size;
 		bool valid;
@@ -98,6 +98,7 @@ static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[])
 static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
 		   char *const argv[])
 {
+	int reg_count = mtrr_get_var_count();
 	int cmd;
 	int cpu_select;
 	uint reg;
@@ -126,7 +127,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
 		if (argc < 2)
 			return CMD_RET_USAGE;
 		reg = simple_strtoul(argv[1], NULL, 16);
-		if (reg >= MTRR_COUNT) {
+		if (reg >= reg_count) {
 			printf("Invalid register number\n");
 			return CMD_RET_USAGE;
 		}
@@ -145,7 +146,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
 			if (!first)
 				printf("\n");
 			printf("CPU %d:\n", i);
-			ret = do_mtrr_list(i);
+			ret = do_mtrr_list(reg_count, i);
 			if (ret) {
 				printf("Failed to read CPU %d (err=%d)\n", i,
 				       ret);