xref: /openbmc/linux/arch/x86/kernel/apic/init.c (revision 2744a7ce)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #define pr_fmt(fmt) "APIC: " fmt
3 
4 #include <asm/apic.h>
5 
6 #include "local.h"
7 
8 /* The container for function call overrides */
9 struct apic_override __x86_apic_override __initdata;
10 
11 #define apply_override(__cb)					\
12 	if (__x86_apic_override.__cb)				\
13 		apic->__cb = __x86_apic_override.__cb
14 
15 static __init void restore_override_callbacks(void)
16 {
17 	apply_override(eoi);
18 	apply_override(native_eoi);
19 	apply_override(write);
20 	apply_override(read);
21 	apply_override(send_IPI);
22 	apply_override(send_IPI_mask);
23 	apply_override(send_IPI_mask_allbutself);
24 	apply_override(send_IPI_allbutself);
25 	apply_override(send_IPI_all);
26 	apply_override(send_IPI_self);
27 	apply_override(icr_read);
28 	apply_override(icr_write);
29 	apply_override(wakeup_secondary_cpu);
30 	apply_override(wakeup_secondary_cpu_64);
31 }
32 
33 void __init apic_setup_apic_calls(void)
34 {
35 	/* Ensure that the default APIC has native_eoi populated */
36 	apic->native_eoi = apic->eoi;
37 }
38 
39 void __init apic_install_driver(struct apic *driver)
40 {
41 	if (apic == driver)
42 		return;
43 
44 	apic = driver;
45 
46 	if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
47 		apic->max_apic_id = x2apic_max_apicid;
48 
49 	/* Copy the original eoi() callback as KVM/HyperV might overwrite it */
50 	if (!apic->native_eoi)
51 		apic->native_eoi = apic->eoi;
52 
53 	/* Apply any already installed callback overrides */
54 	restore_override_callbacks();
55 
56 	pr_info("Switched APIC routing to: %s\n", driver->name);
57 }
58