Author: gallatin
Date: Wed May 22 13:44:15 2019
New Revision: 348109
URL: https://svnweb.freebsd.org/changeset/base/348109
Log:
x86 MCA: introduce MCA hooks for different vendor implementations
This is needed for AMD SMCA processors, as SMCA uses different
MSR address for access MCA banks.
Use IA32 specific msr_ops as defualt, and use SMCA-specific msr_ops
when on an SMCA-enabled processor
Submitted by: chandu from amd dot com
Reviewed by: cem
Differential Revision:https://reviews.freebsd.org/D18055
Modified:
head/sys/x86/include/specialreg.h
head/sys/x86/x86/mca.c
Modified: head/sys/x86/include/specialreg.h
==
--- head/sys/x86/include/specialreg.h Wed May 22 08:30:03 2019
(r348108)
+++ head/sys/x86/include/specialreg.h Wed May 22 13:44:15 2019
(r348109)
@@ -944,6 +944,16 @@
#defineMC_MISC_AMD_PTR_MASK0xff00 /* Pointer to
additional registers */
#defineMC_MISC_AMD_PTR_SHIFT 24
+/* AMD Scalable MCA */
+#define MSR_SMCA_MC0_CTL 0xc0002000
+#define MSR_SMCA_MC0_STATUS 0xc0002001
+#define MSR_SMCA_MC0_ADDR 0xc0002002
+#define MSR_SMCA_MC0_MISC00xc0002003
+#define MSR_SMCA_MC_CTL(x) (MSR_SMCA_MC0_CTL + 0x10 * (x))
+#define MSR_SMCA_MC_STATUS(x)(MSR_SMCA_MC0_STATUS + 0x10 * (x))
+#define MSR_SMCA_MC_ADDR(x) (MSR_SMCA_MC0_ADDR + 0x10 * (x))
+#define MSR_SMCA_MC_MISC(x) (MSR_SMCA_MC0_MISC0 + 0x10 * (x))
+
/*
* The following four 3-byte registers control the non-cacheable regions.
* These registers must be written as three separate bytes.
Modified: head/sys/x86/x86/mca.c
==
--- head/sys/x86/x86/mca.c Wed May 22 08:30:03 2019(r348108)
+++ head/sys/x86/x86/mca.c Wed May 22 13:44:15 2019(r348109)
@@ -90,6 +90,13 @@ struct mca_internal {
STAILQ_ENTRY(mca_internal) link;
};
+struct mca_enumerator_ops {
+unsigned int (*ctl)(int);
+unsigned int (*status)(int);
+unsigned int (*addr)(int);
+unsigned int (*misc)(int);
+};
+
static MALLOC_DEFINE(M_MCA, "MCA", "Machine Check Architecture");
static volatile int mca_count; /* Number of records stored. */
@@ -124,6 +131,61 @@ static struct taskqueue *mca_tq;
static struct task mca_refill_task, mca_scan_task;
static struct mtx mca_lock;
+static unsigned int
+mca_ia32_ctl_reg(int bank)
+{
+ return (MSR_MC_CTL(bank));
+}
+
+static unsigned int
+mca_ia32_status_reg(int bank)
+{
+ return (MSR_MC_STATUS(bank));
+}
+
+static unsigned int
+mca_ia32_addr_reg(int bank)
+{
+ return (MSR_MC_ADDR(bank));
+}
+
+static unsigned int
+mca_ia32_misc_reg(int bank)
+{
+ return (MSR_MC_MISC(bank));
+}
+
+static unsigned int
+mca_smca_ctl_reg(int bank)
+{
+return (MSR_SMCA_MC_CTL(bank));
+}
+
+static unsigned int
+mca_smca_status_reg(int bank)
+{
+return (MSR_SMCA_MC_STATUS(bank));
+}
+
+static unsigned int
+mca_smca_addr_reg(int bank)
+{
+return (MSR_SMCA_MC_ADDR(bank));
+}
+
+static unsigned int
+mca_smca_misc_reg(int bank)
+{
+return (MSR_SMCA_MC_MISC(bank));
+}
+
+static struct mca_enumerator_ops mca_msr_ops = {
+.ctl= mca_ia32_ctl_reg,
+.status = mca_ia32_status_reg,
+.addr = mca_ia32_addr_reg,
+.misc = mca_ia32_misc_reg
+};
+
#ifdef DEV_APIC
static struct cmc_state **cmc_state; /* Indexed by cpuid, bank. */
static struct amd_et_state **amd_et_state; /* Indexed by cpuid, bank. */
@@ -462,7 +524,7 @@ mca_check_status(int bank, struct mca_record *rec)
uint64_t status;
u_int p[4];
- status = rdmsr(MSR_MC_STATUS(bank));
+ status = rdmsr(mca_msr_ops.status(bank));
if (!(status & MC_STATUS_VAL))
return (0);
@@ -471,10 +533,10 @@ mca_check_status(int bank, struct mca_record *rec)
rec->mr_bank = bank;
rec->mr_addr = 0;
if (status & MC_STATUS_ADDRV)
- rec->mr_addr = rdmsr(MSR_MC_ADDR(bank));
+ rec->mr_addr = rdmsr(mca_msr_ops.addr(bank));
rec->mr_misc = 0;
if (status & MC_STATUS_MISCV)
- rec->mr_misc = rdmsr(MSR_MC_MISC(bank));
+ rec->mr_misc = rdmsr(mca_msr_ops.misc(bank));
rec->mr_tsc = rdtsc();
rec->mr_apic_id = PCPU_GET(apic_id);
rec->mr_mcg_cap = rdmsr(MSR_MCG_CAP);
@@ -488,7 +550,7 @@ mca_check_status(int bank, struct mca_record *rec)
* errors so that the BIOS can see them.
*/
if (!(rec->mr_status & (MC_STATUS_PCC | MC_STATUS_UC))) {
- wrmsr(MSR_MC_STATUS(bank), 0);
+ wrmsr(mca_msr_ops.status(bank), 0);
do_cpuid(0, p);
}
return (1);
@@ -648,7 +710,7 @@ amd_thresholding_update(enum scan_mode mode, int bank,
int count;
cc =