mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 22:20:45 +00:00
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
3 changed files with 91 additions and 41 deletions
|
@ -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;
|
||||
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));
|
||||
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));
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -61,3 +61,8 @@ int print_cpuinfo(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x86_cpu_reinit_f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue