Merge tag 'arm64-perf' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[cascardo/linux.git] / arch / x86 / kernel / nmi.c
index 697f90d..8a2cdd7 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach_traps.h>
 #include <asm/nmi.h>
 #include <asm/x86_init.h>
+#include <asm/reboot.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/nmi.h>
@@ -231,7 +232,7 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs)
 #endif
 
        if (panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
+               nmi_panic(regs, "NMI: Not continuing");
 
        pr_emerg("Dazed and confused, but trying to continue\n");
 
@@ -255,8 +256,16 @@ io_check_error(unsigned char reason, struct pt_regs *regs)
                 reason, smp_processor_id());
        show_regs(regs);
 
-       if (panic_on_io_nmi)
-               panic("NMI IOCK error: Not continuing");
+       if (panic_on_io_nmi) {
+               nmi_panic(regs, "NMI IOCK error: Not continuing");
+
+               /*
+                * If we end up here, it means we have received an NMI while
+                * processing panic(). Simply return without delaying and
+                * re-enabling NMIs.
+                */
+               return;
+       }
 
        /* Re-enable the IOCK line, wait for a few seconds */
        reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
@@ -297,7 +306,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
 
        pr_emerg("Do you have a strange power saving mode enabled?\n");
        if (unknown_nmi_panic || panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
+               nmi_panic(regs, "NMI: Not continuing");
 
        pr_emerg("Dazed and confused, but trying to continue\n");
 }
@@ -348,8 +357,19 @@ static void default_do_nmi(struct pt_regs *regs)
                return;
        }
 
-       /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
-       raw_spin_lock(&nmi_reason_lock);
+       /*
+        * Non-CPU-specific NMI: NMI sources can be processed on any CPU.
+        *
+        * Another CPU may be processing panic routines while holding
+        * nmi_reason_lock. Check if the CPU issued the IPI for crash dumping,
+        * and if so, call its callback directly.  If there is no CPU preparing
+        * crash dump, we simply loop here.
+        */
+       while (!raw_spin_trylock(&nmi_reason_lock)) {
+               run_crash_ipi_callback(regs);
+               cpu_relax();
+       }
+
        reason = x86_platform.get_nmi_reason();
 
        if (reason & NMI_REASON_MASK) {