xref: /openbmc/linux/arch/x86/kernel/apic/init.c (revision 3b7c27e6)
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 /*
9  * Use DEFINE_STATIC_CALL_NULL() to avoid having to provide stub functions
10  * for each callback. The callbacks are setup during boot and all except
11  * wait_icr_idle() must be initialized before usage. The IPI wrappers
12  * use static_call() and not static_call_cond() to catch any fails.
13  */
14 #define DEFINE_APIC_CALL(__cb)						\
15 	DEFINE_STATIC_CALL_NULL(apic_call_##__cb, *apic->__cb)
16 
17 DEFINE_APIC_CALL(eoi);
18 DEFINE_APIC_CALL(native_eoi);
19 DEFINE_APIC_CALL(icr_read);
20 DEFINE_APIC_CALL(icr_write);
21 DEFINE_APIC_CALL(read);
22 DEFINE_APIC_CALL(send_IPI);
23 DEFINE_APIC_CALL(send_IPI_mask);
24 DEFINE_APIC_CALL(send_IPI_mask_allbutself);
25 DEFINE_APIC_CALL(send_IPI_allbutself);
26 DEFINE_APIC_CALL(send_IPI_all);
27 DEFINE_APIC_CALL(send_IPI_self);
28 DEFINE_APIC_CALL(wait_icr_idle);
29 DEFINE_APIC_CALL(wakeup_secondary_cpu);
30 DEFINE_APIC_CALL(wakeup_secondary_cpu_64);
31 DEFINE_APIC_CALL(write);
32 
33 EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_mask);
34 EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_self);
35 
36 /* The container for function call overrides */
37 struct apic_override __x86_apic_override __initdata;
38 
39 #define apply_override(__cb)					\
40 	if (__x86_apic_override.__cb)				\
41 		apic->__cb = __x86_apic_override.__cb
42 
restore_override_callbacks(void)43 static __init void restore_override_callbacks(void)
44 {
45 	apply_override(eoi);
46 	apply_override(native_eoi);
47 	apply_override(write);
48 	apply_override(read);
49 	apply_override(send_IPI);
50 	apply_override(send_IPI_mask);
51 	apply_override(send_IPI_mask_allbutself);
52 	apply_override(send_IPI_allbutself);
53 	apply_override(send_IPI_all);
54 	apply_override(send_IPI_self);
55 	apply_override(icr_read);
56 	apply_override(icr_write);
57 	apply_override(wakeup_secondary_cpu);
58 	apply_override(wakeup_secondary_cpu_64);
59 }
60 
61 #define update_call(__cb)					\
62 	static_call_update(apic_call_##__cb, *apic->__cb)
63 
update_static_calls(void)64 static __init void update_static_calls(void)
65 {
66 	update_call(eoi);
67 	update_call(native_eoi);
68 	update_call(write);
69 	update_call(read);
70 	update_call(send_IPI);
71 	update_call(send_IPI_mask);
72 	update_call(send_IPI_mask_allbutself);
73 	update_call(send_IPI_allbutself);
74 	update_call(send_IPI_all);
75 	update_call(send_IPI_self);
76 	update_call(icr_read);
77 	update_call(icr_write);
78 	update_call(wait_icr_idle);
79 	update_call(wakeup_secondary_cpu);
80 	update_call(wakeup_secondary_cpu_64);
81 }
82 
apic_setup_apic_calls(void)83 void __init apic_setup_apic_calls(void)
84 {
85 	/* Ensure that the default APIC has native_eoi populated */
86 	apic->native_eoi = apic->eoi;
87 	update_static_calls();
88 	pr_info("Static calls initialized\n");
89 }
90 
apic_install_driver(struct apic * driver)91 void __init apic_install_driver(struct apic *driver)
92 {
93 	if (apic == driver)
94 		return;
95 
96 	apic = driver;
97 
98 	if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
99 		apic->max_apic_id = x2apic_max_apicid;
100 
101 	/* Copy the original eoi() callback as KVM/HyperV might overwrite it */
102 	if (!apic->native_eoi)
103 		apic->native_eoi = apic->eoi;
104 
105 	/* Apply any already installed callback overrides */
106 	restore_override_callbacks();
107 	update_static_calls();
108 
109 	pr_info("Switched APIC routing to: %s\n", driver->name);
110 }
111