57 lines
1.8 KiB
Diff
57 lines
1.8 KiB
Diff
|
# HG changeset patch
|
||
|
# User Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
# Date 1313744302 -3600
|
||
|
# Node ID 0ddb4481f883ddf55c12a0b8d1445cf137ef0b63
|
||
|
# Parent 9957bef3e7b4511f83ed8883cd5ecd49ea3ee95d
|
||
|
x86/KEXEC: disable hpet legacy broadcasts earlier
|
||
|
|
||
|
On x2apic machines which booted in xapic mode,
|
||
|
hpet_disable_legacy_broadcast() sends an event check IPI to all online
|
||
|
processors. This leads to a protection fault as the genapic blindly
|
||
|
pokes x2apic MSRs while the local apic is in xapic mode.
|
||
|
|
||
|
One option is to change genapic when we shut down the local apic, but
|
||
|
there are still problems with trying to IPI processors in the online
|
||
|
processor map which are actually sitting in NMI loops
|
||
|
|
||
|
Another option is to have each CPU take itself out of the online CPU
|
||
|
map during the NMI shootdown.
|
||
|
|
||
|
Realistically however, disabling hpet legacy broadcasts earlier in the
|
||
|
kexec path is the easiest fix to the problem.
|
||
|
|
||
|
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
|
||
|
--- a/xen/arch/x86/crash.c
|
||
|
+++ b/xen/arch/x86/crash.c
|
||
|
@@ -27,6 +27,7 @@
|
||
|
#include <asm/hvm/support.h>
|
||
|
#include <asm/apic.h>
|
||
|
#include <asm/io_apic.h>
|
||
|
+#include <asm/hpet.h>
|
||
|
|
||
|
static atomic_t waiting_for_crash_ipi;
|
||
|
static unsigned int crashing_cpu;
|
||
|
@@ -59,6 +60,9 @@ static void nmi_shootdown_cpus(void)
|
||
|
|
||
|
local_irq_disable();
|
||
|
|
||
|
+ if ( hpet_broadcast_is_available() )
|
||
|
+ hpet_disable_legacy_broadcast();
|
||
|
+
|
||
|
crashing_cpu = smp_processor_id();
|
||
|
local_irq_count(crashing_cpu) = 0;
|
||
|
|
||
|
--- a/xen/arch/x86/machine_kexec.c
|
||
|
+++ b/xen/arch/x86/machine_kexec.c
|
||
|
@@ -96,9 +96,6 @@ void machine_kexec(xen_kexec_image_t *im
|
||
|
.limit = LAST_RESERVED_GDT_BYTE
|
||
|
};
|
||
|
|
||
|
- if ( hpet_broadcast_is_available() )
|
||
|
- hpet_disable_legacy_broadcast();
|
||
|
-
|
||
|
/*
|
||
|
* compat_machine_kexec() returns to idle pagetables, which requires us
|
||
|
* to be running on a static GDT mapping (idle pagetables have no GDT
|