Synchronize machine check panics with MCE broadcasts For recent kernels before 2.6.31 Signed-off-by: Andi Kleen --- arch/x86/kernel/cpu/mcheck/mce_64.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) Index: linux/arch/x86/kernel/cpu/mcheck/mce_64.c =================================================================== --- linux.orig/arch/x86/kernel/cpu/mcheck/mce_64.c +++ linux/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -147,6 +147,33 @@ static void print_mce(struct mce *m) "and contact your hardware vendor\n"); } +static void print_mce_panic(char *msg) +{ + static atomic_t mce_entry; + /* + * Machine check panics often come up from multiple CPUs in parallel. + * panic doesn't handle that well and deadlocks, so synchronize here. + */ + int first = atomic_add_return(1, &mce_entry) == 1; + + if (!first) { + printk("CPU %d: MCE PANIC: %s\n", smp_processor_id(), msg); + /* + * Enable interrupts so that smp_stop_cpus() can interrupts us, + * but prevent scheduling in case someone compiles this + * preemptible. + * Then wait for the other panic to shut us down. + */ + preempt_disable(); + local_irq_enable(); + for (;;) + cpu_relax(); + } + + oops_in_progress = 1; + panic(msg); +} + static void mce_panic(char *msg, struct mce *backup, unsigned long start) { int i; @@ -163,7 +190,7 @@ static void mce_panic(char *msg, struct } if (backup) print_mce(backup); - panic(msg); + print_mce_panic(msg); } int mce_available(struct cpuinfo_x86 *c)