Skip to content

Commit 7c693f5

Browse files
pa1guptasuryasaimadhu
authored andcommitted
x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
Extend spectre_v2= boot option with Kernel IBRS. [jpoimboe: no STIBP with IBRS] Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Borislav Petkov <bp@suse.de>
1 parent c779bc1 commit 7c693f5

3 files changed

Lines changed: 54 additions & 14 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5589,6 +5589,7 @@
55895589
eibrs - enhanced IBRS
55905590
eibrs,retpoline - enhanced IBRS + Retpolines
55915591
eibrs,lfence - enhanced IBRS + LFENCE
5592+
ibrs - use IBRS to protect kernel
55925593

55935594
Not specifying this option is equivalent to
55945595
spectre_v2=auto.

arch/x86/include/asm/nospec-branch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ enum spectre_v2_mitigation {
211211
SPECTRE_V2_EIBRS,
212212
SPECTRE_V2_EIBRS_RETPOLINE,
213213
SPECTRE_V2_EIBRS_LFENCE,
214+
SPECTRE_V2_IBRS,
214215
};
215216

216217
/* The indirect branch speculation control variants */

arch/x86/kernel/cpu/bugs.c

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,7 @@ enum spectre_v2_mitigation_cmd {
972972
SPECTRE_V2_CMD_EIBRS,
973973
SPECTRE_V2_CMD_EIBRS_RETPOLINE,
974974
SPECTRE_V2_CMD_EIBRS_LFENCE,
975+
SPECTRE_V2_CMD_IBRS,
975976
};
976977

977978
enum spectre_v2_user_cmd {
@@ -1044,11 +1045,12 @@ spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
10441045
return SPECTRE_V2_USER_CMD_AUTO;
10451046
}
10461047

1047-
static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
1048+
static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
10481049
{
1049-
return (mode == SPECTRE_V2_EIBRS ||
1050-
mode == SPECTRE_V2_EIBRS_RETPOLINE ||
1051-
mode == SPECTRE_V2_EIBRS_LFENCE);
1050+
return mode == SPECTRE_V2_IBRS ||
1051+
mode == SPECTRE_V2_EIBRS ||
1052+
mode == SPECTRE_V2_EIBRS_RETPOLINE ||
1053+
mode == SPECTRE_V2_EIBRS_LFENCE;
10521054
}
10531055

10541056
static void __init
@@ -1113,12 +1115,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
11131115
}
11141116

11151117
/*
1116-
* If no STIBP, enhanced IBRS is enabled or SMT impossible, STIBP is not
1117-
* required.
1118+
* If no STIBP, IBRS or enhanced IBRS is enabled, or SMT impossible,
1119+
* STIBP is not required.
11181120
*/
11191121
if (!boot_cpu_has(X86_FEATURE_STIBP) ||
11201122
!smt_possible ||
1121-
spectre_v2_in_eibrs_mode(spectre_v2_enabled))
1123+
spectre_v2_in_ibrs_mode(spectre_v2_enabled))
11221124
return;
11231125

