|
|
14c61e3 |
From: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
|
14c61e3 |
Subject: x86/amd: Mitigations for Zenbleed
|
|
|
14c61e3 |
|
|
|
14c61e3 |
Zenbleed is a malfunction on AMD Zen2 uarch parts which results in corruption
|
|
|
14c61e3 |
of the vector registers. An attacker can trigger this bug deliberately in
|
|
|
14c61e3 |
order to access stale data in the physical vector register file. This can
|
|
|
14c61e3 |
include data from sibling threads, or a higher-privilege context.
|
|
|
14c61e3 |
|
|
|
14c61e3 |
Microcode is the preferred mitigation but in the case that's not available use
|
|
|
14c61e3 |
the chickenbit as instructed by AMD. Re-evaluate the mitigation on late
|
|
|
14c61e3 |
microcode load too.
|
|
|
14c61e3 |
|
|
|
14c61e3 |
This is XSA-433 / CVE-2023-20593.
|
|
|
14c61e3 |
|
|
|
14c61e3 |
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
|
14c61e3 |
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
|
|
|
14c61e3 |
|
|
|
14c61e3 |
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
|
|
|
14c61e3 |
index b6a20d375ad1..8d23a5be0c5f 100644
|
|
|
14c61e3 |
--- a/xen/arch/x86/cpu/amd.c
|
|
|
14c61e3 |
+++ b/xen/arch/x86/cpu/amd.c
|
|
|
14c61e3 |
@@ -13,6 +13,7 @@
|
|
|
14c61e3 |
#include <asm/spec_ctrl.h>
|
|
|
14c61e3 |
#include <asm/acpi.h>
|
|
|
14c61e3 |
#include <asm/apic.h>
|
|
|
14c61e3 |
+#include <asm/microcode.h>
|
|
|
14c61e3 |
|
|
|
14c61e3 |
#include "cpu.h"
|
|
|
14c61e3 |
|
|
|
14c61e3 |
@@ -878,6 +879,72 @@ void __init detect_zen2_null_seg_behaviour(void)
|
|
|
14c61e3 |
|
|
|
14c61e3 |
}
|
|
|
14c61e3 |
|
|
|
14c61e3 |
+void amd_check_zenbleed(void)
|
|
|
14c61e3 |
+{
|
|
|
14c61e3 |
+ const struct cpu_signature *sig = &this_cpu(cpu_sig);
|
|
|
14c61e3 |
+ unsigned int good_rev, chickenbit = (1 << 9);
|
|
|
14c61e3 |
+ uint64_t val, old_val;
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ /*
|
|
|
14c61e3 |
+ * If we're virtualised, we can't do family/model checks safely, and
|
|
|
14c61e3 |
+ * we likely wouldn't have access to DE_CFG even if we could see a
|
|
|
14c61e3 |
+ * microcode revision.
|
|
|
14c61e3 |
+ *
|
|
|
14c61e3 |
+ * A hypervisor may hide AVX as a stopgap mitigation. We're not in a
|
|
|
14c61e3 |
+ * position to care either way. An admin doesn't want to be disabling
|
|
|
14c61e3 |
+ * AVX as a mitigation on any build of Xen with this logic present.
|
|
|
14c61e3 |
+ */
|
|
|
14c61e3 |
+ if (cpu_has_hypervisor || boot_cpu_data.x86 != 0x17)
|
|
|
14c61e3 |
+ return;
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ switch (boot_cpu_data.x86_model) {
|
|
|
14c61e3 |
+ case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
|
|
|
14c61e3 |
+ case 0x60 ... 0x67: good_rev = 0x0860010b; break;
|
|
|
14c61e3 |
+ case 0x68 ... 0x6f: good_rev = 0x08608105; break;
|
|
|
14c61e3 |
+ case 0x70 ... 0x7f: good_rev = 0x08701032; break;
|
|
|
14c61e3 |
+ case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
|
|
|
14c61e3 |
+ default:
|
|
|
14c61e3 |
+ /*
|
|
|
14c61e3 |
+ * With the Fam17h check above, parts getting here are Zen1.
|
|
|
14c61e3 |
+ * They're not affected.
|
|
|
14c61e3 |
+ */
|
|
|
14c61e3 |
+ return;
|
|
|
14c61e3 |
+ }
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ rdmsrl(MSR_AMD64_DE_CFG, val);
|
|
|
14c61e3 |
+ old_val = val;
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ /*
|
|
|
14c61e3 |
+ * Microcode is the preferred mitigation, in terms of performance.
|
|
|
14c61e3 |
+ * However, without microcode, this chickenbit (specific to the Zen2
|
|
|
14c61e3 |
+ * uarch) disables Floating Point Mov-Elimination to mitigate the
|
|
|
14c61e3 |
+ * issue.
|
|
|
14c61e3 |
+ */
|
|
|
14c61e3 |
+ val &= ~chickenbit;
|
|
|
14c61e3 |
+ if (sig->rev < good_rev)
|
|
|
14c61e3 |
+ val |= chickenbit;
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ if (val == old_val)
|
|
|
14c61e3 |
+ /* Nothing to change. */
|
|
|
14c61e3 |
+ return;
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ /*
|
|
|
14c61e3 |
+ * DE_CFG is a Core-scoped MSR, and this write is racy during late
|
|
|
14c61e3 |
+ * microcode load. However, both threads calculate the new value from
|
|
|
14c61e3 |
+ * state which is shared, and unrelated to the old value, so the
|
|
|
14c61e3 |
+ * result should be consistent.
|
|
|
14c61e3 |
+ */
|
|
|
14c61e3 |
+ wrmsrl(MSR_AMD64_DE_CFG, val);
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
+ /*
|
|
|
14c61e3 |
+ * Inform the admin that we changed something, but don't spam,
|
|
|
14c61e3 |
+ * especially during a late microcode load.
|
|
|
14c61e3 |
+ */
|
|
|
14c61e3 |
+ if (smp_processor_id() == 0)
|
|
|
14c61e3 |
+ printk(XENLOG_INFO "Zenbleed mitigation - using %s\n",
|
|
|
14c61e3 |
+ val & chickenbit ? "chickenbit" : "microcode");
|
|
|
14c61e3 |
+}
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
static void cf_check init_amd(struct cpuinfo_x86 *c)
|
|
|
14c61e3 |
{
|
|
|
14c61e3 |
u32 l, h;
|
|
|
14c61e3 |
@@ -1150,6 +1217,8 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
|
|
|
14c61e3 |
if ((smp_processor_id() == 1) && !cpu_has(c, X86_FEATURE_ITSC))
|
|
|
14c61e3 |
disable_c1_ramping();
|
|
|
14c61e3 |
|
|
|
14c61e3 |
+ amd_check_zenbleed();
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
check_syscfg_dram_mod_en();
|
|
|
14c61e3 |
|
|
|
14c61e3 |
amd_log_freq(c);
|
|
|
14c61e3 |
diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
|
|
|
14c61e3 |
index ded8fe90e650..c6d13f3fb35f 100644
|
|
|
14c61e3 |
--- a/xen/arch/x86/cpu/microcode/amd.c
|
|
|
14c61e3 |
+++ b/xen/arch/x86/cpu/microcode/amd.c
|
|
|
14c61e3 |
@@ -262,6 +262,8 @@ static int cf_check apply_microcode(const struct microcode_patch *patch)
|
|
|
14c61e3 |
"microcode: CPU%u updated from revision %#x to %#x, date = %04x-%02x-%02x\n",
|
|
|
14c61e3 |
cpu, old_rev, rev, patch->year, patch->month, patch->day);
|
|
|
14c61e3 |
|
|
|
14c61e3 |
+ amd_check_zenbleed();
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
return 0;
|
|
|
14c61e3 |
}
|
|
|
14c61e3 |
|
|
|
14c61e3 |
diff --git a/xen/arch/x86/include/asm/processor.h b/xen/arch/x86/include/asm/processor.h
|
|
|
14c61e3 |
index 8e2816fae9b9..66611df6efc1 100644
|
|
|
14c61e3 |
--- a/xen/arch/x86/include/asm/processor.h
|
|
|
14c61e3 |
+++ b/xen/arch/x86/include/asm/processor.h
|
|
|
14c61e3 |
@@ -637,6 +637,8 @@ enum ap_boot_method {
|
|
|
14c61e3 |
};
|
|
|
14c61e3 |
extern enum ap_boot_method ap_boot_method;
|
|
|
14c61e3 |
|
|
|
14c61e3 |
+void amd_check_zenbleed(void);
|
|
|
14c61e3 |
+
|
|
|
14c61e3 |
#endif /* !__ASSEMBLY__ */
|
|
|
14c61e3 |
|
|
|
14c61e3 |
#endif /* __ASM_X86_PROCESSOR_H */
|
|
|
14c61e3 |
|