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:
Simon Glass 2019-04-25 21:58:42 -06:00 committed by Bin Meng
parent 7b14023880
commit c0069e9a8a
3 changed files with 91 additions and 41 deletions

View file

@ -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()) {
/* initialize FPU, reset EM, set MP and NE */
asm ("fninit\n" \ asm ("fninit\n" \
"movl %%cr0, %%eax\n" \ "movl %%cr0, %%eax\n" \
"andl %0, %%eax\n" \ "andl %0, %%eax\n" \
"orl %1, %%eax\n" \ "orl %1, %%eax\n" \
"movl %%eax, %%cr0\n" \ "movl %%eax, %%cr0\n" \
: : "i" (em_rst), "i" (mp_ne_set) : "eax"); : : "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,12 +340,21 @@ 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) {
@ -373,12 +383,27 @@ int x86_cpu_init_f(void)
/* 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 */
if (IS_ENABLED(CONFIG_I8254_TIMER))
i8254_init(); i8254_init();
#endif
return 0;
}
int x86_cpu_reinit_f(void)
{
setup_identity();
setup_pci_ram_top();
return 0; return 0;
} }

View file

@ -61,3 +61,8 @@ int print_cpuinfo(void)
{ {
return 0; return 0;
} }
int x86_cpu_reinit_f(void)
{
return 0;
}

View file

@ -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);
/* /*