x86/apic: Sanitize APIC address setup
authorThomas Gleixner <tglx@linutronix.de>
Tue, 8 Aug 2023 22:03:49 +0000 (15:03 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 9 Aug 2023 18:58:20 +0000 (11:58 -0700)
Convert places which just write mp_lapic_addr and let them register the
local APIC address directly instead of relying on magic other code to do
so.

Add a WARN_ON() into register_lapic_address() which is raised when
register_lapic_address() is invoked more than once during boot.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Michael Kelley <mikelley@microsoft.com>
Tested-by: Sohil Mehta <sohil.mehta@intel.com>
Tested-by: Juergen Gross <jgross@suse.com> # Xen PV (dom0 and unpriv. guest)
arch/x86/include/asm/mpspec.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/mpparse.c

index 190d30685facb531c4831002a73515595f33b238..5d01bdee0186ec97d92f7ff3bdad5bf68d41a709 100644 (file)
@@ -41,7 +41,6 @@ extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 extern unsigned int boot_cpu_physical_apicid;
 extern u8 boot_cpu_apic_version;
-extern unsigned long mp_lapic_addr;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 extern int smp_found_config;
index 45ae178b9e50ea65f58c92d8e512119afed4ad80..84ff5b27590bb3a192e7e696f310729463b098b8 100644 (file)
@@ -172,7 +172,7 @@ static __init int setup_apicpmtimer(char *s)
 __setup("apicpmtimer", setup_apicpmtimer);
 #endif
 
-unsigned long mp_lapic_addr __ro_after_init;
+static unsigned long mp_lapic_addr __ro_after_init;
 bool apic_is_disabled __ro_after_init;
 /* Disable local APIC timer from the kernel commandline or via dmi quirk */
 static int disable_apic_timer __initdata;
@@ -2009,12 +2009,12 @@ static bool __init detect_init_APIC(void)
                return false;
        }
 
-       mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+       register_lapic_address(APIC_DEFAULT_PHYS_BASE);
        return true;
 }
 #else
 
-static bool __init apic_verify(void)
+static bool __init apic_verify(unsigned long addr)
 {
        u32 features, h, l;
 
@@ -2028,15 +2028,15 @@ static bool __init apic_verify(void)
                return false;
        }
        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 */
        if (boot_cpu_data.x86 >= 6) {
                rdmsr(MSR_IA32_APICBASE, l, h);
                if (l & MSR_IA32_APICBASE_ENABLE)
-                       mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+                       addr = l & MSR_IA32_APICBASE_BASE;
        }
 
+       register_lapic_address(addr);
        pr_info("Found and enabled local APIC!\n");
        return true;
 }
@@ -2063,7 +2063,7 @@ bool __init apic_force_enable(unsigned long addr)
                        enabled_via_apicbase = 1;
                }
        }
-       return apic_verify();
+       return apic_verify(addr);
 }
 
 /*
@@ -2105,7 +2105,7 @@ static bool __init detect_init_APIC(void)
                if (!apic_force_enable(APIC_DEFAULT_PHYS_BASE))
                        return false;
        } else {
-               if (!apic_verify())
+               if (!apic_verify(APIC_DEFAULT_PHYS_BASE))
                        return false;
        }
 
@@ -2130,27 +2130,16 @@ void __init init_apic_mappings(void)
        if (x2apic_mode)
                return;
 
-       /* If no local APIC can be found return early */
        if (!smp_found_config && !detect_init_APIC()) {
-               /* lets NOP'ify apic operations */
                pr_info("APIC: disable apic facility\n");
                apic_disable();
-       } else {
-               apic_phys = mp_lapic_addr;
-
-               /*
-                * If the system has ACPI MADT tables or MP info, the LAPIC
-                * address is already registered.
-                */
-               if (!acpi_lapic && !smp_found_config)
-                       register_lapic_address(apic_phys);
        }
 }
 
 static __init void apic_set_fixmap(void)
 {
        set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
-       apic_mmio_base = APIC_BASE;
+       apic_phys = apic_mmio_base = APIC_BASE;
        apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
                    apic_mmio_base, mp_lapic_addr);
        apic_read_boot_cpu_id(false);
@@ -2158,6 +2147,8 @@ static __init void apic_set_fixmap(void)
 
 void __init register_lapic_address(unsigned long address)
 {
+       /* This should only happen once */
+       WARN_ON_ONCE(mp_lapic_addr);
        mp_lapic_addr = address;
 
        if (!x2apic_mode)
index 333dee2cfbb8144e1b71dc318c0c975cfa32689a..b223922248e9f0af271a0fa69b19afb495b9840f 100644 (file)
@@ -374,11 +374,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
        int linttypes[2] = { mp_ExtINT, mp_NMI };
        int i;
 
-       /*
-        * local APIC has default address
-        */
-       mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-
        /*
         * 2 CPUs, numbered 0 & 1.
         */
@@ -520,10 +515,8 @@ void __init default_get_smp_config(unsigned int early)
         */
        if (mpf->feature1) {
                if (early) {
-                       /*
-                        * local APIC has default address
-                        */
-                       mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+                       /* Local APIC has default address */
+                       register_lapic_address(APIC_DEFAULT_PHYS_BASE);
                        goto out;
                }