Commit e7862eda authored by Kim Phillips's avatar Kim Phillips Committed by Borislav Petkov (AMD)
Browse files

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: default avatarKim Phillips <kim.phillips@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Acked-by: default avatarSean Christopherson <seanjc@google.com>
Acked-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Link: https://lore.kernel.org/r/20230124163319.2277355-8-kim.phillips@amd.com
parent faabfcb1
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -610,9 +610,9 @@ 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
+3 −3
Original line number Diff line number Diff line
@@ -5729,9 +5729,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

			Not specifying this option is equivalent to
+1 −0
Original line number Diff line number Diff line
@@ -431,6 +431,7 @@
#define X86_FEATURE_NO_NESTED_DATA_BP	(20*32+ 0) /* "" No Nested Data Breakpoints */
#define X86_FEATURE_LFENCE_RDTSC	(20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */
#define X86_FEATURE_NULL_SEL_CLR_BASE	(20*32+ 6) /* "" Null Selector Clears Base */
#define X86_FEATURE_AUTOIBRS		(20*32+ 8) /* "" Automatic IBRS */
#define X86_FEATURE_NO_SMM_CTL_MSR	(20*32+ 9) /* "" SMM_CTL MSR is not present */

/*
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,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)
@@ -33,6 +34,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 */

+12 −8
Original line number Diff line number Diff line
@@ -1238,9 +1238,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",
};

@@ -1309,7 +1309,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;
	}
@@ -1495,9 +1495,13 @@ static void __init spectre_v2_select_mitigation(void)
		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);

	if (spectre_v2_in_ibrs_mode(mode)) {
		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) {
	case SPECTRE_V2_NONE:
@@ -1580,8 +1584,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
Loading