11241126
/*
@@ -1150,6 +1152,7 @@ static const char * const spectre_v2_strings[] = {
11501152
[SPECTRE_V2_EIBRS] = "Mitigation: Enhanced IBRS",
11511153
[SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced IBRS + LFENCE",
11521154
[SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced IBRS + Retpolines",
1155+
[SPECTRE_V2_IBRS] = "Mitigation: IBRS",
11531156
};
11541157

11551158
static const struct {
@@ -1167,6 +1170,7 @@ static const struct {
11671170
{ "eibrs,lfence", SPECTRE_V2_CMD_EIBRS_LFENCE, false },
11681171
{ "eibrs,retpoline", SPECTRE_V2_CMD_EIBRS_RETPOLINE, false },
11691172
{ "auto", SPECTRE_V2_CMD_AUTO, false },
1173+
{ "ibrs", SPECTRE_V2_CMD_IBRS, false },
11701174
};
11711175

11721176
static void __init spec_v2_print_cond(const char *reason, bool secure)
@@ -1229,6 +1233,24 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
12291233
return SPECTRE_V2_CMD_AUTO;
12301234
}
12311235

1236+
if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
1237+
pr_err("%s selected but not Intel CPU. Switching to AUTO select\n",
1238+
mitigation_options[i].option);
1239+
return SPECTRE_V2_CMD_AUTO;
1240+
}
1241+
1242+
if (cmd == SPECTRE_V2_CMD_IBRS && !boot_cpu_has(X86_FEATURE_IBRS)) {
1243+
pr_err("%s selected but CPU doesn't have IBRS. Switching to AUTO select\n",
1244+
mitigation_options[i].option);
1245+
return SPECTRE_V2_CMD_AUTO;
1246+
}
1247+
1248+
if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_has(X86_FEATURE_XENPV)) {
1249+
pr_err("%s selected but running as XenPV guest. Switching to AUTO select\n",
1250+
mitigation_options[i].option);
1251+
return SPECTRE_V2_CMD_AUTO;
1252+
}
1253+
12321254
spec_v2_print_cond(mitigation_options[i].option,
12331255
mitigation_options[i].secure);
12341256
return cmd;
@@ -1268,6 +1290,14 @@ static void __init spectre_v2_select_mitigation(void)
12681290
break;
12691291
}
12701292

1293+
if (boot_cpu_has_bug(X86_BUG_RETBLEED) &&
1294+
retbleed_cmd != RETBLEED_CMD_OFF &&
1295+
boot_cpu_has(X86_FEATURE_IBRS) &&
1296+
boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
1297+
mode = SPECTRE_V2_IBRS;
1298+
break;
1299+
}
1300+
12711301
mode = spectre_v2_select_retpoline();
12721302
break;
12731303

@@ -1284,6 +1314,10 @@ static void __init spectre_v2_select_mitigation(void)
12841314
mode = spectre_v2_select_retpoline();
12851315
break;
12861316

1317+
case SPECTRE_V2_CMD_IBRS:
1318+
mode = SPECTRE_V2_IBRS;
1319+
break;
1320+
12871321
case SPECTRE_V2_CMD_EIBRS:
12881322
mode = SPECTRE_V2_EIBRS;
12891323
break;
@@ -1300,7 +1334,7 @@ static void __init spectre_v2_select_mitigation(void)
13001334
if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
13011335
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
13021336

1303-
if (spectre_v2_in_eibrs_mode(mode)) {
1337+
if (spectre_v2_in_ibrs_mode(mode)) {
13041338
/* Force it so VMEXIT will restore correctly */
13051339
x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
13061340
write_spec_ctrl_current(x86_spec_ctrl_base, true);
@@ -1311,6 +1345,10 @@ static void __init spectre_v2_select_mitigation(void)
13111345
case SPECTRE_V2_EIBRS:
13121346
break;
13131347

1348+
case SPECTRE_V2_IBRS:
1349+
setup_force_cpu_cap(X86_FEATURE_KERNEL_IBRS);
1350+
break;
1351+
13141352
case SPECTRE_V2_LFENCE:
13151353
case SPECTRE_V2_EIBRS_LFENCE:
13161354
setup_force_cpu_cap(X86_FEATURE_RETPOLINE_LFENCE);
@@ -1337,17 +1375,17 @@ static void __init spectre_v2_select_mitigation(void)
13371375
pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
13381376

13391377
/*
1340-
* Retpoline means the kernel is safe because it has no indirect
1341-
* branches. Enhanced IBRS protects firmware too, so, enable restricted
1342-
* speculation around firmware calls only when Enhanced IBRS isn't
1343-
* supported.
1378+
* Retpoline protects the kernel, but doesn't protect firmware. IBRS
1379+
* and Enhanced IBRS protect firmware too, so enable IBRS around
1380+
* firmware calls only when IBRS / Enhanced IBRS aren't otherwise
1381+
* enabled.
13441382
*
13451383
* Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
13461384
* the user might select retpoline on the kernel command line and if
13471385
* the CPU supports Enhanced IBRS, kernel might un-intentionally not
13481386
* enable IBRS around firmware calls.
13491387
*/
1350-
if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_eibrs_mode(mode)) {
1388+
if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_ibrs_mode(mode)) {
13511389
setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
13521390
pr_info("Enabling Restricted Speculation for firmware calls\n");
13531391
}
@@ -2089,7 +2127,7 @@ static ssize_t mmio_stale_data_show_state(char *buf)
20892127

20902128
static char *stibp_state(void)
20912129
{
2092-
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
2130+
if (spectre_v2_in_ibrs_mode(spectre_v2_enabled))
20932131
return "";
20942132

20952133
switch (spectre_v2_user_stibp) {

0 commit comments

Comments
 (0)