61 lines
2.2 KiB
Diff
61 lines
2.2 KiB
Diff
|
# Commit 2a16fcd5ba0244fef764886211452acc69c0ed00
|
||
|
# Date 2013-11-22 14:48:12 +0100
|
||
|
# Author David Vrabel <david.vrabel@citrix.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
x86/crash: disable the watchdog NMIs on the crashing cpu
|
||
|
|
||
|
nmi_shootdown_cpus() is called during a crash to park all the other
|
||
|
CPUs. This changes the NMI trap handlers which means there's no point
|
||
|
in having the watchdog still running.
|
||
|
|
||
|
This also disables the watchdog before executing any crash kexec image
|
||
|
and prevents the image from receiving unexpected NMIs.
|
||
|
|
||
|
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
|
||
|
|
||
|
PVOps Linux as a kexec image shoots itself in the foot otherwise.
|
||
|
|
||
|
On a Core2 system, Linux declares a firmware bug and tries to invert some bits
|
||
|
in the performance counter register. It ends up setting the number of retired
|
||
|
instructions to generate another NMI to fewer instructions than the NMI
|
||
|
interrupt path itself, and ceases to make any useful progress.
|
||
|
|
||
|
The call to disable_lapic_nmi_watchdog() must be this late into the kexec path
|
||
|
to be sure that this cpu is the one which will execute the kexec image.
|
||
|
Otherwise there are race conditions where the NMIs might be disabled on the
|
||
|
wrong cpu, resulting in the kexec image still receiving NMIs.
|
||
|
|
||
|
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
|
||
|
--- a/xen/arch/x86/crash.c
|
||
|
+++ b/xen/arch/x86/crash.c
|
||
|
@@ -117,6 +117,7 @@ static void nmi_shootdown_cpus(void)
|
||
|
unsigned long msecs;
|
||
|
int i, cpu = smp_processor_id();
|
||
|
|
||
|
+ disable_lapic_nmi_watchdog();
|
||
|
local_irq_disable();
|
||
|
|
||
|
crashing_cpu = cpu;
|
||
|
--- a/xen/arch/x86/nmi.c
|
||
|
+++ b/xen/arch/x86/nmi.c
|
||
|
@@ -165,7 +165,7 @@ static void nmi_timer_fn(void *unused)
|
||
|
set_timer(&this_cpu(nmi_timer), NOW() + MILLISECS(1000));
|
||
|
}
|
||
|
|
||
|
-static void disable_lapic_nmi_watchdog(void)
|
||
|
+void disable_lapic_nmi_watchdog(void)
|
||
|
{
|
||
|
if (nmi_active <= 0)
|
||
|
return;
|
||
|
--- a/xen/include/asm-x86/apic.h
|
||
|
+++ b/xen/include/asm-x86/apic.h
|
||
|
@@ -200,6 +200,7 @@ extern void smp_local_timer_interrupt (s
|
||
|
extern void setup_boot_APIC_clock (void);
|
||
|
extern void setup_secondary_APIC_clock (void);
|
||
|
extern void setup_apic_nmi_watchdog (void);
|
||
|
+extern void disable_lapic_nmi_watchdog(void);
|
||
|
extern int reserve_lapic_nmi(void);
|
||
|
extern void release_lapic_nmi(void);
|
||
|
extern void self_nmi(void);
|