Subject: [PATCH 2891/2944] x86/mce: Add Zhaoxin CMCI support

From: LeoLiu-oc <[email-masked]>
Date: Sun, 21 Mar 2021 20:37:01 +0800

commit 5a3d56a034be9e8e87a6cb9ed3f2928184db1417 upstream.

All newer Zhaoxin CPUs support CMCI and are compatible with Intel's
Machine-Check Architecture. Add that support for Zhaoxin CPUs.

 [ bp: Massage comments and export intel_init_cmci(). ]

Signed-off-by: Tony W Wang-oc <[email-masked]>
Signed-off-by: Borislav Petkov <[email-masked]>
Cc: [email-masked]
Cc: [email-masked]
Cc: [email-masked]
Cc: "H. Peter Anvin" <[email-masked]>
Cc: Ingo Molnar <[email-masked]>
Cc: linux-edac <[email-masked]>
Cc: [email-masked]
Cc: Thomas Gleixner <[email-masked]>
Cc: Tony Luck <[email-masked]>
Cc: x86-ml <[email-masked]>
Link: https://lkml.kernel.org/r/[email-masked]

[ LeoLiu-oc: Add support for more Zhaoxin CPUs and adapt to
  the current MCE directory ]

Signed-off-by: LeoLiu-oc <[email-masked]>
Reviewed-by: Artie Ding <[email-masked]>
---
 arch/x86/kernel/cpu/mcheck/mce-internal.h |  2 ++
 arch/x86/kernel/cpu/mcheck/mce.c          | 30 +++++++++++++++++++-----------
 arch/x86/kernel/cpu/mcheck/mce_intel.c    |  7 +++++--
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 91f6a7b..79936ea 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -53,11 +53,13 @@ extern int (*mce_severity)(struct mce *a, struct pt_regs *regs,
 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);
 #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) { }
 #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 24e7f3f..ace6406 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1743,19 +1743,26 @@ static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c)
 	}
 }
 
-static void mce_centaur_feature_init(struct cpuinfo_x86 *c)
+static void mce_zhaoxin_feature_init(struct cpuinfo_x86 *c)
 {
 	struct mca_config *cfg = &mca_cfg;
-
-	 /*
-	  * All newer Centaur CPUs support MCE broadcasting. Enable
-	  * synchronization with a one second timeout.
-	  */
-	if ((c->x86 == 6 && c->x86_model == 0xf && c->x86_stepping >= 0xe) ||
-	     c->x86 > 6) {
-		if (cfg->monarch_timeout < 0)
-			cfg->monarch_timeout = USEC_PER_SEC;
+	/*
+	 * These CPUs have MCA bank 8 which reports only one error type called
+	 * SVAD (System View Address Decoder). The reporting of that error is
+	 * controlled by IA32_MC8.CTL.0.
+	 *
+	 * If enabled, prefetching on these CPUs will cause SVAD MCE when
+	 * virtual machines start and result in a system  panic. Always disable
+	 * bank 8 SVAD error by default.
+	 */
+	if ((c->x86 == 7 && c->x86_model == 0x1b) ||
+	    (c->x86_model == 0x19 || c->x86_model == 0x1f)) {
+		if (cfg->banks > 8)
+			mce_banks[8].ctl = 0;
 	}
+
+	intel_init_cmci();
+	mce_adjust_timer = cmci_intel_adjust_timer;
 }
 
 static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
@@ -1776,7 +1783,8 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
 		break;
 
 	case X86_VENDOR_CENTAUR:
-		mce_centaur_feature_init(c);
+	case X86_VENDOR_ZHAOXIN:
+		mce_zhaoxin_feature_init(c);
 		break;
 
 	default:
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index d05be30..63778052 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -85,8 +85,11 @@ static int cmci_supported(int *banks)
 	 * initialization is vendor keyed and this
 	 * makes sure none of the backdoors are entered otherwise.
 	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL &&
+	    boot_cpu_data.x86_vendor != X86_VENDOR_ZHAOXIN &&
+	    boot_cpu_data.x86_vendor != X86_VENDOR_CENTAUR)
 		return 0;
+
 	if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6)
 		return 0;
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
@@ -423,7 +426,7 @@ void cmci_disable_bank(int bank)
 	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
-static void intel_init_cmci(void)
+void intel_init_cmci(void)
 {
 	int banks;
 
-- 
1.8.3.1