Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/apic/init.c
26481 views
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
112