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>
This commit is contained in:
		
							parent
							
								
									51af144eb7
								
							
						
					
					
						commit
						29d2d64ed5
					
				|  | @ -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) | void mtrr_read_all(struct mtrr_info *info) | ||||||
| { | { | ||||||
|  | 	int reg_count = mtrr_get_var_count(); | ||||||
| 	int i; | 	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].base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); | ||||||
| 		info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_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) | void mtrr_write_all(struct mtrr_info *info) | ||||||
| { | { | ||||||
|  | 	int reg_count = mtrr_get_var_count(); | ||||||
| 	struct mtrr_state state; | 	struct mtrr_state state; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < MTRR_COUNT; i++) { | 	for (i = 0; i < reg_count; i++) { | ||||||
| 		mtrr_open(&state, true); | 		mtrr_open(&state, true); | ||||||
| 		wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base); | 		wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base); | ||||||
| 		wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask); | 		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 */ | 	/* Clear the ones that are unused */ | ||||||
| 	debug("clear\n"); | 	debug("clear\n"); | ||||||
| 	for (; i < MTRR_COUNT; i++) | 	for (; i < MTRR_MAX_COUNT; i++) | ||||||
| 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); | 		wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); | ||||||
| 	debug("close\n"); | 	debug("close\n"); | ||||||
| 	mtrr_close(&state, do_caches); | 	mtrr_close(&state, do_caches); | ||||||
|  | @ -196,7 +198,7 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size) | ||||||
| 	return 0; | 	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; | 	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 vcnt; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	vcnt = get_var_mtrr_count(); | 	vcnt = mtrr_get_var_count(); | ||||||
| 
 | 
 | ||||||
| 	/* Identify the first var mtrr which is not valid */ | 	/* Identify the first var mtrr which is not valid */ | ||||||
| 	for (i = 0; i < vcnt; i++) { | 	for (i = 0; i < vcnt; i++) { | ||||||
|  |  | ||||||
|  | @ -36,8 +36,8 @@ | ||||||
| 
 | 
 | ||||||
| #define MTRR_BASE_TYPE_MASK	0x7 | #define MTRR_BASE_TYPE_MASK	0x7 | ||||||
| 
 | 
 | ||||||
| /* Number of MTRRs supported */ | /* Maximum number of MTRRs supported - see also mtrr_get_var_count() */ | ||||||
| #define MTRR_COUNT		8 | #define MTRR_MAX_COUNT		10 | ||||||
| 
 | 
 | ||||||
| #define NUM_FIXED_MTRRS		11 | #define NUM_FIXED_MTRRS		11 | ||||||
| #define RANGES_PER_FIXED_MTRR	8 | #define RANGES_PER_FIXED_MTRR	8 | ||||||
|  | @ -87,7 +87,7 @@ struct mtrr { | ||||||
|  * @mtrr: Information about each mtrr |  * @mtrr: Information about each mtrr | ||||||
|  */ |  */ | ||||||
| struct mtrr_info { | 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); | 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 | #endif | ||||||
| 
 | 
 | ||||||
| #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) | #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ static void read_mtrrs(void *arg) | ||||||
| 	mtrr_read_all(info); | 	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; | 	struct mtrr_info info; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -39,7 +39,7 @@ static int do_mtrr_list(int cpu_select) | ||||||
| 	ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info); | 	ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return log_msg_ret("run", 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"; | 		const char *type = "Invalid"; | ||||||
| 		uint64_t base, mask, size; | 		uint64_t base, mask, size; | ||||||
| 		bool valid; | 		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, | static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, | ||||||
| 		   char *const argv[]) | 		   char *const argv[]) | ||||||
| { | { | ||||||
|  | 	int reg_count = mtrr_get_var_count(); | ||||||
| 	int cmd; | 	int cmd; | ||||||
| 	int cpu_select; | 	int cpu_select; | ||||||
| 	uint reg; | 	uint reg; | ||||||
|  | @ -126,7 +127,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, | ||||||
| 		if (argc < 2) | 		if (argc < 2) | ||||||
| 			return CMD_RET_USAGE; | 			return CMD_RET_USAGE; | ||||||
| 		reg = simple_strtoul(argv[1], NULL, 16); | 		reg = simple_strtoul(argv[1], NULL, 16); | ||||||
| 		if (reg >= MTRR_COUNT) { | 		if (reg >= reg_count) { | ||||||
| 			printf("Invalid register number\n"); | 			printf("Invalid register number\n"); | ||||||
| 			return CMD_RET_USAGE; | 			return CMD_RET_USAGE; | ||||||
| 		} | 		} | ||||||
|  | @ -145,7 +146,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, | ||||||
| 			if (!first) | 			if (!first) | ||||||
| 				printf("\n"); | 				printf("\n"); | ||||||
| 			printf("CPU %d:\n", i); | 			printf("CPU %d:\n", i); | ||||||
| 			ret = do_mtrr_list(i); | 			ret = do_mtrr_list(reg_count, i); | ||||||
| 			if (ret) { | 			if (ret) { | ||||||
| 				printf("Failed to read CPU %d (err=%d)\n", i, | 				printf("Failed to read CPU %d (err=%d)\n", i, | ||||||
| 				       ret); | 				       ret); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue