]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/kernel/cpu/mcheck/mce.c
Merge branch 'ras/urgent' into ras/core, to pick up fix
[karo-tx-linux.git] / arch / x86 / kernel / cpu / mcheck / mce.c
index 5accfbdee3f06fac48eaf4423d66d7bee1e3a0a3..e95e02734f250bbe3b98a44a270d58fb930b6a59 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/tlbflush.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
+#include <asm/reboot.h>
 
 #include "mce-internal.h"
 
@@ -1133,9 +1134,22 @@ void do_machine_check(struct pt_regs *regs, long error_code)
         * on Intel.
         */
        int lmce = 1;
+       int cpu = smp_processor_id();
 
-       /* If this CPU is offline, just bail out. */
-       if (cpu_is_offline(smp_processor_id())) {
+       /*
+        * Cases where we avoid rendezvous handler timeout:
+        * 1) If this CPU is offline.
+        *
+        * 2) If crashing_cpu was set, e.g. we're entering kdump and we need to
+        *  skip those CPUs which remain looping in the 1st kernel - see
+        *  crash_nmi_callback().
+        *
+        * Note: there still is a small window between kexec-ing and the new,
+        * kdump kernel establishing a new #MC handler where a broadcasted MCE
+        * might not get handled properly.
+        */
+       if (cpu_is_offline(cpu) ||
+           (crashing_cpu != -1 && crashing_cpu != cpu)) {
                u64 mcgstatus;
 
                mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
@@ -1694,30 +1708,35 @@ static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
        return 0;
 }
 
-static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
+/*
+ * Init basic CPU features needed for early decoding of MCEs.
+ */
+static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c)
 {
-       switch (c->x86_vendor) {
-       case X86_VENDOR_INTEL:
-               mce_intel_feature_init(c);
-               mce_adjust_timer = cmci_intel_adjust_timer;
-               break;
-
-       case X86_VENDOR_AMD: {
+       if (c->x86_vendor == X86_VENDOR_AMD) {
                mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV);
                mce_flags.succor         = !!cpu_has(c, X86_FEATURE_SUCCOR);
                mce_flags.smca           = !!cpu_has(c, X86_FEATURE_SMCA);
 
-               /*
-                * Install proper ops for Scalable MCA enabled processors
-                */
                if (mce_flags.smca) {
                        msr_ops.ctl     = smca_ctl_reg;
                        msr_ops.status  = smca_status_reg;
                        msr_ops.addr    = smca_addr_reg;
                        msr_ops.misc    = smca_misc_reg;
                }
-               mce_amd_feature_init(c);
+       }
+}
+
+static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
+{
+       switch (c->x86_vendor) {
+       case X86_VENDOR_INTEL:
+               mce_intel_feature_init(c);
+               mce_adjust_timer = cmci_intel_adjust_timer;
+               break;
 
+       case X86_VENDOR_AMD: {
+               mce_amd_feature_init(c);
                break;
                }
 
@@ -1804,6 +1823,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
 
        machine_check_vector = do_machine_check;
 
+       __mcheck_cpu_init_early(c);
        __mcheck_cpu_init_generic();
        __mcheck_cpu_init_vendor(c);
        __mcheck_cpu_init_clear_banks();