Messages in this thread Patch in this message | | | From | Smita Koralahalli <> | Subject | [PATCH v5 2/3] x86/mce: Check for writes ignored in MCA_STATUS register | Date | Mon, 2 May 2022 22:28:18 -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 before doing hw error injection. If true, return the appropriate error code to userspace.
Introduce "hw_injection_possible" flag to return early on subsequent hw error injections.
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/20220214233640.70510-2-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. v4: Simplified the code by just checking for writes ignored behavior in MCA_STATUS register. Introduced prepare_mca_status() and performed writes ignored checks inside the function. Rephrased error message. v5: Replaced i_mce with inject_desc. Introduction of hw_injection_possible flag to return early if HW error injections are not possible. --- arch/x86/kernel/cpu/mce/inject.c | 25 +++++++++++++++++++++++++ arch/x86/kernel/cpu/mce/internal.h | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c index 05581b718529..cce068a4478c 100644 --- a/arch/x86/kernel/cpu/mce/inject.c +++ b/arch/x86/kernel/cpu/mce/inject.c @@ -33,6 +33,8 @@ #include "internal.h" +static bool hw_injection_possible = true; + /* Collect all the MCi_XXX settings */ static struct inject_desc { struct mce m; @@ -474,11 +476,29 @@ static void toggle_nb_mca_mst_cpu(u16 nid) __func__, PCI_FUNC(F3->devfn), NBCFG); } +static bool prepare_mca_status(void) +{ + u32 status_reg = mca_msr_reg(inj_desc.m.bank, MCA_STATUS); + u64 status_val = inj_desc.m.status; + + wrmsrl(status_reg, status_val); + rdmsrl(status_reg, status_val); + + return status_val == inj_desc.m.status; +} + static void prepare_msrs(void *unused) { struct mce *m = &inj_desc.m; u8 b = inj_desc.m.bank; + if (!prepare_mca_status()) { + pr_err("Platform does not allow error injection, try using APEI EINJ instead.\n"); + inj_desc.err = -EINVAL; + hw_injection_possible = false; + return; + } + wrmsrl(MSR_IA32_MCG_STATUS, m->mcgstatus); if (boot_cpu_has(X86_FEATURE_SMCA)) { @@ -521,6 +541,11 @@ static int do_inject(void) return 0; } + if (!hw_injection_possible) { + pr_err("SW-only injection possible on this platform"); + return -EINVAL; + } + /* prep MCE global settings for the injection */ mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV; diff --git a/arch/x86/kernel/cpu/mce/internal.h b/arch/x86/kernel/cpu/mce/internal.h index 4ae0e603f7fa..7e03f5b7f6bd 100644 --- a/arch/x86/kernel/cpu/mce/internal.h +++ b/arch/x86/kernel/cpu/mce/internal.h @@ -211,7 +211,7 @@ noinstr u64 mce_rdmsrl(u32 msr); static __always_inline u32 mca_msr_reg(int bank, enum mca_msr reg) { - if (mce_flags.smca) { + if (cpu_feature_enabled(X86_FEATURE_SMCA)) { switch (reg) { case MCA_CTL: return MSR_AMD64_SMCA_MCx_CTL(bank); case MCA_ADDR: return MSR_AMD64_SMCA_MCx_ADDR(bank); -- 2.17.1
| |