Skip to content

Commit 3b7c27e

Browse files
KAGA-KOKOhansendc
authored andcommitted
x86/apic: Provide static call infrastructure for APIC callbacks
Declare and define the static calls for the hotpath APIC callbacks. Note this deliberately uses STATIC_CALL_NULL() because otherwise it would be required to have the definitions in the 32bit and the 64bit default APIC implementations and it's hard to keep the calls in sync. The other option would be to have stub functions for each callback type. Not pretty either So the NULL capable calls are used and filled in during early boot after the static key infrastructure has been initialized. The calls will be static_call() except for the wait_irc_idle() callback which is valid to be NULL for X2APIC systems. Update the calls when a new APIC driver is installed and when a callback override is invoked. Export the trampolines for the two calls which are used in KVM and MCE error inject modules. Test the setup and let the next step convert the inline wrappers to make it effective. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Michael Kelley <mikelley@microsoft.com> Tested-by: Sohil Mehta <sohil.mehta@intel.com> Tested-by: Juergen Gross <jgross@suse.com> # Xen PV (dom0 and unpriv. guest)
1 parent 28b8235 commit 3b7c27e

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

arch/x86/include/asm/apic.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define _ASM_X86_APIC_H
44

55
#include <linux/cpumask.h>
6+
#include <linux/static_call.h>
67

78
#include <asm/alternative.h>
89
#include <asm/cpufeature.h>
@@ -368,9 +369,29 @@ void __init apic_install_driver(struct apic *driver);
368369
#define apic_update_callback(_callback, _fn) { \
369370
__x86_apic_override._callback = _fn; \
370371
apic->_callback = _fn; \
372+
static_call_update(apic_call_##_callback, _fn); \
371373
pr_info("APIC: %s() replaced with %ps()\n", #_callback, _fn); \
372374
}
373375

376+
#define DECLARE_APIC_CALL(__cb) \
377+
DECLARE_STATIC_CALL(apic_call_##__cb, *apic->__cb)
378+
379+
DECLARE_APIC_CALL(eoi);
380+
DECLARE_APIC_CALL(native_eoi);
381+
DECLARE_APIC_CALL(icr_read);
382+
DECLARE_APIC_CALL(icr_write);
383+
DECLARE_APIC_CALL(read);
384+
DECLARE_APIC_CALL(send_IPI);
385+
DECLARE_APIC_CALL(send_IPI_mask);
386+
DECLARE_APIC_CALL(send_IPI_mask_allbutself);
387+
DECLARE_APIC_CALL(send_IPI_allbutself);
388+
DECLARE_APIC_CALL(send_IPI_all);
389+
DECLARE_APIC_CALL(send_IPI_self);
390+
DECLARE_APIC_CALL(wait_icr_idle);
391+
DECLARE_APIC_CALL(wakeup_secondary_cpu);
392+
DECLARE_APIC_CALL(wakeup_secondary_cpu_64);
393+
DECLARE_APIC_CALL(write);
394+
374395
static __always_inline u32 apic_read(u32 reg)
375396
{
376397
return apic->read(reg);

arch/x86/kernel/apic/init.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,34 @@
55

66
#include "local.h"
77

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+
836
/* The container for function call overrides */
937
struct apic_override __x86_apic_override __initdata;
1038

@@ -30,10 +58,34 @@ static __init void restore_override_callbacks(void)
3058
apply_override(wakeup_secondary_cpu_64);
3159
}
3260

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+
3383
void __init apic_setup_apic_calls(void)
3484
{
3585
/* Ensure that the default APIC has native_eoi populated */
3686
apic->native_eoi = apic->eoi;
87+
update_static_calls();
88+
pr_info("Static calls initialized\n");
3789
}
3890

3991
void __init apic_install_driver(struct apic *driver)
@@ -52,6 +104,7 @@ void __init apic_install_driver(struct apic *driver)
52104

53105
/* Apply any already installed callback overrides */
54106
restore_override_callbacks();
107+
update_static_calls();
55108

56109
pr_info("Switched APIC routing to: %s\n", driver->name);
57110
}

0 commit comments

Comments
 (0)