[PATCH 2/2] x86/CPU/AMD: Improve the erratum 1386 workaround

From: Borislav Petkov
Date: Thu Mar 21 2024 - 08:06:40 EST


From: "Borislav Petkov (AMD)" <bp@xxxxxxxxx>

Disable XSAVES only on machines which haven't loaded the microcode
revision containing the erratum fix.

This will come in handy when running archaic OSes as guests. OSes whose
brilliant programmers thought that CPUID is overrated and one should not
query it but use features directly, ala shoot first, ask questions
later... but only if you're alive after the shooting.

Signed-off-by: Borislav Petkov (AMD) <bp@xxxxxxxxx>
Cc: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
Cc: "Maciej S. Szmigiero" <maciej.szmigiero@xxxxxxxxxx>
---
arch/x86/kernel/cpu/amd.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 6d8677e80ddb..c02b07feff6e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -15,6 +15,7 @@
#include <asm/cpu.h>
#include <asm/spec-ctrl.h>
#include <asm/smp.h>
+#include <asm/microcode.h>
#include <asm/numa.h>
#include <asm/pci-direct.h>
#include <asm/delay.h>
@@ -804,6 +805,16 @@ static void init_amd_bd(struct cpuinfo_x86 *c)

static void fix_erratum_1386(struct cpuinfo_x86 *c)
{
+ u8 fam, model, stpng, rev;
+ union zen_patch_rev p;
+
+ p.ucode_rev = c->microcode;
+
+ fam = p.ext_fam + 0xf;
+ model = p.ext_model << 4 | p.model;
+ stpng = p.stepping;
+ rev = p.rev;
+
/*
* Work around Erratum 1386. The XSAVES instruction malfunctions in
* certain circumstances on Zen1/2 uarch, and not all parts have had
@@ -811,7 +822,24 @@ static void fix_erratum_1386(struct cpuinfo_x86 *c)
*
* Affected parts all have no supervisor XSAVE states, meaning that
* the XSAVEC instruction (which works fine) is equivalent.
+ *
+ * Clear the feature flag only on microcode revisions which
+ * don't have the fix.
*/
+ if (fam == c->x86 &&
+ model == c->x86_model &&
+ stpng == c->x86_stepping) {
+ if (fam == 0x17) {
+ if (model == 0x1 && stpng == 0x2) {
+ if (rev >= 0x6e)
+ return;
+ } else if (model == 0x31 && stpng == 0x0) {
+ if (rev >= 0x52)
+ return;
+ }
+ }
+ }
+
clear_cpu_cap(c, X86_FEATURE_XSAVES);
}

--
2.43.0