[U-Boot] [PATCH v2 10/50] x86: Add a way to reinit the cpu

Simon Glass sjg at chromium.org
Fri Apr 26 03:58:42 UTC 2019


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 at chromium.org>
Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
---

Changes in v2: None

 arch/x86/cpu/i386/cpu.c           | 113 ++++++++++++++++++------------
 arch/x86/cpu/x86_64/cpu.c         |   5 ++
 arch/x86/include/asm/u-boot-x86.h |  20 ++++++
 3 files changed, 94 insertions(+), 44 deletions(-)

diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 3bde44ebf53..90b546e7410 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -309,21 +309,22 @@ u32 cpu_get_stepping(void)
 	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 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
 
-	if (ll_boot_init()) {
-		/* initialize FPU, reset EM, set MP and NE */
-		asm ("fninit\n" \
-		"movl %%cr0, %%eax\n" \
-		"andl %0, %%eax\n" \
-		"orl  %1, %%eax\n" \
-		"movl %%eax, %%cr0\n" \
-		: : "i" (em_rst), "i" (mp_ne_set) : "eax");
-	}
+	asm ("fninit\n" \
+	"movl %%cr0, %%eax\n" \
+	"andl %0, %%eax\n" \
+	"orl  %1, %%eax\n" \
+	"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 */
 	if (has_cpuid()) {
 		struct cpu_device_id cpu;
@@ -339,46 +340,70 @@ int x86_cpu_init_f(void)
 
 		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;
+}
+
+static void setup_mtrr(void)
+{
+	u64 mtrr_cap;
 
 	/* Configure fixed range MTRRs for some legacy regions */
-	if (gd->arch.has_mtrr) {
-		u64 mtrr_cap;
-
-		mtrr_cap = native_read_msr(MTRR_CAP_MSR);
-		if (mtrr_cap & MTRR_CAP_FIX) {
-			/* Mark the VGA RAM area as uncacheable */
-			native_write_msr(MTRR_FIX_16K_A0000_MSR,
-					 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
-					 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
-
-			/*
-			 * Mark the PCI ROM area as cacheable to improve ROM
-			 * execution performance.
-			 */
-			native_write_msr(MTRR_FIX_4K_C0000_MSR,
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-			native_write_msr(MTRR_FIX_4K_C8000_MSR,
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-			native_write_msr(MTRR_FIX_4K_D0000_MSR,
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-			native_write_msr(MTRR_FIX_4K_D8000_MSR,
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
-					 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
-
-			/* Enable the fixed range MTRRs */
-			msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
-		}
+	if (!gd->arch.has_mtrr)
+		return;
+
+	mtrr_cap = native_read_msr(MTRR_CAP_MSR);
+	if (mtrr_cap & MTRR_CAP_FIX) {
+		/* Mark the VGA RAM area as uncacheable */
+		native_write_msr(MTRR_FIX_16K_A0000_MSR,
+				 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
+				 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+
+		/*
+		 * Mark the PCI ROM area as cacheable to improve ROM
+		 * execution performance.
+		 */
+		native_write_msr(MTRR_FIX_4K_C0000_MSR,
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+		native_write_msr(MTRR_FIX_4K_C8000_MSR,
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+		native_write_msr(MTRR_FIX_4K_D0000_MSR,
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+		native_write_msr(MTRR_FIX_4K_D8000_MSR,
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+				 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+
+		/* Enable the fixed range MTRRs */
+		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 */
-	i8254_init();
-#endif
+	if (IS_ENABLED(CONFIG_I8254_TIMER))
+		i8254_init();
+
+	return 0;
+}
+
+int x86_cpu_reinit_f(void)
+{
+	setup_identity();
+	setup_pci_ram_top();
 
 	return 0;
 }
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c
index 6c063e82009..42abb23a9ed 100644
--- a/arch/x86/cpu/x86_64/cpu.c
+++ b/arch/x86/cpu/x86_64/cpu.c
@@ -61,3 +61,8 @@ int print_cpuinfo(void)
 {
 	return 0;
 }
+
+int x86_cpu_reinit_f(void)
+{
+	return 0;
+}
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 670fcdc0093..c252192bf41 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -13,7 +13,27 @@ extern char gdt_rom[];
 
 /* cpu/.../cpu.c */
 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);
+
+/**
+ * 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);
 void setup_gdt(struct global_data *id, u64 *gdt_addr);
 /*
-- 
2.21.0.593.g511ec345e18-goog



More information about the U-Boot mailing list