Skip to content

Commit bef4f37

Browse files
KAGA-KOKOhansendc
authored andcommitted
x86/apic: Provide apic_update_callback()
There are already two variants of update mechanism for particular callbacks and virtualization just writes into the data structure. Provide an interface and use a shadow data structure to preserve callbacks so they can be reapplied when the APIC driver is replaced. The extra data structure is intentional as any new callback needs to be also updated in the core code. This also prepares for static calls. 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 3b5244b commit bef4f37

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

arch/x86/include/asm/apic.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,23 @@ struct apic {
308308
char *name;
309309
};
310310

311+
struct apic_override {
312+
void (*eoi)(void);
313+
void (*native_eoi)(void);
314+
void (*write)(u32 reg, u32 v);
315+
u32 (*read)(u32 reg);
316+
void (*send_IPI)(int cpu, int vector);
317+
void (*send_IPI_mask)(const struct cpumask *mask, int vector);
318+
void (*send_IPI_mask_allbutself)(const struct cpumask *msk, int vec);
319+
void (*send_IPI_allbutself)(int vector);
320+
void (*send_IPI_all)(int vector);
321+
void (*send_IPI_self)(int vector);
322+
u64 (*icr_read)(void);
323+
void (*icr_write)(u32 low, u32 high);
324+
int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
325+
int (*wakeup_secondary_cpu_64)(int apicid, unsigned long start_eip);
326+
};
327+
311328
/*
312329
* Pointer to the local APIC driver in use on this system (there's
313330
* always just one such driver in use - the kernel decides via an
@@ -343,9 +360,17 @@ extern int lapic_can_unplug_cpu(void);
343360
#endif
344361

345362
#ifdef CONFIG_X86_LOCAL_APIC
363+
extern struct apic_override __x86_apic_override;
346364

365+
void __init apic_setup_apic_calls(void);
347366
void __init apic_install_driver(struct apic *driver);
348367

368+
#define apic_update_callback(_callback, _fn) { \
369+
__x86_apic_override._callback = _fn; \
370+
apic->_callback = _fn; \
371+
pr_info("APIC: %s() replaced with %ps()\n", #_callback, _fn); \
372+
}
373+
349374
static inline u32 apic_read(u32 reg)
350375
{
351376
return apic->read(reg);
@@ -405,6 +430,9 @@ static inline void apic_wait_icr_idle(void) { }
405430
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
406431
static inline void apic_set_eoi_cb(void (*eoi)(void)) {}
407432
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
433+
static inline void apic_setup_apic_calls(void) { }
434+
435+
#define apic_update_callback(_callback, _fn) do { } while (0)
408436

409437
#endif /* CONFIG_X86_LOCAL_APIC */
410438

arch/x86/kernel/apic/init.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,37 @@
55

66
#include "local.h"
77

8+
/* The container for function call overrides */
9+
struct apic_override __x86_apic_override __initdata;
10+
11+
#define apply_override(__cb) \
12+
if (__x86_apic_override.__cb) \
13+
apic->__cb = __x86_apic_override.__cb
14+
15+
static __init void restore_override_callbacks(void)
16+
{
17+
apply_override(eoi);
18+
apply_override(native_eoi);
19+
apply_override(write);
20+
apply_override(read);
21+
apply_override(send_IPI);
22+
apply_override(send_IPI_mask);
23+
apply_override(send_IPI_mask_allbutself);
24+
apply_override(send_IPI_allbutself);
25+
apply_override(send_IPI_all);
26+
apply_override(send_IPI_self);
27+
apply_override(icr_read);
28+
apply_override(icr_write);
29+
apply_override(wakeup_secondary_cpu);
30+
apply_override(wakeup_secondary_cpu_64);
31+
}
32+
33+
void __init apic_setup_apic_calls(void)
34+
{
35+
/* Ensure that the default APIC has native_eoi populated */
36+
apic->native_eoi = apic->eoi;
37+
}
38+
839
void __init apic_install_driver(struct apic *driver)
940
{
1041
if (apic == driver)
@@ -15,6 +46,13 @@ void __init apic_install_driver(struct apic *driver)
1546
if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
1647
apic->max_apic_id = x2apic_max_apicid;
1748

49+
/* Copy the original eoi() callback as KVM/HyperV might overwrite it */
50+
if (!apic->native_eoi)
51+
apic->native_eoi = apic->eoi;
52+
53+
/* Apply any already installed callback overrides */
54+
restore_override_callbacks();
55+
1856
pr_info("Switched APIC routing to: %s\n", driver->name);
1957
}
2058

@@ -41,7 +79,6 @@ void __init apic_set_eoi_cb(void (*eoi)(void))
4179
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
4280
/* Should happen once for each apic */
4381
WARN_ON((*drv)->eoi == eoi);
44-
(*drv)->native_eoi = (*drv)->eoi;
4582
(*drv)->eoi = eoi;
4683
}
4784
}

arch/x86/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,8 @@ void __init setup_arch(char **cmdline_p)
10171017

10181018
x86_report_nx();
10191019

1020+
apic_setup_apic_calls();
1021+
10201022
if (acpi_mps_check()) {
10211023
#ifdef CONFIG_X86_LOCAL_APIC
10221024
apic_is_disabled = true;

0 commit comments

Comments
 (0)