[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] x86/kexec: Check for a good per-cpu area before accessing IDTs



commit 2c9829a2611e4ac1d9200af6f159605fc8849bf2
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Jun 22 17:51:10 2026 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Jun 23 19:15:51 2026 +0100

    x86/kexec: Check for a good per-cpu area before accessing IDTs
    
    Prior to commit 9c20d3c5915d ("x86/IDT: Make idt_tables[] be per_cpu(idt)"),
    the global idt_tables[] was always safe to use for CPUs in any state.
    
    However, not-yet-onlined CPUs (e.g. MADT with more entries than exist in
    practice) or offlined CPUs (e.g. xen-hptool) have their per-cpu pointer
    poisoned to detect incorrect uses.  machine_kexec() trips over the posion 
when
    clobbering #MC entry paths.  Update the comment to discuss parked CPUs, and 
to
    remove discussion which isn't particularly relevant to the actions at hand.
    
    This fixes a fatal #GP (non-canonical memory reference) when trying to enter
    the crash kernel.
    
    Fixes: 9c20d3c5915d ("x86/IDT: Make idt_tables[] be per_cpu(idt)")
    Reported-by: Lin Liu <Lin.Liu01@xxxxxxxxxx>
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
 xen/arch/x86/machine_kexec.c | 19 ++++++++++---------
 xen/common/percpu.c          |  1 -
 xen/include/xen/percpu.h     |  1 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c
index f921eec5aa..038670922d 100644
--- a/xen/arch/x86/machine_kexec.c
+++ b/xen/arch/x86/machine_kexec.c
@@ -18,6 +18,7 @@
 #include <xen/domain_page.h>
 #include <xen/elfstructs.h>
 #include <xen/kexec.h>
+#include <xen/percpu.h>
 #include <xen/types.h>
 
 #include <asm/fixmap.h>
@@ -159,19 +160,19 @@ void machine_kexec(struct kexec_image *image)
      */
     local_irq_disable();
 
-    /* Now regular interrupts are disabled, we need to reduce the impact
-     * of interrupts not disabled by 'cli'.
-     *
-     * The NMI handlers have already been set up nmi_shootdown_cpus().  All
-     * pcpus other than us have the nmi_crash handler, while we have the nop
-     * handler.
-     *
+    /*
      * The MCE handlers touch extensive areas of Xen code and data.  At this
-     * point, there is nothing we can usefully do, so set the nop handler.
+     * point, there is nothing we can usefully do, so set the NOP handler even
+     * for parked CPUs.
      */
     for ( i = 0; i < nr_cpu_ids; i++ )
     {
-        idt_entry_t *idt = per_cpu(idt, i);
+        idt_entry_t *idt;
+
+        if ( __per_cpu_offset[i] == INVALID_PERCPU_AREA )
+            continue;
+
+        idt = per_cpu(idt, i);
 
         if ( !idt )
             continue;
diff --git a/xen/common/percpu.c b/xen/common/percpu.c
index cdd70acbea..f180f37253 100644
--- a/xen/common/percpu.c
+++ b/xen/common/percpu.c
@@ -13,7 +13,6 @@
 
 #define PERCPU_ORDER get_order_from_bytes(__per_cpu_data_end - __per_cpu_start)
 
-extern char __per_cpu_start[];
 extern const char __per_cpu_data_end[];
 
 unsigned long __read_mostly __per_cpu_offset[NR_CPUS];
diff --git a/xen/include/xen/percpu.h b/xen/include/xen/percpu.h
index fcf2095bd5..30609f49f0 100644
--- a/xen/include/xen/percpu.h
+++ b/xen/include/xen/percpu.h
@@ -43,6 +43,7 @@
 #endif
 
 extern unsigned long __per_cpu_offset[];
+extern char __per_cpu_start[];
 
 #define per_cpu(var, cpu)  \
     (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.