1
0
Fork 0

x86/apic: Fix x2apic enablement without interrupt remapping

Currently, Linux as a hypervisor guest will enable x2apic only if there are
no CPUs present at boot time with an APIC ID above 255.

Hotplugging a CPU later with a higher APIC ID would result in a CPU which
cannot be targeted by external interrupts.

Add a filter in x2apic_apic_id_valid() which can be used to prevent such
CPUs from coming online, and allow x2apic to be enabled even if they are
present at boot time.

Fixes: ce69a78450 ("x86/apic: Enable x2APIC without interrupt remapping under KVM")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20201024213535.443185-2-dwmw2@infradead.org
zero-sugar-mainline-defconfig
David Woodhouse 2020-10-24 22:35:01 +01:00 committed by Thomas Gleixner
parent 5a169bf04c
commit 26573a9774
3 changed files with 18 additions and 6 deletions

View File

@ -259,6 +259,7 @@ static inline u64 native_x2apic_icr_read(void)
extern int x2apic_mode; extern int x2apic_mode;
extern int x2apic_phys; extern int x2apic_phys;
extern void __init x2apic_set_max_apicid(u32 apicid);
extern void __init check_x2apic(void); extern void __init check_x2apic(void);
extern void x2apic_setup(void); extern void x2apic_setup(void);
static inline int x2apic_enabled(void) static inline int x2apic_enabled(void)

View File

@ -1841,20 +1841,22 @@ static __init void try_to_enable_x2apic(int remap_mode)
return; return;
if (remap_mode != IRQ_REMAP_X2APIC_MODE) { if (remap_mode != IRQ_REMAP_X2APIC_MODE) {
/* IR is required if there is APIC ID > 255 even when running /*
* under KVM * Using X2APIC without IR is not architecturally supported
* on bare metal but may be supported in guests.
*/ */
if (max_physical_apicid > 255 || if (!x86_init.hyper.x2apic_available()) {
!x86_init.hyper.x2apic_available()) {
pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
x2apic_disable(); x2apic_disable();
return; return;
} }
/* /*
* without IR all CPUs can be addressed by IOAPIC/MSI * Without IR, all CPUs can be addressed by IOAPIC/MSI only
* only in physical mode * in physical mode, and CPUs with an APIC ID that cannnot
* be addressed must not be brought online.
*/ */
x2apic_set_max_apicid(255);
x2apic_phys = 1; x2apic_phys = 1;
} }
x2apic_enable(); x2apic_enable();

View File

@ -8,6 +8,12 @@
int x2apic_phys; int x2apic_phys;
static struct apic apic_x2apic_phys; static struct apic apic_x2apic_phys;
static u32 x2apic_max_apicid __ro_after_init;
void __init x2apic_set_max_apicid(u32 apicid)
{
x2apic_max_apicid = apicid;
}
static int __init set_x2apic_phys_mode(char *arg) static int __init set_x2apic_phys_mode(char *arg)
{ {
@ -98,6 +104,9 @@ static int x2apic_phys_probe(void)
/* Common x2apic functions, also used by x2apic_cluster */ /* Common x2apic functions, also used by x2apic_cluster */
int x2apic_apic_id_valid(u32 apicid) int x2apic_apic_id_valid(u32 apicid)
{ {
if (x2apic_max_apicid && apicid > x2apic_max_apicid)
return 0;
return 1; return 1;
} }