x86/apic: Provide common init infrastructure
In preparation for converting the hotpath APIC callbacks to static keys, provide common initialization infrastructure. Lift apic_install_drivers() from probe_64.c and convert all places which switch the apic instance by storing the pointer to use apic_install_driver() as a first step. 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
0fa075769c
commit
3af1e415e4
@ -344,6 +344,8 @@ extern int lapic_can_unplug_cpu(void);
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
|
||||
void __init apic_install_driver(struct apic *driver);
|
||||
|
||||
static inline u32 apic_read(u32 reg)
|
||||
{
|
||||
return apic->read(reg);
|
||||
|
@ -7,7 +7,7 @@
|
||||
# In particualr, smp_apic_timer_interrupt() is called in random places.
|
||||
KCOV_INSTRUMENT := n
|
||||
|
||||
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_common.o apic_noop.o ipi.o vector.o
|
||||
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_common.o apic_noop.o ipi.o vector.o init.o
|
||||
obj-y += hw_nmi.o
|
||||
|
||||
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
|
||||
|
@ -236,8 +236,7 @@ static int modern_apic(void)
|
||||
*/
|
||||
static void __init apic_disable(void)
|
||||
{
|
||||
pr_info("APIC: switched to apic NOOP\n");
|
||||
apic = &apic_noop;
|
||||
apic_install_driver(&apic_noop);
|
||||
}
|
||||
|
||||
void native_apic_icr_write(u32 low, u32 id)
|
||||
@ -2486,34 +2485,6 @@ u32 x86_msi_msg_get_destid(struct msi_msg *msg, bool extid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x86_msi_msg_get_destid);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
void __init acpi_wake_cpu_handler_update(wakeup_cpu_handler handler)
|
||||
{
|
||||
struct apic **drv;
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++)
|
||||
(*drv)->wakeup_secondary_cpu_64 = handler;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Override the generic EOI implementation with an optimized version.
|
||||
* Only called during early boot when only one CPU is active and with
|
||||
* interrupts disabled, so we know this does not race with actual APIC driver
|
||||
* use.
|
||||
*/
|
||||
void __init apic_set_eoi_cb(void (*eoi)(void))
|
||||
{
|
||||
struct apic **drv;
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
|
||||
/* Should happen once for each apic */
|
||||
WARN_ON((*drv)->eoi == eoi);
|
||||
(*drv)->native_eoi = (*drv)->eoi;
|
||||
(*drv)->eoi = eoi;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init apic_bsp_up_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
|
@ -143,11 +143,7 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
|
||||
static int physflat_probe(void)
|
||||
{
|
||||
if (apic == &apic_physflat || num_possible_cpus() > 8 ||
|
||||
jailhouse_paravirt())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return apic == &apic_physflat || num_possible_cpus() > 8 || jailhouse_paravirt();
|
||||
}
|
||||
|
||||
static struct apic apic_physflat __ro_after_init = {
|
||||
|
@ -119,10 +119,8 @@ bool __init apic_bigsmp_possible(bool cmdline_override)
|
||||
|
||||
void __init apic_bigsmp_force(void)
|
||||
{
|
||||
if (apic != &apic_bigsmp) {
|
||||
apic = &apic_bigsmp;
|
||||
pr_info("Overriding APIC driver with bigsmp\n");
|
||||
}
|
||||
if (apic != &apic_bigsmp)
|
||||
apic_install_driver(&apic_bigsmp);
|
||||
}
|
||||
|
||||
apic_driver(apic_bigsmp);
|
||||
|
47
arch/x86/kernel/apic/init.c
Normal file
47
arch/x86/kernel/apic/init.c
Normal file
@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#define pr_fmt(fmt) "APIC: " fmt
|
||||
|
||||
#include <asm/apic.h>
|
||||
|
||||
#include "local.h"
|
||||
|
||||
void __init apic_install_driver(struct apic *driver)
|
||||
{
|
||||
if (apic == driver)
|
||||
return;
|
||||
|
||||
apic = driver;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
|
||||
apic->max_apic_id = x2apic_max_apicid;
|
||||
|
||||
pr_info("Switched APIC routing to: %s\n", driver->name);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
void __init acpi_wake_cpu_handler_update(wakeup_cpu_handler handler)
|
||||
{
|
||||
struct apic **drv;
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++)
|
||||
(*drv)->wakeup_secondary_cpu_64 = handler;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Override the generic EOI implementation with an optimized version.
|
||||
* Only called during early boot when only one CPU is active and with
|
||||
* interrupts disabled, so we know this does not race with actual APIC driver
|
||||
* use.
|
||||
*/
|
||||
void __init apic_set_eoi_cb(void (*eoi)(void))
|
||||
{
|
||||
struct apic **drv;
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
|
||||
/* Should happen once for each apic */
|
||||
WARN_ON((*drv)->eoi == eoi);
|
||||
(*drv)->native_eoi = (*drv)->eoi;
|
||||
(*drv)->eoi = eoi;
|
||||
}
|
||||
}
|
@ -82,7 +82,7 @@ static int __init parse_apic(char *arg)
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
|
||||
if (!strcmp((*drv)->name, arg)) {
|
||||
apic = *drv;
|
||||
apic_install_driver(*drv);
|
||||
cmdline_apic = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -129,7 +129,7 @@ void __init x86_32_probe_apic(void)
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
|
||||
if ((*drv)->probe()) {
|
||||
apic = *drv;
|
||||
apic_install_driver(*drv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -137,5 +137,4 @@ void __init x86_32_probe_apic(void)
|
||||
if (drv == __apicdrivers_end)
|
||||
panic("Didn't find an APIC driver");
|
||||
}
|
||||
printk(KERN_INFO "Using APIC driver %s\n", apic->name);
|
||||
}
|
||||
|
@ -13,19 +13,6 @@
|
||||
|
||||
#include "local.h"
|
||||
|
||||
static __init void apic_install_driver(struct apic *driver)
|
||||
{
|
||||
if (apic == driver)
|
||||
return;
|
||||
|
||||
apic = driver;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
|
||||
apic->max_apic_id = x2apic_max_apicid;
|
||||
|
||||
pr_info("Switched APIC routing to %s:\n", apic->name);
|
||||
}
|
||||
|
||||
/* Select the appropriate APIC driver */
|
||||
void __init x86_64_probe_apic(void)
|
||||
{
|
||||
|
@ -160,20 +160,16 @@ static struct apic xen_pv_apic = {
|
||||
|
||||
static void __init xen_apic_check(void)
|
||||
{
|
||||
if (apic == &xen_pv_apic)
|
||||
return;
|
||||
|
||||
pr_info("Switched APIC routing from %s to %s.\n", apic->name,
|
||||
xen_pv_apic.name);
|
||||
apic = &xen_pv_apic;
|
||||
apic_install_driver(&xen_pv_apic);
|
||||
}
|
||||
|
||||
void __init xen_init_apic(void)
|
||||
{
|
||||
x86_apic_ops.io_apic_read = xen_io_apic_read;
|
||||
/* On PV guests the APIC CPUID bit is disabled so none of the
|
||||
* routines end up executing. */
|
||||
if (!xen_initial_domain())
|
||||
apic = &xen_pv_apic;
|
||||
apic_install_driver(&xen_pv_apic);
|
||||
|
||||
x86_platform.apic_post_init = xen_apic_check;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user