#define X86_FEATURE_IBRS ( 7*32+20) /* Control Speculation Control */
#define X86_FEATURE_STIBP ( 7*32+21) /* Single Thread Indirect Branch Predictors */
#define X86_FEATURE_IA32_ARCH_CAPS ( 7*32+22) /* Control Speculation Control */
-#define X86_FEATURE_IBRS_ALL ( 7*32+23) /* IBRS all the time */
+#define X86_FEATURE_IBRS_ENHANCED ( 7*32+23) /* IBRS all the time */
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13.
* But thanks to kABI we have to jam it somewhere else. */
/*
* Define the current state.
*
- * IBRS firmware is enabled if either IBRS or retpoline is enabled.
- * If both IBRS and retpoline are disabled, then IBRS firmware is
- * disabled too.
+ * IBRS firmware is enabled if either basic IBRS or retpoline is
+ * enabled. If both IBRS and retpoline are disabled, then IBRS firmware
+ * is disabled too.
*/
ibrs_used = !ibrs_disabled;
retpoline_used = !!retpoline_enabled();
- ibrs_fw_used = (ibrs_used || retpoline_used);
+ ibrs_fw_used = ((ibrs_used && !eibrs_supported) || retpoline_used);
/*
* Define the requested state.
case SPECTRE_V2_ENABLE_IBRS:
ibrs_requested = true;
- ibrs_fw_requested = true;
+ ibrs_fw_requested = !eibrs_supported;
retpoline_requested = false;
break;
case SPECTRE_V2_DISABLE_RETPOLINE:
ibrs_requested = ibrs_used;
- ibrs_fw_requested = ibrs_used;
+ ibrs_fw_requested = ibrs_used && !eibrs_supported;
retpoline_requested = false;
break;
}
if (ibrs_requested != ibrs_used) {
if (ibrs_requested) {
clear_ibrs_disabled();
+ /* If enhanced IBRS is available, turn it on now */
+ if (eibrs_supported)
+ spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
+ x86_spec_ctrl_priv);
} else {
set_ibrs_disabled();
if (use_ibrs & SPEC_CTRL_IBRS_SUPPORTED) {
if (cmd == SPECTRE_V2_CMD_IBRS || !IS_ENABLED(CONFIG_RETPOLINE)) {
ibrs_select(&mode);
- if (mode != SPECTRE_V2_NONE)
+ if (mode != SPECTRE_V2_NONE) {
+ /* One of the IBRS modes was successfully selected */
goto display;
+ }
if (!IS_ENABLED(CONFIG_RETPOLINE)) {
pr_err("Spectre mitigation: kernel not compiled with retpoline; no mitigation available!");
goto out;
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
pr_info("Filling RSB on context switch\n");
- /* IBRS is unnecessary with retpoline mitigation. */
- if (mode == SPECTRE_V2_RETPOLINE_GENERIC ||
- mode == SPECTRE_V2_RETPOLINE_AMD) {
+ if (mode == SPECTRE_V2_IBRS_ENHANCED) {
+ /* If enhanced IBRS is available, enable it on all cpus now */
+ spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
+ x86_spec_ctrl_base | SPEC_CTRL_FEATURE_ENABLE_IBRS);
+
+ } else if (mode == SPECTRE_V2_RETPOLINE_GENERIC ||
+ mode == SPECTRE_V2_RETPOLINE_AMD) {
disable_ibrs_and_friends(false /* set not-in-use */);
}
+
/* Future CPUs with IBRS_ALL might be able to avoid this. */
setup_force_cpu_cap(X86_FEATURE_VMEXIT_RSB_FULL);
u64 cap;
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, cap);
if (cap & 2) /* IBRS all the time */
- set_cpu_cap(c, X86_FEATURE_IBRS_ALL);
+ set_cpu_cap(c, X86_FEATURE_IBRS_ENHANCED);
}
if (cpu_has(c, X86_FEATURE_IBRS))
mutex_lock(&spec_ctrl_mutex);
if (cpu_has(c, X86_FEATURE_IBRS)) {
set_ibrs_supported();
- /*
- * Don't do this after disable_ibrs_and_friends as we
- * would re-enable it (say if spectre_v2=off is used).
- */
- set_ibrs_firmware();
+ /* Enable enhanced IBRS usage if available */
+ if (cpu_has(c, X86_FEATURE_IBRS_ENHANCED)) {
+ set_ibrs_enhanced();
+ } else {
+ /*
+ * Don't do this after disable_ibrs_and_friends
+ * as we would re-enable it (say if
+ * spectre_v2=off is used).
+ */
+ set_ibrs_firmware();
+ }
}
if (cpu_has(c, X86_FEATURE_IBPB))
set_ibpb_supported();