commit 70f0c230031dfef3c9b3e37b2a8c18d3f7186fb2 upstream.
Newer Zhaoxin CPUs support LMCE compatible with Intel. Add support for
that.
  [ bp: Export functions and massage. ]
Signed-off-by: Tony W Wang-oc <TonyWWang-oc(a)zhaoxin.com>
Signed-off-by: Borislav Petkov <bp(a)suse.de>
Cc: CooperYan(a)zhaoxin.com
Cc: DavidWang(a)zhaoxin.com
Cc: HerryYang(a)zhaoxin.com
Cc: "H. Peter Anvin" <hpa(a)zytor.com>
Cc: Ingo Molnar <mingo(a)redhat.com>
Cc: linux-edac <linux-edac(a)vger.kernel.org>
Cc: QiyuanWang(a)zhaoxin.com
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Tony Luck <tony.luck(a)intel.com>
Cc: x86-ml <x86(a)kernel.org>
Link: 
https://lkml.kernel.org/r/1568787573-1297-5-git-send-email-TonyWWang-oc@zha…
[ LeoLiu-oc: Add support for more Zhaoxin CPUs and adapt to
   the current MCE directory ]
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
  arch/x86/kernel/cpu/mcheck/mce-internal.h |  4 ++++
  arch/x86/kernel/cpu/mcheck/mce.c          | 25 +++++++++++++++++++++--
  arch/x86/kernel/cpu/mcheck/mce_intel.c    |  4 ++--
  3 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h 
b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 79936eaec14b..6bc9d8991efa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -54,12 +54,16 @@ bool mce_intel_cmci_poll(void);
  void mce_intel_hcpu_update(unsigned long cpu);
  void cmci_disable_bank(int bank);
  void intel_init_cmci(void);
+void intel_init_lmce(void);
+void intel_clear_lmce(void);
  #else
  # define cmci_intel_adjust_timer mce_adjust_timer_default
  static inline bool mce_intel_cmci_poll(void) { return false; }
  static inline void mce_intel_hcpu_update(unsigned long cpu) { }
  static inline void cmci_disable_bank(int bank) { }
  static inline void intel_init_cmci(void) { }
+static inline void intel_init_lmce(void) { }
+static inline void intel_clear_lmce(void) { }
  #endif
  void mce_timer_kick(unsigned long interval);
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c 
b/arch/x86/kernel/cpu/mcheck/mce.c
index ace64069152d..95267d1d458f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1099,6 +1099,13 @@ static bool mce_check_crashing_cpu(void)
  		u64 mcgstatus;
  		mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+
+		if (boot_cpu_data.x86_vendor == X86_VENDOR_ZHAOXIN ||
+			boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR) {
+			if (mcgstatus & MCG_STATUS_LMCES)
+				return false;
+		}
+
  		if (mcgstatus & MCG_STATUS_RIPV) {
  			mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
  			return true;
@@ -1285,9 +1292,11 @@ void do_machine_check(struct pt_regs *regs, long 
error_code)
  	/*
  	 * Check if this MCE is signaled to only this logical processor,
-	 * on Intel only.
+	 * on Intel, Zhaoxin only.
  	 */
-	if (m.cpuvendor == X86_VENDOR_INTEL)
+	if (m.cpuvendor == X86_VENDOR_INTEL ||
+	    m.cpuvendor == X86_VENDOR_ZHAOXIN ||
+	    m.cpuvendor == X86_VENDOR_CENTAUR)
  		lmce = m.mcgstatus & MCG_STATUS_LMCES;
  	/*
@@ -1762,9 +1771,15 @@ static void mce_zhaoxin_feature_init(struct 
cpuinfo_x86 *c)
  	}
  	intel_init_cmci();
+	intel_init_lmce();
  	mce_adjust_timer = cmci_intel_adjust_timer;
  }
+static void mce_zhaoxin_feature_clear(struct cpuinfo_x86 *c)
+{
+	intel_clear_lmce();
+}
+
  static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
  {
  	switch (c->x86_vendor) {
@@ -1798,6 +1813,12 @@ static void __mcheck_cpu_clear_vendor(struct 
cpuinfo_x86 *c)
  	case X86_VENDOR_INTEL:
  		mce_intel_feature_clear(c);
  		break;
+
+	case X86_VENDOR_ZHAOXIN:
+	case X86_VENDOR_CENTAUR:
+		mce_zhaoxin_feature_clear(c);
+		break;
+
  	default:
  		break;
  	}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c 
b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 637780528380..3bc5d6d47178 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -445,7 +445,7 @@ void intel_init_cmci(void)
  	cmci_recheck();
  }
-static void intel_init_lmce(void)
+void intel_init_lmce(void)
  {
  	u64 val;
@@ -458,7 +458,7 @@ static void intel_init_lmce(void)
  		wrmsrl(MSR_IA32_MCG_EXT_CTL, val | MCG_EXT_CTL_LMCE_EN);
  }
-static void intel_clear_lmce(void)
+void intel_clear_lmce(void)
  {
  	u64 val;
-- 
2.20.1