forked from rpms/kernel
210 lines
9.2 KiB
Diff
210 lines
9.2 KiB
Diff
From 6b575d67beff6c1ce5f7643cb9326327170114a8 Mon Sep 17 00:00:00 2001
|
|
From: Kim Phillips <kim.phillips@amd.com>
|
|
Date: Tue, 24 Jan 2023 10:33:18 -0600
|
|
Subject: [PATCH 33/36] x86/cpu: Support AMD Automatic IBRS
|
|
|
|
The AMD Zen4 core supports a new feature called Automatic IBRS.
|
|
|
|
It is a "set-and-forget" feature that means that, like Intel's Enhanced IBRS,
|
|
h/w manages its IBRS mitigation resources automatically across CPL transitions.
|
|
|
|
The feature is advertised by CPUID_Fn80000021_EAX bit 8 and is enabled by
|
|
setting MSR C000_0080 (EFER) bit 21.
|
|
|
|
Enable Automatic IBRS by default if the CPU feature is present. It typically
|
|
provides greater performance over the incumbent generic retpolines mitigation.
|
|
|
|
Reuse the SPECTRE_V2_EIBRS spectre_v2_mitigation enum. AMD Automatic IBRS and
|
|
Intel Enhanced IBRS have similar enablement. Add NO_EIBRS_PBRSB to
|
|
cpu_vuln_whitelist, since AMD Automatic IBRS isn't affected by PBRSB-eIBRS.
|
|
|
|
The kernel command line option spectre_v2=eibrs is used to select AMD Automatic
|
|
IBRS, if available.
|
|
|
|
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
|
|
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
|
|
Acked-by: Sean Christopherson <seanjc@google.com>
|
|
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
|
|
Link: https://lore.kernel.org/r/20230124163319.2277355-8-kim.phillips@amd.com
|
|
(cherry picked from commit e7862eda309ecfccc36bb5558d937ed3ace07f3f)
|
|
|
|
Also add fix 06cb31cc761823ef444ba4e1df11347342a6e745 upstream found
|
|
while resolving conflicts. It's a minor doc change.
|
|
|
|
Signed-off-by: Mridula Shastry <mridula.c.shastry@oracle.com>
|
|
Reviewed-by: Todd Vierling <todd.vierling@oracle.com>
|
|
---
|
|
Documentation/admin-guide/hw-vuln/spectre.rst | 7 ++++---
|
|
.../admin-guide/kernel-parameters.txt | 6 +++---
|
|
arch/x86/include/asm/cpufeatures.h | 1 +
|
|
arch/x86/include/asm/msr-index.h | 2 ++
|
|
arch/x86/kernel/cpu/bugs.c | 20 +++++++++++--------
|
|
arch/x86/kernel/cpu/common.c | 17 +++++++++-------
|
|
6 files changed, 32 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
|
|
index fb2572ed9674..bf161b5aa98f 100644
|
|
--- a/Documentation/admin-guide/hw-vuln/spectre.rst
|
|
+++ b/Documentation/admin-guide/hw-vuln/spectre.rst
|
|
@@ -610,9 +610,10 @@ kernel command line.
|
|
retpoline,generic Retpolines
|
|
retpoline,lfence LFENCE; indirect branch
|
|
retpoline,amd alias for retpoline,lfence
|
|
- eibrs enhanced IBRS
|
|
- eibrs,retpoline enhanced IBRS + Retpolines
|
|
- eibrs,lfence enhanced IBRS + LFENCE
|
|
+ eibrs Enhanced/Auto IBRS
|
|
+ eibrs,retpoline Enhanced/Auto IBRS + Retpolines
|
|
+ eibrs,lfence Enhanced/Auto IBRS + LFENCE
|
|
+ ibrs use IBRS to protect kernel
|
|
|
|
Not specifying this option is equivalent to
|
|
spectre_v2=auto.
|
|
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index 73a92fb9e3c6..b6da8048f62c 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -4968,9 +4968,9 @@
|
|
retpoline,generic - Retpolines
|
|
retpoline,lfence - LFENCE; indirect branch
|
|
retpoline,amd - alias for retpoline,lfence
|
|
- eibrs - enhanced IBRS
|
|
- eibrs,retpoline - enhanced IBRS + Retpolines
|
|
- eibrs,lfence - enhanced IBRS + LFENCE
|
|
+ eibrs - Enhanced/Auto IBRS
|
|
+ eibrs,retpoline - Enhanced/Auto IBRS + Retpolines
|
|
+ eibrs,lfence - Enhanced/Auto IBRS + LFENCE
|
|
ibrs - use IBRS to protect kernel
|
|
ibrs_always - use IBRS to protect both kernel
|
|
and userland
|
|
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
|
|
index ac6e58a79fad..316b11ea50ca 100644
|
|
--- a/arch/x86/include/asm/cpufeatures.h
|
|
+++ b/arch/x86/include/asm/cpufeatures.h
|
|
@@ -423,6 +423,7 @@
|
|
|
|
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
|
|
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */
|
|
+#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
|
|
|
|
/*
|
|
* BUG word(s)
|
|
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
|
|
index 9b0d407dd1ae..bf54eb786776 100644
|
|
--- a/arch/x86/include/asm/msr-index.h
|
|
+++ b/arch/x86/include/asm/msr-index.h
|
|
@@ -30,6 +30,7 @@
|
|
#define _EFER_SVME 12 /* Enable virtualization */
|
|
#define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */
|
|
#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */
|
|
+#define _EFER_AUTOIBRS 21 /* Enable Automatic IBRS */
|
|
|
|
#define EFER_SCE (1<<_EFER_SCE)
|
|
#define EFER_LME (1<<_EFER_LME)
|
|
@@ -38,6 +39,7 @@
|
|
#define EFER_SVME (1<<_EFER_SVME)
|
|
#define EFER_LMSLE (1<<_EFER_LMSLE)
|
|
#define EFER_FFXSR (1<<_EFER_FFXSR)
|
|
+#define EFER_AUTOIBRS (1<<_EFER_AUTOIBRS)
|
|
|
|
/* Intel MSRs. Some also available on other CPUs */
|
|
|
|
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
|
|
index 53623ea69873..43295a878b8f 100644
|
|
--- a/arch/x86/kernel/cpu/bugs.c
|
|
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
@@ -1177,9 +1177,9 @@ static const char * const spectre_v2_strings[] = {
|
|
[SPECTRE_V2_NONE] = "Vulnerable",
|
|
[SPECTRE_V2_RETPOLINE] = "Mitigation: Retpolines",
|
|
[SPECTRE_V2_LFENCE] = "Mitigation: LFENCE",
|
|
- [SPECTRE_V2_EIBRS] = "Mitigation: Enhanced IBRS",
|
|
- [SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced IBRS + LFENCE",
|
|
- [SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced IBRS + Retpolines",
|
|
+ [SPECTRE_V2_EIBRS] = "Mitigation: Enhanced / Automatic IBRS",
|
|
+ [SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced / Automatic IBRS + LFENCE",
|
|
+ [SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced / Automatic IBRS + Retpolines",
|
|
[SPECTRE_V2_IBRS] = "Mitigation: IBRS",
|
|
[SPECTRE_V2_IBRS_ALWAYS] = "Mitigation: IBRS (kernel and user space)",
|
|
[SPECTRE_V2_RETPOLINE_IBRS_USER] = "Mitigation: Full retpoline and IBRS (user space)",
|
|
@@ -1253,7 +1253,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
|
cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
|
|
cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) &&
|
|
!boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
|
|
- pr_err("%s selected but CPU doesn't have eIBRS. Switching to AUTO select\n",
|
|
+ pr_err("%s selected but CPU doesn't have Enhanced or Automatic IBRS. Switching to AUTO select\n",
|
|
mitigation_options[i].option);
|
|
return SPECTRE_V2_CMD_AUTO;
|
|
}
|
|
@@ -1446,8 +1446,12 @@ static void __init spectre_v2_select_mitigation(void)
|
|
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
|
|
|
|
if (spectre_v2_in_ibrs_mode(mode)) {
|
|
- x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
|
|
- update_spec_ctrl(x86_spec_ctrl_base);
|
|
+ if (boot_cpu_has(X86_FEATURE_AUTOIBRS)) {
|
|
+ msr_set_bit(MSR_EFER, _EFER_AUTOIBRS);
|
|
+ } else {
|
|
+ x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
|
|
+ update_spec_ctrl(x86_spec_ctrl_base);
|
|
+ }
|
|
}
|
|
|
|
switch (mode) {
|
|
@@ -1542,8 +1546,8 @@ static void __init spectre_v2_select_mitigation(void)
|
|
/*
|
|
* Retpoline protects the kernel, but doesn't protect firmware. IBRS
|
|
* and Enhanced IBRS protect firmware too, so enable IBRS around
|
|
- * firmware calls only when IBRS / Enhanced IBRS aren't otherwise
|
|
- * enabled.
|
|
+ * firmware calls only when IBRS / Enhanced / Automatic IBRS aren't
|
|
+ * otherwise enabled.
|
|
*
|
|
* Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
|
|
* the user might select retpoline on the kernel command line and if
|
|
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
|
|
index a8dfd75588cd..c5c08a3ace2a 100644
|
|
--- a/arch/x86/kernel/cpu/common.c
|
|
+++ b/arch/x86/kernel/cpu/common.c
|
|
@@ -1091,7 +1091,7 @@ static const __initconst struct x86_cpu_id_v2 cpu_vuln_whitelist[] = {
|
|
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
|
|
|
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
|
|
- VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
|
+ VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
|
|
{}
|
|
};
|
|
|
|
@@ -1196,8 +1196,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
|
!cpu_has(c, X86_FEATURE_AMD_SSB_NO))
|
|
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
|
|
|
- if (ia32_cap & ARCH_CAP_IBRS_ALL)
|
|
+ /*
|
|
+ * AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
|
|
+ * flag and protect from vendor-specific bugs via the whitelist.
|
|
+ */
|
|
+ if ((ia32_cap & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
|
|
setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
|
|
+ if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
|
+ !(ia32_cap & ARCH_CAP_PBRSB_NO))
|
|
+ setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
|
+ }
|
|
|
|
if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
|
|
!(ia32_cap & ARCH_CAP_MDS_NO)) {
|
|
@@ -1259,11 +1267,6 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
|
setup_force_cpu_bug(X86_BUG_RETBLEED);
|
|
}
|
|
|
|
- if (cpu_has(c, X86_FEATURE_IBRS_ENHANCED) &&
|
|
- !cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
|
- !(ia32_cap & ARCH_CAP_PBRSB_NO))
|
|
- setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
|
-
|
|
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
|
return;
|
|
|
|
--
|
|
2.39.3
|
|
|