Commit 81287ad6 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Dave Hansen

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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: default avatarMichael Kelley <mikelley@microsoft.com>
Tested-by: default avatarSohil Mehta <sohil.mehta@intel.com>
Tested-by: Juergen Gross <jgross@suse.com> # Xen PV (dom0 and unpriv. guest)
parent 5a88f354
...@@ -41,7 +41,6 @@ extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES); ...@@ -41,7 +41,6 @@ extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
extern unsigned int boot_cpu_physical_apicid; extern unsigned int boot_cpu_physical_apicid;
extern u8 boot_cpu_apic_version; extern u8 boot_cpu_apic_version;
extern unsigned long mp_lapic_addr;
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
extern int smp_found_config; extern int smp_found_config;
......
...@@ -172,7 +172,7 @@ static __init int setup_apicpmtimer(char *s) ...@@ -172,7 +172,7 @@ static __init int setup_apicpmtimer(char *s)
__setup("apicpmtimer", setup_apicpmtimer); __setup("apicpmtimer", setup_apicpmtimer);
#endif #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; bool apic_is_disabled __ro_after_init;
/* Disable local APIC timer from the kernel commandline or via dmi quirk */ /* Disable local APIC timer from the kernel commandline or via dmi quirk */
static int disable_apic_timer __initdata; static int disable_apic_timer __initdata;
...@@ -2009,12 +2009,12 @@ static bool __init detect_init_APIC(void) ...@@ -2009,12 +2009,12 @@ static bool __init detect_init_APIC(void)
return false; return false;
} }
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; register_lapic_address(APIC_DEFAULT_PHYS_BASE);
return true; return true;
} }
#else #else
static bool __init apic_verify(void) static bool __init apic_verify(unsigned long addr)
{ {
u32 features, h, l; u32 features, h, l;
...@@ -2028,15 +2028,15 @@ static bool __init apic_verify(void) ...@@ -2028,15 +2028,15 @@ static bool __init apic_verify(void)
return false; return false;
} }
set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 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 */ /* The BIOS may have set up the APIC at some other address */
if (boot_cpu_data.x86 >= 6) { if (boot_cpu_data.x86 >= 6) {
rdmsr(MSR_IA32_APICBASE, l, h); rdmsr(MSR_IA32_APICBASE, l, h);
if (l & MSR_IA32_APICBASE_ENABLE) 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"); pr_info("Found and enabled local APIC!\n");
return true; return true;
} }
...@@ -2063,7 +2063,7 @@ bool __init apic_force_enable(unsigned long addr) ...@@ -2063,7 +2063,7 @@ bool __init apic_force_enable(unsigned long addr)
enabled_via_apicbase = 1; enabled_via_apicbase = 1;
} }
} }
return apic_verify(); return apic_verify(addr);
} }
/* /*
...@@ -2105,7 +2105,7 @@ static bool __init detect_init_APIC(void) ...@@ -2105,7 +2105,7 @@ static bool __init detect_init_APIC(void)
if (!apic_force_enable(APIC_DEFAULT_PHYS_BASE)) if (!apic_force_enable(APIC_DEFAULT_PHYS_BASE))
return false; return false;
} else { } else {
if (!apic_verify()) if (!apic_verify(APIC_DEFAULT_PHYS_BASE))
return false; return false;
} }
...@@ -2130,27 +2130,16 @@ void __init init_apic_mappings(void) ...@@ -2130,27 +2130,16 @@ void __init init_apic_mappings(void)
if (x2apic_mode) if (x2apic_mode)
return; return;
/* If no local APIC can be found return early */
if (!smp_found_config && !detect_init_APIC()) { if (!smp_found_config && !detect_init_APIC()) {
/* lets NOP'ify apic operations */
pr_info("APIC: disable apic facility\n"); pr_info("APIC: disable apic facility\n");
apic_disable(); 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) static __init void apic_set_fixmap(void)
{ {
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); 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_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
apic_mmio_base, mp_lapic_addr); apic_mmio_base, mp_lapic_addr);
apic_read_boot_cpu_id(false); apic_read_boot_cpu_id(false);
...@@ -2158,6 +2147,8 @@ static __init void apic_set_fixmap(void) ...@@ -2158,6 +2147,8 @@ static __init void apic_set_fixmap(void)
void __init register_lapic_address(unsigned long address) void __init register_lapic_address(unsigned long address)
{ {
/* This should only happen once */
WARN_ON_ONCE(mp_lapic_addr);
mp_lapic_addr = address; mp_lapic_addr = address;
if (!x2apic_mode) if (!x2apic_mode)
......
...@@ -374,11 +374,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) ...@@ -374,11 +374,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
int linttypes[2] = { mp_ExtINT, mp_NMI }; int linttypes[2] = { mp_ExtINT, mp_NMI };
int i; int i;
/*
* local APIC has default address
*/
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/* /*
* 2 CPUs, numbered 0 & 1. * 2 CPUs, numbered 0 & 1.
*/ */
...@@ -520,10 +515,8 @@ void __init default_get_smp_config(unsigned int early) ...@@ -520,10 +515,8 @@ void __init default_get_smp_config(unsigned int early)
*/ */
if (mpf->feature1) { if (mpf->feature1) {
if (early) { if (early) {
/* /* Local APIC has default address */
* local APIC has default address register_lapic_address(APIC_DEFAULT_PHYS_BASE);
*/
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
goto out; goto out;
} }
......
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