* [PATCH v2 1/4] x86/apic: Rename init_apic_mappings() to apic_finalize_early_init()
2026-09-24 10:40 [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
@ 2026-09-24 10:40 ` Grzegorz Jaszczyk
2026-10-20 18:32 ` [tip: x86/apic] " tip-bot2 for Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 2/4] x86/apic: Consolidate early APIC initialization into apic_early_init() Grzegorz Jaszczyk
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Grzegorz Jaszczyk @ 2026-09-24 10:40 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, dmaluka, vineethrp, chuanxiao.dong, jaszczyk,
Grzegorz Jaszczyk, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Juergen Gross,
Peter Zijlstra (Intel),
Radu Rendec, Ahmed S. Darwish, Shashank Balaji,
Sean Christopherson, Julian Stecklina, Thierry Reding,
Naveen N Rao (AMD), Mike Rapoport (Microsoft),
Ard Biesheuvel, Andrew Morton, Arnd Bergmann, Thomas Zimmermann,
Thorsten Blum, Breno Leitao, Harshit Mogalapalli
Rename init_apic_mappings() to apic_finalize_early_init() to
accurately reflect its purpose (validating the TSC deadline timer and
finalizing early APIC detection and fallback mapping when no SMP config
was found).
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
---
arch/x86/include/asm/apic.h | 4 ++--
arch/x86/kernel/apic/apic.c | 5 +----
arch/x86/kernel/setup.c | 2 +-
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 9cd493d467d4d..b4c112b6d3ab3 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -133,7 +133,7 @@ extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
extern void apic_intr_mode_select(void);
extern void apic_intr_mode_init(void);
-extern void init_apic_mappings(void);
+void apic_finalize_early_init(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
@@ -183,7 +183,7 @@ extern void topology_reset_possible_cpus_up(void);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
-static inline void init_apic_mappings(void) { }
+static inline void apic_finalize_early_init(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 90025451ace2f..cb78e0d6c9317 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2064,10 +2064,7 @@ static bool __init detect_init_APIC(void)
}
#endif
-/**
- * init_apic_mappings - initialize APIC mappings
- */
-void __init init_apic_mappings(void)
+void __init apic_finalize_early_init(void)
{
if (apic_validate_deadline_timer())
pr_info("TSC deadline timer available\n");
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cda6adb9f69c4..06522a205dd93 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1242,7 +1242,7 @@ void __init setup_arch(char **cmdline_p)
x86_init.mpparse.parse_smp_cfg();
/* Last opportunity to detect and map the local APIC */
- init_apic_mappings();
+ apic_finalize_early_init();
topology_init_possible_cpus();
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 10+ messages in thread* [tip: x86/apic] x86/apic: Rename init_apic_mappings() to apic_finalize_early_init()
2026-09-24 10:40 ` [PATCH v2 1/4] x86/apic: Rename init_apic_mappings() to apic_finalize_early_init() Grzegorz Jaszczyk
@ 2026-10-20 18:32 ` tip-bot2 for Grzegorz Jaszczyk
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot2 for Grzegorz Jaszczyk @ 2026-10-20 18:32 UTC (permalink / raw)
To: linux-tip-commits
Cc: Thomas Gleixner, Grzegorz Jaszczyk, Borislav Petkov (AMD),
Thomas Gleixner, x86, linux-kernel
The following commit has been merged into the x86/apic branch of tip:
Commit-ID: ecb8135571e435bc38c86d363f231681562c9ba6
Gitweb: https://git.kernel.org/tip/ecb8135571e435bc38c86d363f231681562c9ba6
Author: Grzegorz Jaszczyk <jaszczyk@chromium.org>
AuthorDate: Thu, 24 Sep 2026 10:40:18
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Mon, 19 Oct 2026 17:06:49 -07:00
x86/apic: Rename init_apic_mappings() to apic_finalize_early_init()
Rename init_apic_mappings() to apic_finalize_early_init() to accurately
reflect its purpose (validating the TSC deadline timer and finalizing early
APIC detection and fallback mapping when no SMP config was found).
No functional changes.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260924104102.3534474-2-jaszczyk@chromium.org
---
arch/x86/include/asm/apic.h | 4 ++--
arch/x86/kernel/apic/apic.c | 5 +----
arch/x86/kernel/setup.c | 2 +-
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 9cd493d..b4c112b 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -133,7 +133,7 @@ extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
extern void apic_intr_mode_select(void);
extern void apic_intr_mode_init(void);
-extern void init_apic_mappings(void);
+void apic_finalize_early_init(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
@@ -183,7 +183,7 @@ extern void topology_reset_possible_cpus_up(void);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
-static inline void init_apic_mappings(void) { }
+static inline void apic_finalize_early_init(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 9002545..cb78e0d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2064,10 +2064,7 @@ no_apic:
}
#endif
-/**
- * init_apic_mappings - initialize APIC mappings
- */
-void __init init_apic_mappings(void)
+void __init apic_finalize_early_init(void)
{
if (apic_validate_deadline_timer())
pr_info("TSC deadline timer available\n");
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cda6adb..06522a2 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1242,7 +1242,7 @@ void __init setup_arch(char **cmdline_p)
x86_init.mpparse.parse_smp_cfg();
/* Last opportunity to detect and map the local APIC */
- init_apic_mappings();
+ apic_finalize_early_init();
topology_init_possible_cpus();
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/4] x86/apic: Consolidate early APIC initialization into apic_early_init()
2026-09-24 10:40 [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 1/4] x86/apic: Rename init_apic_mappings() to apic_finalize_early_init() Grzegorz Jaszczyk
@ 2026-09-24 10:40 ` Grzegorz Jaszczyk
2026-10-20 18:32 ` [tip: x86/apic] " tip-bot2 for Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 3/4] x86/apic: Remove redundant check from x2apic_phys_probe() Grzegorz Jaszczyk
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Grzegorz Jaszczyk @ 2026-09-24 10:40 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, dmaluka, vineethrp, chuanxiao.dong, jaszczyk,
Grzegorz Jaszczyk, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra (Intel),
Juergen Gross, Radu Rendec, Thierry Reding, Julian Stecklina,
Sean Christopherson, Naveen N Rao (AMD),
Ard Biesheuvel, Mike Rapoport (Microsoft),
Andrew Morton, Arnd Bergmann, Thomas Zimmermann, Thorsten Blum,
Breno Leitao, Harshit Mogalapalli
Early APIC initialization is currently scattered across setup_arch():
apic_setup_apic_calls() and acpi_mps_check() run early, check_x2apic()
is invoked much later during memory range setup, and
apic_finalize_early_init() runs near the end of setup_arch().
Consolidate the initial setup into apic_early_init() in
arch/x86/kernel/apic/apic.c so that acpi_mps_check(), check_x2apic(),
and static call initialization happen together in one place. Make
check_x2apic() static as it no longer has external callers.
Place apic_setup_apic_calls() at the end of apic_early_init() in
preparation for replacing it with apic_install_default_driver() in the
subsequent patch. This ordering change is safe because neither
acpi_mps_check() nor check_x2apic() uses APIC static calls
(check_x2apic() accesses x2APIC MSRs directly via native_apic_msr_read()).
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
---
arch/x86/include/asm/apic.h | 3 ++-
arch/x86/kernel/apic/apic.c | 16 ++++++++++++++--
arch/x86/kernel/setup.c | 10 +---------
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index b4c112b6d3ab3..b1610b8bc6544 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -133,6 +133,7 @@ extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
extern void apic_intr_mode_select(void);
extern void apic_intr_mode_init(void);
+void apic_early_init(void);
void apic_finalize_early_init(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
@@ -183,6 +184,7 @@ extern void topology_reset_possible_cpus_up(void);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
+static inline void apic_early_init(void) { }
static inline void apic_finalize_early_init(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
@@ -254,7 +256,6 @@ static inline u32 native_apic_msr_read(u32 reg) { BUG(); }
#define x2apic_mode (0)
#define x2apic_supported() (0)
#endif /* !CONFIG_X86_X2APIC */
-extern void __init check_x2apic(void);
struct irq_data;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index cb78e0d6c9317..721e194ceac2d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1869,7 +1869,7 @@ static __init void try_to_enable_x2apic(int remap_mode)
x2apic_enable();
}
-void __init check_x2apic(void)
+static void __init check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
@@ -1884,7 +1884,7 @@ void __init check_x2apic(void)
}
}
#else /* CONFIG_X86_X2APIC */
-void __init check_x2apic(void)
+static void __init check_x2apic(void)
{
if (!apic_is_x2apic_enabled())
return;
@@ -2064,6 +2064,18 @@ static bool __init detect_init_APIC(void)
}
#endif
+void __init apic_early_init(void)
+{
+ if (acpi_mps_check()) {
+ apic_is_disabled = true;
+ setup_clear_cpu_cap(X86_FEATURE_APIC);
+ } else {
+ check_x2apic();
+ }
+
+ apic_setup_apic_calls();
+}
+
void __init apic_finalize_early_init(void)
{
if (apic_validate_deadline_timer())
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 06522a205dd93..2bab41e073d52 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -993,14 +993,7 @@ void __init setup_arch(char **cmdline_p)
x86_report_nx();
- apic_setup_apic_calls();
-
- if (acpi_mps_check()) {
-#ifdef CONFIG_X86_LOCAL_APIC
- apic_is_disabled = true;
-#endif
- setup_clear_cpu_cap(X86_FEATURE_APIC);
- }
+ apic_early_init();
e820__finish_early_params();
@@ -1062,7 +1055,6 @@ void __init setup_arch(char **cmdline_p)
/* max_low_pfn get updated here */
find_low_pfn_range();
#else
- check_x2apic();
/* How many end-of-memory variables you have, grandma! */
/* need this before calling reserve_initrd */
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 10+ messages in thread* [tip: x86/apic] x86/apic: Consolidate early APIC initialization into apic_early_init()
2026-09-24 10:40 ` [PATCH v2 2/4] x86/apic: Consolidate early APIC initialization into apic_early_init() Grzegorz Jaszczyk
@ 2026-10-20 18:32 ` tip-bot2 for Grzegorz Jaszczyk
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot2 for Grzegorz Jaszczyk @ 2026-10-20 18:32 UTC (permalink / raw)
To: linux-tip-commits
Cc: Thomas Gleixner, Grzegorz Jaszczyk, Borislav Petkov (AMD),
Thomas Gleixner, x86, linux-kernel
The following commit has been merged into the x86/apic branch of tip:
Commit-ID: 90f8b3e500657beeeb0f67bbb27c53b9707202a2
Gitweb: https://git.kernel.org/tip/90f8b3e500657beeeb0f67bbb27c53b9707202a2
Author: Grzegorz Jaszczyk <jaszczyk@chromium.org>
AuthorDate: Thu, 24 Sep 2026 10:40:19
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Mon, 19 Oct 2026 17:54:29 -07:00
x86/apic: Consolidate early APIC initialization into apic_early_init()
Early APIC initialization is currently scattered across setup_arch():
apic_setup_apic_calls() and acpi_mps_check() run early, check_x2apic() is invoked
much later during memory range setup, and apic_finalize_early_init() runs near the
end of setup_arch().
Consolidate the initial setup into apic_early_init() in arch/x86/kernel/apic/apic.c
so that acpi_mps_check(), check_x2apic(), and static call initialization happen
together in one place.
Place apic_setup_apic_calls() at the end of apic_early_init() in preparation for
replacing it with apic_install_default_driver(). This ordering change is safe because
neither acpi_mps_check() nor check_x2apic() uses APIC static calls (check_x2apic()
accesses x2APIC MSRs directly via native_apic_msr_read()).
[ bp: Tone down the patch explanation text. ]
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260924104102.3534474-3-jaszczyk@chromium.org
---
arch/x86/include/asm/apic.h | 3 ++-
arch/x86/kernel/apic/apic.c | 16 ++++++++++++++--
arch/x86/kernel/setup.c | 10 +---------
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index b4c112b..b1610b8 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -133,6 +133,7 @@ extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
extern void apic_intr_mode_select(void);
extern void apic_intr_mode_init(void);
+void apic_early_init(void);
void apic_finalize_early_init(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
@@ -183,6 +184,7 @@ extern void topology_reset_possible_cpus_up(void);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
+static inline void apic_early_init(void) { }
static inline void apic_finalize_early_init(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
@@ -254,7 +256,6 @@ static inline u32 native_apic_msr_read(u32 reg) { BUG(); }
#define x2apic_mode (0)
#define x2apic_supported() (0)
#endif /* !CONFIG_X86_X2APIC */
-extern void __init check_x2apic(void);
struct irq_data;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index cb78e0d..721e194 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1869,7 +1869,7 @@ static __init void try_to_enable_x2apic(int remap_mode)
x2apic_enable();
}
-void __init check_x2apic(void)
+static void __init check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
@@ -1884,7 +1884,7 @@ void __init check_x2apic(void)
}
}
#else /* CONFIG_X86_X2APIC */
-void __init check_x2apic(void)
+static void __init check_x2apic(void)
{
if (!apic_is_x2apic_enabled())
return;
@@ -2064,6 +2064,18 @@ no_apic:
}
#endif
+void __init apic_early_init(void)
+{
+ if (acpi_mps_check()) {
+ apic_is_disabled = true;
+ setup_clear_cpu_cap(X86_FEATURE_APIC);
+ } else {
+ check_x2apic();
+ }
+
+ apic_setup_apic_calls();
+}
+
void __init apic_finalize_early_init(void)
{
if (apic_validate_deadline_timer())
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 06522a2..2bab41e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -993,14 +993,7 @@ void __init setup_arch(char **cmdline_p)
x86_report_nx();
- apic_setup_apic_calls();
-
- if (acpi_mps_check()) {
-#ifdef CONFIG_X86_LOCAL_APIC
- apic_is_disabled = true;
-#endif
- setup_clear_cpu_cap(X86_FEATURE_APIC);
- }
+ apic_early_init();
e820__finish_early_params();
@@ -1062,7 +1055,6 @@ void __init setup_arch(char **cmdline_p)
/* max_low_pfn get updated here */
find_low_pfn_range();
#else
- check_x2apic();
/* How many end-of-memory variables you have, grandma! */
/* need this before calling reserve_initrd */
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 3/4] x86/apic: Remove redundant check from x2apic_phys_probe()
2026-09-24 10:40 [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 1/4] x86/apic: Rename init_apic_mappings() to apic_finalize_early_init() Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 2/4] x86/apic: Consolidate early APIC initialization into apic_early_init() Grzegorz Jaszczyk
@ 2026-09-24 10:40 ` Grzegorz Jaszczyk
2026-10-20 18:32 ` [tip: x86/apic] " tip-bot2 for Grzegorz Jaszczyk
2026-09-24 10:40 ` [PATCH v2 4/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
2026-10-17 21:04 ` [PATCH v2 0/4] " Thomas Gleixner
4 siblings, 1 reply; 10+ messages in thread
From: Grzegorz Jaszczyk @ 2026-09-24 10:40 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, dmaluka, vineethrp, chuanxiao.dong, jaszczyk,
Grzegorz Jaszczyk, Ingo Molnar, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Eric Dumazet, Melody Wang
Commit 9ebd680bd029 ("x86, apic: Use probe routines to simplify apic
selection") introduced x2apic_phys_probe() with a generic fallback check
for 'apic == &apic_x2apic_phys' to preserve any prior selection of
apic_x2apic_phys by default_acpi_madt_oem_check():
if (x2apic_mode && x2apic_phys)
return 1;
return apic == &apic_x2apic_phys;
At the time, x2apic_acpi_madt_oem_check() only checked
'x2apic_phys && x2apic_enabled()', so that fallback was already
redundant. Commit ea0dcf903e7d ("x86/apic: Use x2apic physical mode
based on FADT setting") later added the ACPI_FADT_APIC_PHYSICAL check
only to x2apic_acpi_madt_oem_check(), temporarily relying on the
'apic == &apic_x2apic_phys' fallback in x2apic_phys_probe() when
x2APIC was pre-enabled by BIOS.
Subsequently, commit cb214ede7657 ("x86/apic: Work around boot failure
on HP ProLiant DL980 G7 Server systems") factored out x2apic_fadt_phys()
and added it directly to x2apic_phys_probe(). Because
default_acpi_madt_oem_check() (via the .acpi_madt_oem_check callback) is
the only path that can install apic_x2apic_phys prior to
x2apic_phys_probe(), and x2apic_acpi_madt_oem_check() checks the exact
same 'x2apic_phys || x2apic_fadt_phys()' condition, the fallback
'apic == &apic_x2apic_phys' check became completely unreachable again.
Remove the redundant check and the associated forward declaration of
apic_x2apic_phys. In addition to cleaning up dead code, this allows
apic_x2apic_phys to be installed as an early boot default driver when
hardware x2APIC is pre-enabled without preventing x2apic_cluster from
being probed and selected later during boot.
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
---
arch/x86/kernel/apic/x2apic_phys.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 090647cc5a784..5bf86839e84c3 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -6,8 +6,6 @@
#include "local.h"
int x2apic_phys;
-
-static struct apic apic_x2apic_phys;
u32 x2apic_max_apicid __ro_after_init = UINT_MAX;
void __init x2apic_set_max_apicid(u32 apicid)
@@ -110,10 +108,7 @@ static int x2apic_phys_probe(void)
if (!x2apic_mode)
return 0;
- if (x2apic_phys || x2apic_fadt_phys())
- return 1;
-
- return apic == &apic_x2apic_phys;
+ return x2apic_phys || x2apic_fadt_phys();
}
u32 x2apic_get_apic_id(u32 id)
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 10+ messages in thread* [tip: x86/apic] x86/apic: Remove redundant check from x2apic_phys_probe()
2026-09-24 10:40 ` [PATCH v2 3/4] x86/apic: Remove redundant check from x2apic_phys_probe() Grzegorz Jaszczyk
@ 2026-10-20 18:32 ` tip-bot2 for Grzegorz Jaszczyk
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot2 for Grzegorz Jaszczyk @ 2026-10-20 18:32 UTC (permalink / raw)
To: linux-tip-commits
Cc: Grzegorz Jaszczyk, Borislav Petkov (AMD),
Thomas Gleixner, x86, linux-kernel
The following commit has been merged into the x86/apic branch of tip:
Commit-ID: 98dff3f1bc033da4d4811d8f335fe7311dbf54df
Gitweb: https://git.kernel.org/tip/98dff3f1bc033da4d4811d8f335fe7311dbf54df
Author: Grzegorz Jaszczyk <jaszczyk@chromium.org>
AuthorDate: Thu, 24 Sep 2026 10:40:20
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Mon, 19 Oct 2026 18:21:25 -07:00
x86/apic: Remove redundant check from x2apic_phys_probe()
Commit
9ebd680bd029 ("x86, apic: Use probe routines to simplify apic selection")
introduced x2apic_phys_probe() with a generic fallback check for
apic == &apic_x2apic_phys
to preserve any prior selection of apic_x2apic_phys by default_acpi_madt_oem_check().
At the time, x2apic_acpi_madt_oem_check() only checked
x2apic_phys && x2apic_enabled()
so that fallback was already redundant. Commit
ea0dcf903e7d ("x86/apic: Use x2apic physical mode based on FADT setting")
later added the ACPI_FADT_APIC_PHYSICAL check only to x2apic_acpi_madt_oem_check(),
temporarily relying on the fallback in x2apic_phys_probe() when x2APIC was
pre-enabled by BIOS.
Subsequently,
cb214ede7657 ("x86/apic: Work around boot failure on HP ProLiant DL980 G7 Server systems")
factored out x2apic_fadt_phys() and added it directly to x2apic_phys_probe(). Because
default_acpi_madt_oem_check() (via the .acpi_madt_oem_check callback) is the only
path that can install apic_x2apic_phys prior to x2apic_phys_probe(), and
x2apic_acpi_madt_oem_check() checks the exact same
x2apic_phys || x2apic_fadt_phys()
condition, the fallback
apic == &apic_x2apic_phys
check became completely unreachable again.
Remove the redundant check and the associated forward declaration of apic_x2apic_phys.
In addition to cleaning up dead code, this allows apic_x2apic_phys to be installed as
an early boot default driver when hardware x2APIC is pre-enabled without preventing
x2apic_cluster from being probed and selected later during boot.
[ bp: Massage commit message. ]
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260924104102.3534474-4-jaszczyk@chromium.org
---
arch/x86/kernel/apic/x2apic_phys.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 090647c..5bf8683 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -6,8 +6,6 @@
#include "local.h"
int x2apic_phys;
-
-static struct apic apic_x2apic_phys;
u32 x2apic_max_apicid __ro_after_init = UINT_MAX;
void __init x2apic_set_max_apicid(u32 apicid)
@@ -110,10 +108,7 @@ static int x2apic_phys_probe(void)
if (!x2apic_mode)
return 0;
- if (x2apic_phys || x2apic_fadt_phys())
- return 1;
-
- return apic == &apic_x2apic_phys;
+ return x2apic_phys || x2apic_fadt_phys();
}
u32 x2apic_get_apic_id(u32 id)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 4/4] x86/apic: Switch to x2apic driver early if x2apic is enabled
2026-09-24 10:40 [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
` (2 preceding siblings ...)
2026-09-24 10:40 ` [PATCH v2 3/4] x86/apic: Remove redundant check from x2apic_phys_probe() Grzegorz Jaszczyk
@ 2026-09-24 10:40 ` Grzegorz Jaszczyk
2026-10-20 18:32 ` [tip: x86/apic] " tip-bot2 for Grzegorz Jaszczyk
2026-10-17 21:04 ` [PATCH v2 0/4] " Thomas Gleixner
4 siblings, 1 reply; 10+ messages in thread
From: Grzegorz Jaszczyk @ 2026-09-24 10:40 UTC (permalink / raw)
To: tglx
Cc: linux-kernel, dmaluka, vineethrp, chuanxiao.dong, jaszczyk,
Grzegorz Jaszczyk, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Juergen Gross,
Peter Zijlstra (Intel),
Radu Rendec, Julian Stecklina, Ahmed S. Darwish, Thierry Reding,
Naveen N Rao (AMD),
Melody Wang, Eric Dumazet
During early boot, the generic x86 kernel defaults to the MMIO-based
APIC driver (apic_physflat). However, if the kernel is booted (e.g., via
kexec) when x2APIC is already enabled in hardware, the MMIO interface to
the APIC is disabled.
Normally, ACPI MADT probing would install an x2APIC driver early.
However, if ACPI is disabled (e.g., CONFIG_ACPI is not set, as in
crashdump kernels), x86_64_probe_apic() does not run until
late_time_init() via apic_intr_mode_init().
This creates a window between local_irq_enable() and late_time_init()
where interrupts are enabled, but the APIC driver pointer still points
to apic_physflat. Because check_x2apic() detected hardware x2APIC mode
and set x2apic_mode = 1, register_lapic_address() and
apic_finalize_early_init() skip mapping the APIC fixmap. If a pending
interrupt (e.g., left in IRR across kexec on secondary CPUs) fires
during this window, native_apic_mem_eoi() is invoked, which attempts to
write to the unmapped APIC EOI register, triggering an immediate kernel
page fault (#PF).
To prevent this, replace apic_setup_apic_calls() with
apic_install_default_driver(), have check_x2apic() return
&apic_x2apic_phys when hardware x2APIC is enabled (or &apic_noop if
x2APIC is enabled on a kernel built without CONFIG_X86_X2APIC), and
install it as the default APIC driver in apic_early_init(). Similarly,
if the local APIC is disabled via command line (apic_is_disabled) or
acpi_mps_check(), install &apic_noop immediately as the default driver.
This ensures safe MSR-based or no-op APIC accesses during early boot
while still allowing normal APIC probing (such as upgrading to
apic_x2apic_cluster) to take place later during boot.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
---
arch/x86/include/asm/apic.h | 4 ----
arch/x86/kernel/apic/apic.c | 22 ++++++++++++++------
arch/x86/kernel/apic/init.c | 32 +++++++++++++++++++-----------
arch/x86/kernel/apic/local.h | 4 ++++
arch/x86/kernel/apic/x2apic_phys.c | 2 +-
5 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index b1610b8bc6544..0b11b7033458f 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -367,9 +367,6 @@ extern int lapic_can_unplug_cpu(void);
#ifdef CONFIG_X86_LOCAL_APIC
extern struct apic_override __x86_apic_override;
-void __init apic_setup_apic_calls(void);
-void __init apic_install_driver(struct apic *driver);
-
#define apic_update_callback(_callback, _fn) { \
__x86_apic_override._callback = _fn; \
apic->_callback = _fn; \
@@ -487,7 +484,6 @@ static inline void apic_icr_write(u32 low, u32 high) { }
static inline void apic_wait_icr_idle(void) { }
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
-static inline void apic_setup_apic_calls(void) { }
static inline void apic_update_vector(unsigned int cpu, unsigned int vector, bool set) { }
#define apic_update_callback(_callback, _fn) do { } while (0)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 721e194ceac2d..3583fcd6f0c55 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1869,7 +1869,7 @@ static __init void try_to_enable_x2apic(int remap_mode)
x2apic_enable();
}
-static void __init check_x2apic(void)
+static __init struct apic *check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
@@ -1879,15 +1879,21 @@ static void __init check_x2apic(void)
else
x2apic_state = X2APIC_ON;
apic_read_boot_cpu_id(true);
+
+ /* Force the initial driver to X2APIC */
+ return &apic_x2apic_phys;
} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
x2apic_state = X2APIC_DISABLED;
}
+
+ /* Keep the default driver */
+ return NULL;
}
#else /* CONFIG_X86_X2APIC */
-static void __init check_x2apic(void)
+static __init struct apic *check_x2apic(void)
{
if (!apic_is_x2apic_enabled())
- return;
+ return NULL;
/*
* Checkme: Can we simply turn off x2APIC here instead of disabling the APIC?
*/
@@ -1896,6 +1902,7 @@ static void __init check_x2apic(void)
apic_is_disabled = true;
setup_clear_cpu_cap(X86_FEATURE_APIC);
+ return &apic_noop;
}
static inline void try_to_enable_x2apic(int remap_mode) { }
@@ -2066,14 +2073,17 @@ static bool __init detect_init_APIC(void)
void __init apic_early_init(void)
{
- if (acpi_mps_check()) {
+ struct apic *driver;
+
+ if (apic_is_disabled || acpi_mps_check()) {
apic_is_disabled = true;
setup_clear_cpu_cap(X86_FEATURE_APIC);
+ driver = &apic_noop;
} else {
- check_x2apic();
+ driver = check_x2apic();
}
- apic_setup_apic_calls();
+ apic_install_default_driver(driver);
}
void __init apic_finalize_early_init(void)
diff --git a/arch/x86/kernel/apic/init.c b/arch/x86/kernel/apic/init.c
index 821e2e536f19c..a25ad263c4236 100644
--- a/arch/x86/kernel/apic/init.c
+++ b/arch/x86/kernel/apic/init.c
@@ -80,19 +80,8 @@ static __init void update_static_calls(void)
update_call(wakeup_secondary_cpu_64);
}
-void __init apic_setup_apic_calls(void)
+static void __init __apic_install_driver(struct apic *driver)
{
- /* Ensure that the default APIC has native_eoi populated */
- apic->native_eoi = apic->eoi;
- update_static_calls();
- pr_info("Static calls initialized\n");
-}
-
-void __init apic_install_driver(struct apic *driver)
-{
- if (apic == driver)
- return;
-
apic = driver;
if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
@@ -105,6 +94,25 @@ void __init apic_install_driver(struct apic *driver)
/* Apply any already installed callback overrides */
restore_override_callbacks();
update_static_calls();
+}
+
+void __init apic_install_default_driver(struct apic *driver)
+{
+ if (driver) {
+ __apic_install_driver(driver);
+ } else {
+ /* Ensure that the default APIC has the native_eoi() callback populated */
+ apic->native_eoi = apic->eoi;
+ update_static_calls();
+ }
+ pr_info("Set default APIC routing to: %s\n", apic->name);
+}
+
+void __init apic_install_driver(struct apic *driver)
+{
+ if (apic == driver)
+ return;
+ __apic_install_driver(driver);
pr_info("Switched APIC routing to: %s\n", driver->name);
}
diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h
index 090dd71837aab..84890e428abf2 100644
--- a/arch/x86/kernel/apic/local.h
+++ b/arch/x86/kernel/apic/local.h
@@ -13,12 +13,16 @@
#include <asm/irq_vectors.h>
#include <asm/apic.h>
+void __init apic_install_default_driver(struct apic *driver);
+void __init apic_install_driver(struct apic *driver);
+
/* X2APIC */
u32 x2apic_get_apic_id(u32 id);
void x2apic_send_IPI_all(int vector);
void x2apic_send_IPI_allbutself(int vector);
void x2apic_send_IPI_self(int vector);
+extern struct apic apic_x2apic_phys;
extern u32 x2apic_max_apicid;
/* IPI */
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 5bf86839e84c3..74d7c0d5b203e 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -116,7 +116,7 @@ u32 x2apic_get_apic_id(u32 id)
return id;
}
-static struct apic apic_x2apic_phys __ro_after_init = {
+struct apic apic_x2apic_phys __ro_after_init = {
.name = "physical x2apic",
.probe = x2apic_phys_probe,
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 10+ messages in thread* [tip: x86/apic] x86/apic: Switch to x2apic driver early if x2apic is enabled
2026-09-24 10:40 ` [PATCH v2 4/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
@ 2026-10-20 18:32 ` tip-bot2 for Grzegorz Jaszczyk
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot2 for Grzegorz Jaszczyk @ 2026-10-20 18:32 UTC (permalink / raw)
To: linux-tip-commits
Cc: Thomas Gleixner, Grzegorz Jaszczyk, Borislav Petkov (AMD),
Thomas Gleixner, x86, linux-kernel
The following commit has been merged into the x86/apic branch of tip:
Commit-ID: 37b841b51a2689da002350c295deac91946c0881
Gitweb: https://git.kernel.org/tip/37b841b51a2689da002350c295deac91946c0881
Author: Grzegorz Jaszczyk <jaszczyk@chromium.org>
AuthorDate: Thu, 24 Sep 2026 10:40:21
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Mon, 19 Oct 2026 18:35:37 -07:00
x86/apic: Switch to x2apic driver early if x2apic is enabled
During early boot, the generic x86 kernel defaults to the MMIO-based APIC driver
(apic_physflat). However, if the kernel is booted (e.g., via kexec) when x2APIC is
already enabled in hardware, the MMIO interface to the APIC is disabled.
Normally, ACPI MADT probing would install an x2APIC driver early. However, if ACPI
is disabled (e.g., CONFIG_ACPI is not set, as in crashdump kernels), x86_64_probe_apic()
does not run until late_time_init() via apic_intr_mode_init().
This creates a window between local_irq_enable() and late_time_init() where
interrupts are enabled, but the APIC driver pointer still points to apic_physflat.
Because check_x2apic() detected hardware x2APIC mode and set x2apic_mode = 1,
register_lapic_address() and apic_finalize_early_init() skip mapping the APIC fixmap.
If a pending interrupt (e.g., left in IRR across kexec on secondary CPUs) fires
during this window, native_apic_mem_eoi() is invoked, which attempts to write to the
unmapped APIC EOI register, triggering an immediate kernel page fault (#PF).
To prevent this, make x2APIC the default driver on hardware which supports it.
Similarly, if the local APIC is disabled via command line (apic_is_disabled) or
acpi_mps_check(), install &apic_noop immediately as the default driver.
This ensures safe MSR-based or no-op APIC accesses during early boot while still
allowing normal APIC probing (such as upgrading to apic_x2apic_cluster) to take place
later during boot.
[ bp: Massage commit message. ]
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Grzegorz Jaszczyk <jaszczyk@chromium.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260924104102.3534474-5-jaszczyk@chromium.org
---
arch/x86/include/asm/apic.h | 4 +----
arch/x86/kernel/apic/apic.c | 22 ++++++++++++++------
arch/x86/kernel/apic/init.c | 32 ++++++++++++++++++-----------
arch/x86/kernel/apic/local.h | 4 ++++-
arch/x86/kernel/apic/x2apic_phys.c | 2 +-
5 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index b1610b8..0b11b70 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -367,9 +367,6 @@ extern int lapic_can_unplug_cpu(void);
#ifdef CONFIG_X86_LOCAL_APIC
extern struct apic_override __x86_apic_override;
-void __init apic_setup_apic_calls(void);
-void __init apic_install_driver(struct apic *driver);
-
#define apic_update_callback(_callback, _fn) { \
__x86_apic_override._callback = _fn; \
apic->_callback = _fn; \
@@ -487,7 +484,6 @@ static inline void apic_icr_write(u32 low, u32 high) { }
static inline void apic_wait_icr_idle(void) { }
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
-static inline void apic_setup_apic_calls(void) { }
static inline void apic_update_vector(unsigned int cpu, unsigned int vector, bool set) { }
#define apic_update_callback(_callback, _fn) do { } while (0)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 721e194..3583fcd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1869,7 +1869,7 @@ static __init void try_to_enable_x2apic(int remap_mode)
x2apic_enable();
}
-static void __init check_x2apic(void)
+static __init struct apic *check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
@@ -1879,15 +1879,21 @@ static void __init check_x2apic(void)
else
x2apic_state = X2APIC_ON;
apic_read_boot_cpu_id(true);
+
+ /* Force the initial driver to X2APIC */
+ return &apic_x2apic_phys;
} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
x2apic_state = X2APIC_DISABLED;
}
+
+ /* Keep the default driver */
+ return NULL;
}
#else /* CONFIG_X86_X2APIC */
-static void __init check_x2apic(void)
+static __init struct apic *check_x2apic(void)
{
if (!apic_is_x2apic_enabled())
- return;
+ return NULL;
/*
* Checkme: Can we simply turn off x2APIC here instead of disabling the APIC?
*/
@@ -1896,6 +1902,7 @@ static void __init check_x2apic(void)
apic_is_disabled = true;
setup_clear_cpu_cap(X86_FEATURE_APIC);
+ return &apic_noop;
}
static inline void try_to_enable_x2apic(int remap_mode) { }
@@ -2066,14 +2073,17 @@ no_apic:
void __init apic_early_init(void)
{
- if (acpi_mps_check()) {
+ struct apic *driver;
+
+ if (apic_is_disabled || acpi_mps_check()) {
apic_is_disabled = true;
setup_clear_cpu_cap(X86_FEATURE_APIC);
+ driver = &apic_noop;
} else {
- check_x2apic();
+ driver = check_x2apic();
}
- apic_setup_apic_calls();
+ apic_install_default_driver(driver);
}
void __init apic_finalize_early_init(void)
diff --git a/arch/x86/kernel/apic/init.c b/arch/x86/kernel/apic/init.c
index 821e2e5..a25ad26 100644
--- a/arch/x86/kernel/apic/init.c
+++ b/arch/x86/kernel/apic/init.c
@@ -80,19 +80,8 @@ static __init void update_static_calls(void)
update_call(wakeup_secondary_cpu_64);
}
-void __init apic_setup_apic_calls(void)
+static void __init __apic_install_driver(struct apic *driver)
{
- /* Ensure that the default APIC has native_eoi populated */
- apic->native_eoi = apic->eoi;
- update_static_calls();
- pr_info("Static calls initialized\n");
-}
-
-void __init apic_install_driver(struct apic *driver)
-{
- if (apic == driver)
- return;
-
apic = driver;
if (IS_ENABLED(CONFIG_X86_X2APIC) && apic->x2apic_set_max_apicid)
@@ -105,6 +94,25 @@ void __init apic_install_driver(struct apic *driver)
/* Apply any already installed callback overrides */
restore_override_callbacks();
update_static_calls();
+}
+
+void __init apic_install_default_driver(struct apic *driver)
+{
+ if (driver) {
+ __apic_install_driver(driver);
+ } else {
+ /* Ensure that the default APIC has the native_eoi() callback populated */
+ apic->native_eoi = apic->eoi;
+ update_static_calls();
+ }
+ pr_info("Set default APIC routing to: %s\n", apic->name);
+}
+
+void __init apic_install_driver(struct apic *driver)
+{
+ if (apic == driver)
+ return;
+ __apic_install_driver(driver);
pr_info("Switched APIC routing to: %s\n", driver->name);
}
diff --git a/arch/x86/kernel/apic/local.h b/arch/x86/kernel/apic/local.h
index 090dd71..84890e4 100644
--- a/arch/x86/kernel/apic/local.h
+++ b/arch/x86/kernel/apic/local.h
@@ -13,12 +13,16 @@
#include <asm/irq_vectors.h>
#include <asm/apic.h>
+void __init apic_install_default_driver(struct apic *driver);
+void __init apic_install_driver(struct apic *driver);
+
/* X2APIC */
u32 x2apic_get_apic_id(u32 id);
void x2apic_send_IPI_all(int vector);
void x2apic_send_IPI_allbutself(int vector);
void x2apic_send_IPI_self(int vector);
+extern struct apic apic_x2apic_phys;
extern u32 x2apic_max_apicid;
/* IPI */
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 5bf8683..74d7c0d 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -116,7 +116,7 @@ u32 x2apic_get_apic_id(u32 id)
return id;
}
-static struct apic apic_x2apic_phys __ro_after_init = {
+struct apic apic_x2apic_phys __ro_after_init = {
.name = "physical x2apic",
.probe = x2apic_phys_probe,
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled
2026-09-24 10:40 [PATCH v2 0/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
` (3 preceding siblings ...)
2026-09-24 10:40 ` [PATCH v2 4/4] x86/apic: Switch to x2apic driver early if x2apic is enabled Grzegorz Jaszczyk
@ 2026-10-17 21:04 ` Thomas Gleixner
4 siblings, 0 replies; 10+ messages in thread
From: Thomas Gleixner @ 2026-10-17 21:04 UTC (permalink / raw)
To: Grzegorz Jaszczyk
Cc: linux-kernel, dmaluka, vineethrp, chuanxiao.dong, jaszczyk,
Grzegorz Jaszczyk
On Thu, Sep 24 2026 at 10:40, Grzegorz Jaszczyk wrote:
> During early boot, the generic x86 kernel defaults to the MMIO-based
> APIC driver (apic_physflat). When booting (e.g., via kexec into a
> crashdump kernel) with x2APIC already enabled in hardware and without
> ACPI MADT probing (e.g., !CONFIG_ACPI), the APIC driver pointer remains
> set to apic_physflat until late_time_init() runs x86_64_probe_apic().
>
> Because check_x2apic() detects hardware x2APIC mode and sets
> x2apic_mode = 1, the APIC MMIO fixmap is not mapped. If a pending
> interrupt fires in the window between local_irq_enable() and
> late_time_init(), native_apic_mem_eoi() attempts to write to the
> unmapped APIC EOI MMIO address, resulting in an early boot page fault
> (#PF).
>
> This series restructures early APIC initialization and installs
> apic_x2apic_phys (or apic_noop if the APIC is disabled or built without
> CONFIG_X86_X2APIC) as the default APIC driver in apic_early_init(),
> ensuring safe MSR-based or no-op APIC accesses while still allowing
> later APIC probing (e.g., upgrading to apic_x2apic_cluster) to proceed
> normally.
Reviewed-by: Thomas Gleixner <tglx@kernel.org>
^ permalink raw reply [flat|nested] 10+ messages in thread