x86/cpu/amd: Add a Zenbleed fix
Upstream commit: 522b1d69219d8f083173819fde04f994aa051a98 Add a fix for the Zen2 VZEROUPPER data corruption bug where under certain circumstances executing VZEROUPPER can cause register corruption or leak data. The optimal fix is through microcode but in the case the proper microcode revision has not been applied, enable a fallback fix using a chicken bit. Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
191b8f9b0e
commit
93df00f9d4
@@ -71,6 +71,11 @@ static const int amd_erratum_383[] =
|
||||
static const int amd_erratum_1054[] =
|
||||
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
|
||||
|
||||
static const int amd_zenbleed[] =
|
||||
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
|
||||
AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
|
||||
AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
|
||||
|
||||
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
|
||||
{
|
||||
int osvw_id = *erratum++;
|
||||
@@ -1030,6 +1035,47 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
|
||||
}
|
||||
}
|
||||
|
||||
static bool cpu_has_zenbleed_microcode(void)
|
||||
{
|
||||
u32 good_rev = 0;
|
||||
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
|
||||
case 0x60 ... 0x67: good_rev = 0x0860010b; break;
|
||||
case 0x68 ... 0x6f: good_rev = 0x08608105; break;
|
||||
case 0x70 ... 0x7f: good_rev = 0x08701032; break;
|
||||
case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (boot_cpu_data.microcode < good_rev)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void zenbleed_check(struct cpuinfo_x86 *c)
|
||||
{
|
||||
if (!cpu_has_amd_erratum(c, amd_zenbleed))
|
||||
return;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
|
||||
return;
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_AVX))
|
||||
return;
|
||||
|
||||
if (!cpu_has_zenbleed_microcode()) {
|
||||
pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n");
|
||||
msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
|
||||
} else {
|
||||
msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_amd(struct cpuinfo_x86 *c)
|
||||
{
|
||||
early_init_amd(c);
|
||||
@@ -1120,6 +1166,8 @@ static void init_amd(struct cpuinfo_x86 *c)
|
||||
msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
|
||||
|
||||
check_null_seg_clears_base(c);
|
||||
|
||||
zenbleed_check(c);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
@@ -1233,3 +1281,15 @@ void set_dr_addr_mask(unsigned long mask, int dr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void zenbleed_check_cpu(void *unused)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
||||
|
||||
zenbleed_check(c);
|
||||
}
|
||||
|
||||
void amd_check_microcode(void)
|
||||
{
|
||||
on_each_cpu(zenbleed_check_cpu, NULL, 1);
|
||||
}
|
||||
|
@@ -2165,6 +2165,8 @@ void microcode_check(struct cpuinfo_x86 *prev_info)
|
||||
|
||||
perf_check_microcode();
|
||||
|
||||
amd_check_microcode();
|
||||
|
||||
store_cpu_caps(&curr_info);
|
||||
|
||||
if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
|
||||
|
Reference in New Issue
Block a user