]> git.neil.brown.name Git - history.git/commitdiff
Fix APIC address handling at bootup and restore.
authorLinus Torvalds <torvalds@home.osdl.org>
Wed, 15 Oct 2003 10:51:43 +0000 (03:51 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Wed, 15 Oct 2003 10:51:43 +0000 (03:51 -0700)
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)

arch/i386/kernel/apic.c

index 2639c2026700e11351f03f81e3da13ec0fcb13cb..97ac569c8b5ea5e92331674ab63210b9ad6e06e4 100644 (file)
@@ -533,14 +533,19 @@ static int lapic_resume(struct sys_device *dev)
        if (!apic_pm_state.active)
                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);
+
+       /*
+        * 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);
        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);
+
        apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
        apic_write(APIC_ID, apic_pm_state.apic_id);
        apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -680,6 +685,12 @@ static int __init detect_init_APIC (void)
        }
        set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
        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)
                nmi_watchdog = NMI_LOCAL_APIC;