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
17DEFINE_APIC_CALL(eoi);
18DEFINE_APIC_CALL(native_eoi);
19DEFINE_APIC_CALL(icr_read);
20DEFINE_APIC_CALL(icr_write);
21DEFINE_APIC_CALL(read);
22DEFINE_APIC_CALL(send_IPI);
23DEFINE_APIC_CALL(send_IPI_mask);
24DEFINE_APIC_CALL(send_IPI_mask_allbutself);
25DEFINE_APIC_CALL(send_IPI_allbutself);
26DEFINE_APIC_CALL(send_IPI_all);
27DEFINE_APIC_CALL(send_IPI_self);
28DEFINE_APIC_CALL(wait_icr_idle);
29DEFINE_APIC_CALL(wakeup_secondary_cpu);
30DEFINE_APIC_CALL(wakeup_secondary_cpu_64);
31DEFINE_APIC_CALL(write);
32
33EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_mask);
34EXPORT_STATIC_CALL_TRAMP_GPL(apic_call_send_IPI_self);
35
36/* The container for function call overrides */
37struct 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
43static __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
64static __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
83void __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
91void __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

source code of linux/arch/x86/kernel/apic/init.c