Messages in this thread Patch in this message | | | From | Smita Koralahalli <> | Subject | [PATCH v3 3/6] x86/mce/inject: Check for writes ignored in status registers | Date | Thu, 4 Nov 2021 16:58:43 -0500 |
| |
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.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537 Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> Link: https://lkml.kernel.org/r/20211019233641.140275-5-Smita.KoralahalliChannabasappa@amd.com --- v2: msr_ops -> mca_msr_reg(). simulation -> injection. pr_info() -> pr_err(). Aligned on ",". v3: Removed "x86/mce: Use mca_msr_reg() in prepare_msrs()" patch and made changes on the existing MCx_{STATUS, ADDR, MISC} macros. --- arch/x86/kernel/cpu/mce/inject.c | 35 ++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c index 5e83a1ce7ac8..4d5689342384 100644 --- a/arch/x86/kernel/cpu/mce/inject.c +++ b/arch/x86/kernel/cpu/mce/inject.c @@ -470,9 +470,17 @@ 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); @@ -480,9 +488,17 @@ static void prepare_msrs(void *info) if (boot_cpu_has(X86_FEATURE_SMCA)) { if (m.inject_flags == DFR_INT_INJ) { wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status); + rdmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status); + if (!m.status) + goto out; + wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr); } else { wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status); + rdmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status); + if (!m.status) + goto out; + wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr); } @@ -490,9 +506,18 @@ static void prepare_msrs(void *info) wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd); } else { wrmsrl(MSR_IA32_MCx_STATUS(b), m.status); + rdmsrl(MSR_IA32_MCx_STATUS(b), m.status); + if (!m.status) + goto out; + wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr); wrmsrl(MSR_IA32_MCx_MISC(b), m.misc); } + +out: + pr_err("Error injection is not available\n"); + i_mce_err->err = -EINVAL; + return; } static void do_inject(void) @@ -501,6 +526,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(); i_mce.status |= MCI_STATUS_VAL; @@ -552,10 +580,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
| |