aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>2016-10-11 16:54:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-11 18:06:32 -0400
commit0ee59413c967c35a6dd2dbdab605b4cd42025ee5 (patch)
treee3325918b5b8d40924eac2b3cc2f2a1f8467048a /arch/x86/kernel
parent2b6b535d9158b822a45080b3d6d5b2993fd49e5a (diff)
x86/panic: replace smp_send_stop() with kdump friendly version in panic path
Daniel Walker reported problems which happens when crash_kexec_post_notifiers kernel option is enabled (https://lkml.org/lkml/2015/6/24/44). In that case, smp_send_stop() is called before entering kdump routines which assume other CPUs are still online. As the result, for x86, kdump routines fail to save other CPUs' registers and disable virtualization extensions. To fix this problem, call a new kdump friendly function, crash_smp_send_stop(), instead of the smp_send_stop() when crash_kexec_post_notifiers is enabled. crash_smp_send_stop() is a weak function, and it just call smp_send_stop(). Architecture codes should override it so that kdump can work appropriately. This patch only provides x86-specific version. For Xen's PV kernel, just keep the current behavior. NOTES: - Right solution would be to place crash_smp_send_stop() before __crash_kexec() invocation in all cases and remove smp_send_stop(), but we can't do that until all architectures implement own crash_smp_send_stop() - crash_smp_send_stop()-like work is still needed by machine_crash_shutdown() because crash_kexec() can be called without entering panic() Fixes: f06e5153f4ae (kernel/panic.c: add "crash_kexec_post_notifiers" option) Link: http://lkml.kernel.org/r/20160810080948.11028.15344.stgit@sysi4-13.yrl.intra.hitachi.co.jp Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Reported-by: Daniel Walker <dwalker@fifo99.com> Cc: Dave Young <dyoung@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Eric Biederman <ebiederm@xmission.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Daniel Walker <dwalker@fifo99.com> Cc: Xunlei Pang <xpang@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Borislav Petkov <bp@suse.de> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Toshi Kani <toshi.kani@hpe.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: David Daney <david.daney@cavium.com> Cc: Aaro Koskinen <aaro.koskinen@iki.fi> Cc: "Steven J. Hill" <steven.hill@cavium.com> Cc: Corey Minyard <cminyard@mvista.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/crash.c22
-rw-r--r--arch/x86/kernel/smp.c5
2 files changed, 24 insertions, 3 deletions
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 9616cf76940c..650830e39e3a 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -133,15 +133,31 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
133 disable_local_APIC(); 133 disable_local_APIC();
134} 134}
135 135
136static void kdump_nmi_shootdown_cpus(void) 136void kdump_nmi_shootdown_cpus(void)
137{ 137{
138 nmi_shootdown_cpus(kdump_nmi_callback); 138 nmi_shootdown_cpus(kdump_nmi_callback);
139 139
140 disable_local_APIC(); 140 disable_local_APIC();
141} 141}
142 142
143/* Override the weak function in kernel/panic.c */
144void crash_smp_send_stop(void)
145{
146 static int cpus_stopped;
147
148 if (cpus_stopped)
149 return;
150
151 if (smp_ops.crash_stop_other_cpus)
152 smp_ops.crash_stop_other_cpus();
153 else
154 smp_send_stop();
155
156 cpus_stopped = 1;
157}
158
143#else 159#else
144static void kdump_nmi_shootdown_cpus(void) 160void crash_smp_send_stop(void)
145{ 161{
146 /* There are no cpus to shootdown */ 162 /* There are no cpus to shootdown */
147} 163}
@@ -160,7 +176,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
160 /* The kernel is broken so disable interrupts */ 176 /* The kernel is broken so disable interrupts */
161 local_irq_disable(); 177 local_irq_disable();
162 178
163 kdump_nmi_shootdown_cpus(); 179 crash_smp_send_stop();
164 180
165 /* 181 /*
166 * VMCLEAR VMCSs loaded on this cpu if needed. 182 * VMCLEAR VMCSs loaded on this cpu if needed.
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 658777cf3851..68f8cc222f25 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -32,6 +32,8 @@
32#include <asm/nmi.h> 32#include <asm/nmi.h>
33#include <asm/mce.h> 33#include <asm/mce.h>
34#include <asm/trace/irq_vectors.h> 34#include <asm/trace/irq_vectors.h>
35#include <asm/kexec.h>
36
35/* 37/*
36 * Some notes on x86 processor bugs affecting SMP operation: 38 * Some notes on x86 processor bugs affecting SMP operation:
37 * 39 *
@@ -342,6 +344,9 @@ struct smp_ops smp_ops = {
342 .smp_cpus_done = native_smp_cpus_done, 344 .smp_cpus_done = native_smp_cpus_done,
343 345
344 .stop_other_cpus = native_stop_other_cpus, 346 .stop_other_cpus = native_stop_other_cpus,
347#if defined(CONFIG_KEXEC_CORE)
348 .crash_stop_other_cpus = kdump_nmi_shootdown_cpus,
349#endif
345 .smp_send_reschedule = native_smp_send_reschedule, 350 .smp_send_reschedule = native_smp_send_reschedule,
346 351
347 .cpu_up = native_cpu_up, 352 .cpu_up = native_cpu_up,