mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
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)
This commit is contained in:
parent
5a88f354dc
commit
81287ad65d
@ -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)
|
|||||||
__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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user