Joerg Roedel 23603d
From: David Woodhouse <dwmw@amazon.co.uk>
Joerg Roedel 23603d
Date: Wed, 7 Oct 2020 13:20:42 +0100
Joerg Roedel 23603d
Subject: [PATCH 1/5] x86/apic: Fix x2apic enablement without interrupt
Joerg Roedel 23603d
 remapping
Joerg Roedel 23603d
Patch-mainline: Never, upstream uses different implementation
Joerg Roedel 23603d
References: bsc#1181001, jsc#ECO-3191
Joerg Roedel 23603d
Joerg Roedel 23603d
Currently, Linux as a hypervisor guest will enable x2apic only if there
Joerg Roedel 23603d
are no CPUs present at boot time with an APIC ID above 255.
Joerg Roedel 23603d
Joerg Roedel 23603d
Hotplugging a CPU later with a higher APIC ID would result in a CPU
Joerg Roedel 23603d
which cannot be targeted by external interrupts.
Joerg Roedel 23603d
Joerg Roedel 23603d
Add a filter in x2apic_apic_id_valid() which can be used to prevent
Joerg Roedel 23603d
such CPUs from coming online, and allow x2apic to be enabled even if
Joerg Roedel 23603d
they are present at boot time.
Joerg Roedel 23603d
Joerg Roedel 23603d
Fixes: ce69a784504 ("x86/apic: Enable x2APIC without interrupt remapping under KVM")
Joerg Roedel 23603d
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Joerg Roedel 23603d
Acked-by: Joerg Roedel <jroedel@suse.de>
Joerg Roedel 23603d
---
Joerg Roedel 23603d
 arch/x86/include/asm/apic.h        |    1 +
Joerg Roedel 23603d
 arch/x86/include/asm/x2apic.h      |    5 +++++
Joerg Roedel 23603d
 arch/x86/kernel/apic/apic.c        |   14 ++++++++------
Joerg Roedel 23603d
 arch/x86/kernel/apic/x2apic_phys.c |    6 ++++++
Joerg Roedel 23603d
 4 files changed, 20 insertions(+), 6 deletions(-)
Joerg Roedel 23603d
Joerg Roedel 23603d
--- a/arch/x86/include/asm/apic.h
Joerg Roedel 23603d
+++ b/arch/x86/include/asm/apic.h
Joerg Roedel 23603d
@@ -235,6 +235,7 @@ static inline u64 native_x2apic_icr_read
Joerg Roedel 23603d
 
Joerg Roedel 23603d
 extern int x2apic_mode;
Joerg Roedel 23603d
 extern int x2apic_phys;
Joerg Roedel 23603d
+extern void __init x2apic_set_max_apicid(u32 apicid);
Joerg Roedel 23603d
 extern void __init check_x2apic(void);
Joerg Roedel 23603d
 extern void x2apic_setup(void);
Joerg Roedel 23603d
 static inline int x2apic_enabled(void)
Joerg Roedel 23603d
--- a/arch/x86/include/asm/x2apic.h
Joerg Roedel 23603d
+++ b/arch/x86/include/asm/x2apic.h
Joerg Roedel 23603d
@@ -9,8 +9,13 @@
Joerg Roedel 23603d
 #include <asm/ipi.h>
Joerg Roedel 23603d
 #include <linux/cpumask.h>
Joerg Roedel 23603d
 
Joerg Roedel 23603d
+extern u32 x2apic_max_apicid;
Joerg Roedel 23603d
+
Joerg Roedel 23603d
 static int x2apic_apic_id_valid(int apicid)
Joerg Roedel 23603d
 {
Joerg Roedel 23603d
+	if (x2apic_max_apicid && apicid > x2apic_max_apicid)
Joerg Roedel 23603d
+		return 0;
Joerg Roedel 23603d
+
Joerg Roedel 23603d
 	return 1;
Joerg Roedel 23603d
 }
Joerg Roedel 23603d
 
Joerg Roedel 23603d
--- a/arch/x86/kernel/apic/apic.c
Joerg Roedel 23603d
+++ b/arch/x86/kernel/apic/apic.c
Joerg Roedel 23603d
@@ -1580,20 +1580,22 @@ static __init void try_to_enable_x2apic(
Joerg Roedel 23603d
 		return;
Joerg Roedel 23603d
 
Joerg Roedel 23603d
 	if (remap_mode != IRQ_REMAP_X2APIC_MODE) {
Joerg Roedel 23603d
-		/* IR is required if there is APIC ID > 255 even when running
Joerg Roedel 23603d
-		 * under KVM
Joerg Roedel 23603d
+		/*
Joerg Roedel 23603d
+		 * Using X2APIC without IR is not architecturally supported
Joerg Roedel 23603d
+		 * on bare metal but may be supported in guests.
Joerg Roedel 23603d
 		 */
Joerg Roedel 23603d
-		if (max_physical_apicid > 255 ||
Joerg Roedel 23603d
-		    !x86_init.hyper.x2apic_available()) {
Joerg Roedel 23603d
+		if (!x86_init.hyper.x2apic_available()) {
Joerg Roedel 23603d
 			pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
Joerg Roedel 23603d
 			x2apic_disable();
Joerg Roedel 23603d
 			return;
Joerg Roedel 23603d
 		}
Joerg Roedel 23603d
 
Joerg Roedel 23603d
 		/*
Joerg Roedel 23603d
-		 * without IR all CPUs can be addressed by IOAPIC/MSI
Joerg Roedel 23603d
-		 * only in physical mode
Joerg Roedel 23603d
+		 * Without IR, all CPUs can be addressed by IOAPIC/MSI only
Joerg Roedel 23603d
+		 * in physical mode, and CPUs with an APIC ID that cannnot
Joerg Roedel 23603d
+		 * be addressed must not be brought online.
Joerg Roedel 23603d
 		 */
Joerg Roedel 23603d
+		x2apic_set_max_apicid(255);
Joerg Roedel 23603d
 		x2apic_phys = 1;
Joerg Roedel 23603d
 	}
Joerg Roedel 23603d
 	x2apic_enable();
Joerg Roedel 23603d
--- a/arch/x86/kernel/apic/x2apic_phys.c
Joerg Roedel 23603d
+++ b/arch/x86/kernel/apic/x2apic_phys.c
Joerg Roedel 23603d
@@ -11,6 +11,12 @@
Joerg Roedel 23603d
 int x2apic_phys;
Joerg Roedel 23603d
 
Joerg Roedel 23603d
 static struct apic apic_x2apic_phys;
Joerg Roedel 23603d
+u32 x2apic_max_apicid;
Joerg Roedel 23603d
+
Joerg Roedel 23603d
+void __init x2apic_set_max_apicid(u32 apicid)
Joerg Roedel 23603d
+{
Joerg Roedel 23603d
+	x2apic_max_apicid = apicid;
Joerg Roedel 23603d
+}
Joerg Roedel 23603d
 
Joerg Roedel 23603d
 static int set_x2apic_phys_mode(char *arg)
Joerg Roedel 23603d
 {