Commit 535a8a4c authored by Linus Torvalds's avatar Linus Torvalds

Fix APIC address handling at bootup and restore.

Don't assume the APIC is at the power-on default address,
since the BIOS can have moved it somewhere else without
really ever telling us (ie we have an MP table or ACPI
that fixes it for us, but those are not always available)
parent 0b2b5576
...@@ -533,14 +533,19 @@ static int lapic_resume(struct sys_device *dev) ...@@ -533,14 +533,19 @@ static int lapic_resume(struct sys_device *dev)
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
/* XXX: Pavel needs this for S3 resume, but can't explain why */
set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
local_irq_save(flags); local_irq_save(flags);
/*
* Make sure the APICBASE points to the right address
*
* FIXME! This will be wrong if we ever support suspend on
* SMP! We'll need to do this as part of the CPU restore!
*/
rdmsr(MSR_IA32_APICBASE, l, h); rdmsr(MSR_IA32_APICBASE, l, h);
l &= ~MSR_IA32_APICBASE_BASE; l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
wrmsr(MSR_IA32_APICBASE, l, h); wrmsr(MSR_IA32_APICBASE, l, h);
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id); apic_write(APIC_ID, apic_pm_state.apic_id);
apic_write(APIC_DFR, apic_pm_state.apic_dfr); apic_write(APIC_DFR, apic_pm_state.apic_dfr);
...@@ -680,6 +685,12 @@ static int __init detect_init_APIC (void) ...@@ -680,6 +685,12 @@ static int __init detect_init_APIC (void)
} }
set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; 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;
if (nmi_watchdog != NMI_NONE) if (nmi_watchdog != NMI_NONE)
nmi_watchdog = NMI_LOCAL_APIC; nmi_watchdog = NMI_LOCAL_APIC;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment