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 | |
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 | |
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 | |
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 | |
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 |