x86: Allow platforms to force enable apic
Some embedded x86 platforms don't setup the APIC in the BIOS/bootloader and would be forced to add "lapic" on the kernel command line. That's a bit akward. Split out the force enable code from detect_init_APIC() and allow platform code to call it from the platform setup. That avoids the command line parameter and possible replication of the MSR dance in the force enable code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> LKML-Reference: <1287510389-8388-1-git-send-email-dirk.brandewie@gmail.com> Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
This commit is contained in:
@@ -238,6 +238,7 @@ extern void setup_boot_APIC_clock(void);
|
|||||||
extern void setup_secondary_APIC_clock(void);
|
extern void setup_secondary_APIC_clock(void);
|
||||||
extern int APIC_init_uniprocessor(void);
|
extern int APIC_init_uniprocessor(void);
|
||||||
extern void enable_NMI_through_LVT0(void);
|
extern void enable_NMI_through_LVT0(void);
|
||||||
|
extern int apic_force_enable(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On 32bit this is mach-xxx local
|
* On 32bit this is mach-xxx local
|
||||||
|
@@ -1531,13 +1531,60 @@ static int __init detect_init_APIC(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
static int apic_verify(void)
|
||||||
|
{
|
||||||
|
u32 features, h, l;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The APIC feature bit should now be enabled
|
||||||
|
* in `cpuid'
|
||||||
|
*/
|
||||||
|
features = cpuid_edx(1);
|
||||||
|
if (!(features & (1 << X86_FEATURE_APIC))) {
|
||||||
|
pr_warning("Could not enable APIC!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
|
||||||
|
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
|
||||||
|
|
||||||
|
/* The BIOS may have set up the APIC at some other address */
|
||||||
|
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||||
|
if (l & MSR_IA32_APICBASE_ENABLE)
|
||||||
|
mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
|
||||||
|
|
||||||
|
pr_info("Found and enabled local APIC!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int apic_force_enable(void)
|
||||||
|
{
|
||||||
|
u32 h, l;
|
||||||
|
|
||||||
|
if (disable_apic)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some BIOSes disable the local APIC in the APIC_BASE
|
||||||
|
* MSR. This can only be done in software for Intel P6 or later
|
||||||
|
* and AMD K7 (Model > 1) or later.
|
||||||
|
*/
|
||||||
|
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||||
|
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
|
||||||
|
pr_info("Local APIC disabled by BIOS -- reenabling.\n");
|
||||||
|
l &= ~MSR_IA32_APICBASE_BASE;
|
||||||
|
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
|
||||||
|
wrmsr(MSR_IA32_APICBASE, l, h);
|
||||||
|
enabled_via_apicbase = 1;
|
||||||
|
}
|
||||||
|
return apic_verify();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect and initialize APIC
|
* Detect and initialize APIC
|
||||||
*/
|
*/
|
||||||
static int __init detect_init_APIC(void)
|
static int __init detect_init_APIC(void)
|
||||||
{
|
{
|
||||||
u32 h, l, features;
|
|
||||||
|
|
||||||
/* Disabled by kernel option? */
|
/* Disabled by kernel option? */
|
||||||
if (disable_apic)
|
if (disable_apic)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1567,38 +1614,12 @@ static int __init detect_init_APIC(void)
|
|||||||
"you can enable it with \"lapic\"\n");
|
"you can enable it with \"lapic\"\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/*
|
if (apic_force_enable())
|
||||||
* Some BIOSes disable the local APIC in the APIC_BASE
|
return -1;
|
||||||
* MSR. This can only be done in software for Intel P6 or later
|
} else {
|
||||||
* and AMD K7 (Model > 1) or later.
|
if (apic_verify())
|
||||||
*/
|
|
||||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
|
||||||
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
|
|
||||||
pr_info("Local APIC disabled by BIOS -- reenabling.\n");
|
|
||||||
l &= ~MSR_IA32_APICBASE_BASE;
|
|
||||||
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
|
|
||||||
wrmsr(MSR_IA32_APICBASE, l, h);
|
|
||||||
enabled_via_apicbase = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* The APIC feature bit should now be enabled
|
|
||||||
* in `cpuid'
|
|
||||||
*/
|
|
||||||
features = cpuid_edx(1);
|
|
||||||
if (!(features & (1 << X86_FEATURE_APIC))) {
|
|
||||||
pr_warning("Could not enable APIC!\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
|
|
||||||
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
|
|
||||||
|
|
||||||
/* The BIOS may have set up the APIC at some other address */
|
|
||||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
|
||||||
if (l & MSR_IA32_APICBASE_ENABLE)
|
|
||||||
mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
|
|
||||||
|
|
||||||
pr_info("Found and enabled local APIC!\n");
|
|
||||||
|
|
||||||
apic_pm_activate();
|
apic_pm_activate();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user