Skip to content

Commit ed9b870

Browse files
bp3tk0vgregkh
authored andcommitted
x86/cpu/amd: Add a Zenbleed fix
Upstream commit: 522b1d6 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) <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5fc203d commit ed9b870

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

arch/x86/include/asm/microcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <asm/cpu.h>
66
#include <linux/earlycpio.h>
77
#include <linux/initrd.h>
8+
#include <asm/microcode_amd.h>
89

910
struct ucode_patch {
1011
struct list_head plist;

arch/x86/include/asm/microcode_amd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@ extern void __init load_ucode_amd_bsp(unsigned int family);
4848
extern void load_ucode_amd_ap(unsigned int family);
4949
extern int __init save_microcode_in_initrd_amd(unsigned int family);
5050
void reload_ucode_amd(unsigned int cpu);
51+
extern void amd_check_microcode(void);
5152
#else
5253
static inline void __init load_ucode_amd_bsp(unsigned int family) {}
5354
static inline void load_ucode_amd_ap(unsigned int family) {}
5455
static inline int __init
5556
save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
5657
static inline void reload_ucode_amd(unsigned int cpu) {}
58+
static inline void amd_check_microcode(void) {}
5759
#endif
5860
#endif /* _ASM_X86_MICROCODE_AMD_H */

arch/x86/include/asm/msr-index.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@
543543
#define MSR_AMD64_DE_CFG 0xc0011029
544544
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1
545545
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
546+
#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9
546547

547548
#define MSR_AMD64_BU_CFG2 0xc001102a
548549
#define MSR_AMD64_IBSFETCHCTL 0xc0011030

arch/x86/kernel/cpu/amd.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ static const int amd_erratum_383[] =
7070
static const int amd_erratum_1054[] =
7171
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
7272

73+
static const int amd_zenbleed[] =
74+
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
75+
AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
76+
AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
77+
7378
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
7479
{
7580
int osvw_id = *erratum++;
@@ -978,6 +983,47 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
978983
}
979984
}
980985

986+
static bool cpu_has_zenbleed_microcode(void)
987+
{
988+
u32 good_rev = 0;
989+
990+
switch (boot_cpu_data.x86_model) {
991+
case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
992+
case 0x60 ... 0x67: good_rev = 0x0860010b; break;
993+
case 0x68 ... 0x6f: good_rev = 0x08608105; break;
994+
case 0x70 ... 0x7f: good_rev = 0x08701032; break;
995+
case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
996+
997+
default:
998+
return false;
999+
break;
1000+
}
1001+
1002+
if (boot_cpu_data.microcode < good_rev)
1003+
return false;
1004+
1005+
return true;
1006+
}
1007+
1008+
static void zenbleed_check(struct cpuinfo_x86 *c)
1009+
{
1010+
if (!cpu_has_amd_erratum(c, amd_zenbleed))
1011+
return;
1012+
1013+
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
1014+
return;
1015+
1016+
if (!cpu_has(c, X86_FEATURE_AVX))
1017+
return;
1018+
1019+
if (!cpu_has_zenbleed_microcode()) {
1020+
pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n");
1021+
msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
1022+
} else {
1023+
msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
1024+
}
1025+
}
1026+
9811027
static void init_amd(struct cpuinfo_x86 *c)
9821028
{
9831029
early_init_amd(c);
@@ -1067,6 +1113,8 @@ static void init_amd(struct cpuinfo_x86 *c)
10671113
msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
10681114

10691115
check_null_seg_clears_base(c);
1116+
1117+
zenbleed_check(c);
10701118
}
10711119

10721120
#ifdef CONFIG_X86_32
@@ -1196,3 +1244,15 @@ u32 amd_get_highest_perf(void)
11961244
return 255;
11971245
}
11981246
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
1247+
1248+
static void zenbleed_check_cpu(void *unused)
1249+
{
1250+
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
1251+
1252+
zenbleed_check(c);
1253+
}
1254+
1255+
void amd_check_microcode(void)
1256+
{
1257+
on_each_cpu(zenbleed_check_cpu, NULL, 1);
1258+
}

arch/x86/kernel/cpu/common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,8 @@ void microcode_check(struct cpuinfo_x86 *prev_info)
23462346

23472347
perf_check_microcode();
23482348

2349+
amd_check_microcode();
2350+
23492351
store_cpu_caps(&curr_info);
23502352

23512353
if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,

0 commit comments

Comments
 (0)