diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2023-08-08 15:03:49 -0700 |
---|---|---|
committer | Dave Hansen <dave.hansen@linux.intel.com> | 2023-08-09 11:58:20 -0700 |
commit | 81287ad65da5b82155f2eca03d81db5512802d16 (patch) | |
tree | 0f020ffbc7bea6caed86060b68ac63ed38a6b116 /arch/x86/kernel/apic/apic.c | |
parent | 5a88f354dcd8f19436bbda52f075276a5c70424f (diff) | |
download | linux-81287ad65da5b82155f2eca03d81db5512802d16.tar.gz linux-81287ad65da5b82155f2eca03d81db5512802d16.tar.bz2 linux-81287ad65da5b82155f2eca03d81db5512802d16.zip |
x86/apic: Sanitize APIC address setup
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)
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 29 |
1 files changed, 10 insertions, 19 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 45ae178b9e50..84ff5b27590b 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -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) |