x86/mce: Add infrastructure to support Local MCE
authorAshok Raj <ashok.raj@intel.com>
Thu, 4 Jun 2015 16:55:23 +0000 (18:55 +0200)
committerIngo Molnar <mingo@kernel.org>
Sun, 7 Jun 2015 13:33:14 +0000 (15:33 +0200)
Initialize and prepare for handling LMCEs. Add a boot-time
option to disable LMCEs.

Signed-off-by: Ashok Raj <ashok.raj@intel.com>
[ Simplify stuff, align statements for better readability, reflow comments; kill
  unused lmce_clear(); save us an MSR write if LMCE is already enabled. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-edac <linux-edac@vger.kernel.org>
Link: http://lkml.kernel.org/r/1433436928-31903-16-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Documentation/x86/x86_64/boot-options.txt
arch/x86/include/asm/mce.h
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_intel.c

index 5223479291a295e7b248661d28c14ea8a33b3eaa..68ed3114c363bf7332b2515b156bf0953ca88d24 100644 (file)
@@ -31,6 +31,9 @@ Machine check
                (e.g. BIOS or hardware monitoring applications), conflicting
                with OS's error handling, and you cannot deactivate the agent,
                then this option will be a help.
+   mce=no_lmce
+               Do not opt-in to Local MCE delivery. Use legacy method
+               to broadcast MCEs.
    mce=bootlog
                Enable logging of machine checks left over from booting.
                Disabled by default on AMD because some BIOS leave bogus ones.
index ae2bfb895994ed175aa82a27f78c95419f0db8d9..982dfc3679ad3d9cd741d75f8799bc1b8b8c5ef7 100644 (file)
@@ -109,6 +109,7 @@ struct mce_log {
 struct mca_config {
        bool dont_log_ce;
        bool cmci_disabled;
+       bool lmce_disabled;
        bool ignore_ce;
        bool disabled;
        bool ser;
@@ -184,12 +185,16 @@ void cmci_clear(void);
 void cmci_reenable(void);
 void cmci_rediscover(void);
 void cmci_recheck(void);
+void lmce_clear(void);
+void lmce_enable(void);
 #else
 static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { }
 static inline void cmci_clear(void) {}
 static inline void cmci_reenable(void) {}
 static inline void cmci_rediscover(void) {}
 static inline void cmci_recheck(void) {}
+static inline void lmce_clear(void) {}
+static inline void lmce_enable(void) {}
 #endif
 
 #ifdef CONFIG_X86_MCE_AMD
index 0cbcd3183acfafeb71e09197fb71721bb43dd756..c8c6577b4adaa482fad5e6373a44c341fd99d501 100644 (file)
@@ -1982,6 +1982,7 @@ void mce_disable_bank(int bank)
 /*
  * mce=off Disables machine check
  * mce=no_cmci Disables CMCI
+ * mce=no_lmce Disables LMCE
  * mce=dont_log_ce Clears corrected events silently, no log created for CEs.
  * mce=ignore_ce Disables polling and CMCI, corrected events are not cleared.
  * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above)
@@ -2005,6 +2006,8 @@ static int __init mcheck_enable(char *str)
                cfg->disabled = true;
        else if (!strcmp(str, "no_cmci"))
                cfg->cmci_disabled = true;
+       else if (!strcmp(str, "no_lmce"))
+               cfg->lmce_disabled = true;
        else if (!strcmp(str, "dont_log_ce"))
                cfg->dont_log_ce = true;
        else if (!strcmp(str, "ignore_ce"))
index b4a41cf030edab7dbfae7dc67560ba63eabc2309..2d872deb2c50deddc8211fdc9bdfe03d0ae35b83 100644 (file)
@@ -91,6 +91,36 @@ static int cmci_supported(int *banks)
        return !!(cap & MCG_CMCI_P);
 }
 
+static bool lmce_supported(void)
+{
+       u64 tmp;
+
+       if (mca_cfg.lmce_disabled)
+               return false;
+
+       rdmsrl(MSR_IA32_MCG_CAP, tmp);
+
+       /*
+        * LMCE depends on recovery support in the processor. Hence both
+        * MCG_SER_P and MCG_LMCE_P should be present in MCG_CAP.
+        */
+       if ((tmp & (MCG_SER_P | MCG_LMCE_P)) !=
+                  (MCG_SER_P | MCG_LMCE_P))
+               return false;
+
+       /*
+        * BIOS should indicate support for LMCE by setting bit 20 in
+        * IA32_FEATURE_CONTROL without which touching MCG_EXT_CTL will
+        * generate a #GP fault.
+        */
+       rdmsrl(MSR_IA32_FEATURE_CONTROL, tmp);
+       if ((tmp & (FEATURE_CONTROL_LOCKED | FEATURE_CONTROL_LMCE)) ==
+                  (FEATURE_CONTROL_LOCKED | FEATURE_CONTROL_LMCE))
+               return true;
+
+       return false;
+}
+
 bool mce_intel_cmci_poll(void)
 {
        if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE)
@@ -405,6 +435,19 @@ static void intel_init_cmci(void)
        cmci_recheck();
 }
 
+void intel_init_lmce(void)
+{
+       u64 val;
+
+       if (!lmce_supported())
+               return;
+
+       rdmsrl(MSR_IA32_MCG_EXT_CTL, val);
+
+       if (!(val & MCG_EXT_CTL_LMCE_EN))
+               wrmsrl(MSR_IA32_MCG_EXT_CTL, val | MCG_EXT_CTL_LMCE_EN);
+}
+
 void mce_intel_feature_init(struct cpuinfo_x86 *c)
 {
        intel_init_thermal(c);