x86: Add a way to reinit the cpu
We cannot init the CPU fully both than once during a boot. Add a new function which can be called to figure out the CPU identity, but which does not change anything. For x86_64, this is empty for now. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
		
							parent
							
								
									7b14023880
								
							
						
					
					
						commit
						c0069e9a8a
					
				|  | @ -309,21 +309,22 @@ u32 cpu_get_stepping(void) | ||||||
| 	return gd->arch.x86_mask; | 	return gd->arch.x86_mask; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int x86_cpu_init_f(void) | /* initialise FPU, reset EM, set MP and NE */ | ||||||
|  | static void setup_cpu_features(void) | ||||||
| { | { | ||||||
| 	const u32 em_rst = ~X86_CR0_EM; | 	const u32 em_rst = ~X86_CR0_EM; | ||||||
| 	const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; | 	const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; | ||||||
| 
 | 
 | ||||||
| 	if (ll_boot_init()) { | 	asm ("fninit\n" \ | ||||||
| 		/* initialize FPU, reset EM, set MP and NE */ | 	"movl %%cr0, %%eax\n" \ | ||||||
| 		asm ("fninit\n" \ | 	"andl %0, %%eax\n" \ | ||||||
| 		"movl %%cr0, %%eax\n" \ | 	"orl  %1, %%eax\n" \ | ||||||
| 		"andl %0, %%eax\n" \ | 	"movl %%eax, %%cr0\n" \ | ||||||
| 		"orl  %1, %%eax\n" \ | 	: : "i" (em_rst), "i" (mp_ne_set) : "eax"); | ||||||
| 		"movl %%eax, %%cr0\n" \ | } | ||||||
| 		: : "i" (em_rst), "i" (mp_ne_set) : "eax"); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
|  | static void setup_identity(void) | ||||||
|  | { | ||||||
| 	/* identify CPU via cpuid and store the decoded info into gd->arch */ | 	/* identify CPU via cpuid and store the decoded info into gd->arch */ | ||||||
| 	if (has_cpuid()) { | 	if (has_cpuid()) { | ||||||
| 		struct cpu_device_id cpu; | 		struct cpu_device_id cpu; | ||||||
|  | @ -339,46 +340,70 @@ int x86_cpu_init_f(void) | ||||||
| 
 | 
 | ||||||
| 		gd->arch.has_mtrr = has_mtrr(); | 		gd->arch.has_mtrr = has_mtrr(); | ||||||
| 	} | 	} | ||||||
| 	/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ | } | ||||||
|  | 
 | ||||||
|  | /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ | ||||||
|  | static void setup_pci_ram_top(void) | ||||||
|  | { | ||||||
| 	gd->pci_ram_top = 0x80000000U; | 	gd->pci_ram_top = 0x80000000U; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void setup_mtrr(void) | ||||||
|  | { | ||||||
|  | 	u64 mtrr_cap; | ||||||
| 
 | 
 | ||||||
| 	/* Configure fixed range MTRRs for some legacy regions */ | 	/* Configure fixed range MTRRs for some legacy regions */ | ||||||
| 	if (gd->arch.has_mtrr) { | 	if (!gd->arch.has_mtrr) | ||||||
| 		u64 mtrr_cap; | 		return; | ||||||
| 
 | 
 | ||||||
| 		mtrr_cap = native_read_msr(MTRR_CAP_MSR); | 	mtrr_cap = native_read_msr(MTRR_CAP_MSR); | ||||||
| 		if (mtrr_cap & MTRR_CAP_FIX) { | 	if (mtrr_cap & MTRR_CAP_FIX) { | ||||||
| 			/* Mark the VGA RAM area as uncacheable */ | 		/* Mark the VGA RAM area as uncacheable */ | ||||||
| 			native_write_msr(MTRR_FIX_16K_A0000_MSR, | 		native_write_msr(MTRR_FIX_16K_A0000_MSR, | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), | 				 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); | 				 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); | ||||||
| 
 | 
 | ||||||
| 			/*
 | 		/*
 | ||||||
| 			 * Mark the PCI ROM area as cacheable to improve ROM | 		 * Mark the PCI ROM area as cacheable to improve ROM | ||||||
| 			 * execution performance. | 		 * execution performance. | ||||||
| 			 */ | 		 */ | ||||||
| 			native_write_msr(MTRR_FIX_4K_C0000_MSR, | 		native_write_msr(MTRR_FIX_4K_C0000_MSR, | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | ||||||
| 			native_write_msr(MTRR_FIX_4K_C8000_MSR, | 		native_write_msr(MTRR_FIX_4K_C8000_MSR, | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | ||||||
| 			native_write_msr(MTRR_FIX_4K_D0000_MSR, | 		native_write_msr(MTRR_FIX_4K_D0000_MSR, | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | ||||||
| 			native_write_msr(MTRR_FIX_4K_D8000_MSR, | 		native_write_msr(MTRR_FIX_4K_D8000_MSR, | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), | ||||||
| 					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | 				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); | ||||||
| 
 | 
 | ||||||
| 			/* Enable the fixed range MTRRs */ | 		/* Enable the fixed range MTRRs */ | ||||||
| 			msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); | 		msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int x86_cpu_init_f(void) | ||||||
|  | { | ||||||
|  | 	if (ll_boot_init()) | ||||||
|  | 		setup_cpu_features(); | ||||||
|  | 	setup_identity(); | ||||||
|  | 	setup_mtrr(); | ||||||
|  | 	setup_pci_ram_top(); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_I8254_TIMER |  | ||||||
| 	/* Set up the i8254 timer if required */ | 	/* Set up the i8254 timer if required */ | ||||||
| 	i8254_init(); | 	if (IS_ENABLED(CONFIG_I8254_TIMER)) | ||||||
| #endif | 		i8254_init(); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int x86_cpu_reinit_f(void) | ||||||
|  | { | ||||||
|  | 	setup_identity(); | ||||||
|  | 	setup_pci_ram_top(); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -61,3 +61,8 @@ int print_cpuinfo(void) | ||||||
| { | { | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | int x86_cpu_reinit_f(void) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -13,7 +13,27 @@ extern char gdt_rom[]; | ||||||
| 
 | 
 | ||||||
| /* cpu/.../cpu.c */ | /* cpu/.../cpu.c */ | ||||||
| int arch_cpu_init(void); | int arch_cpu_init(void); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * x86_cpu_init_f() - Set up basic features of the x86 CPU | ||||||
|  |  * | ||||||
|  |  * 0 on success, -ve on error | ||||||
|  |  */ | ||||||
| int x86_cpu_init_f(void); | int x86_cpu_init_f(void); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * x86_cpu_reinit_f() - Set up the CPU a second time | ||||||
|  |  * | ||||||
|  |  * Once cpu_init_f() has been called (e.g. in SPL) we should not call it | ||||||
|  |  * again (e.g. in U-Boot proper) since it sets up the state from scratch. | ||||||
|  |  * Call this function in later phases of U-Boot instead. It reads the CPU | ||||||
|  |  * identify so that CPU functions can be used correctly, but does not change | ||||||
|  |  * anything. | ||||||
|  |  * | ||||||
|  |  * @return 0 (indicating success, to mimic cpu_init_f()) | ||||||
|  |  */ | ||||||
|  | int x86_cpu_reinit_f(void); | ||||||
|  | 
 | ||||||
| int cpu_init_f(void); | int cpu_init_f(void); | ||||||
| void setup_gdt(struct global_data *id, u64 *gdt_addr); | void setup_gdt(struct global_data *id, u64 *gdt_addr); | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue