[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20211019233641.140275-5-Smita.KoralahalliChannabasappa@amd.com>
Date: Tue, 19 Oct 2021 18:36:40 -0500
From: Smita Koralahalli <Smita.KoralahalliChannabasappa@....com>
To: <x86@...nel.org>, <linux-edac@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
CC: Tony Luck <tony.luck@...el.com>, "H . Peter Anvin" <hpa@...or.com>,
<yazen.ghannam@....com>, <Smita.KoralahalliChannabasappa@....com>
Subject: [PATCH v2 4/5] x86/mce/inject: Check for writes ignored in status registers
According to Section 2.1.16.3 under HWCR[McStatusWrEn] in "PPR for AMD
Family 19h, Model 01h, Revision B1 Processors - 55898 Rev 0.35 - Feb 5,
2021", the status register may sometimes enforce write ignored behavior
independent of the value of HWCR[McStatusWrEn] depending on the platform
settings.
Hence, evaluate for writes ignored for MCA_STATUS and MCA_DESTAT
separately, before doing error injection. If true, return with an error
code.
Deferred errors on an SMCA platform use different MSR for MCA_DESTAT.
Hence, evaluate MCA_DESTAT instead of MCA_STATUS on deferred errors, and
do not modify the existing value in MCA_STATUS by writing and reading from
it.
Rearrange the calls and write to registers MCx_{ADDR, MISC, SYND} and
MCG_STATUS only if error injection is available.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@....com>
---
v2:
msr_ops -> mca_msr_reg().
simulation -> injection.
pr_info() -> pr_err().
Aligned on "=".
---
arch/x86/kernel/cpu/mce/inject.c | 39 ++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c
index 40d0bebe0cd2..72d29d26e033 100644
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -454,24 +454,39 @@ static void toggle_nb_mca_mst_cpu(u16 nid)
__func__, PCI_FUNC(F3->devfn), NBCFG);
}
+struct mce_err_handler {
+ struct mce *mce;
+ int err;
+};
+
+static struct mce_err_handler mce_err;
+
static void prepare_msrs(void *info)
{
- struct mce m = *(struct mce *)info;
+ struct mce_err_handler *i_mce_err = ((struct mce_err_handler *)info);
+ struct mce m = *i_mce_err->mce;
u8 b = m.bank;
- wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+ u32 status_reg = mca_msr_reg(b, MCA_STATUS);
+ u32 addr_reg = mca_msr_reg(b, MCA_ADDR);
if (boot_cpu_has(X86_FEATURE_SMCA) &&
m.inject_flags == DFR_INT_INJ) {
- wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status);
- wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr);
- goto out;
+ status_reg = MSR_AMD64_SMCA_MCx_DESTAT(b);
+ addr_reg = MSR_AMD64_SMCA_MCx_DEADDR(b);
}
- wrmsrl(mca_msr_reg(b, MCA_STATUS), m.status);
- wrmsrl(mca_msr_reg(b, MCA_ADDR), m.addr);
+ wrmsrl(status_reg, m.status);
+ rdmsrl(status_reg, m.status);
+
+ if (!m.status) {
+ pr_err("Error injection is not available\n");
+ i_mce_err->err = -EINVAL;
+ return;
+ }
-out:
+ wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+ wrmsrl(addr_reg, m.addr);
wrmsrl(mca_msr_reg(b, MCA_MISC), m.misc);
if (boot_cpu_has(X86_FEATURE_SMCA))
@@ -484,6 +499,9 @@ static void do_inject(void)
unsigned int cpu = i_mce.extcpu;
u8 b = i_mce.bank;
+ mce_err.mce = &i_mce;
+ mce_err.err = 0;
+
i_mce.tsc = rdtsc_ordered();
if (!(i_mce.status & MCI_STATUS_VAL))
@@ -536,10 +554,13 @@ static void do_inject(void)
i_mce.mcgstatus = mcg_status;
i_mce.inject_flags = inj_type;
- smp_call_function_single(cpu, prepare_msrs, &i_mce, 0);
+ smp_call_function_single(cpu, prepare_msrs, &mce_err, 0);
toggle_hw_mce_inject(cpu, false);
+ if (mce_err.err)
+ goto err;
+
switch (inj_type) {
case DFR_INT_INJ:
smp_call_function_single(cpu, trigger_dfr_int, NULL, 0);
--
2.17.1
Powered by blists - more mailing lists