lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20211104215846.254012-4-Smita.KoralahalliChannabasappa@amd.com>
Date:   Thu, 4 Nov 2021 16:58:43 -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 v3 3/6] 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.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@....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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