Skip to content

Commit 61ab72c

Browse files
dkaplan2Ingo Molnar
authored andcommitted
x86/bugs: Restructure ITS mitigation
Restructure the ITS mitigation to use select/update/apply functions like the other mitigations. There is a particularly complex interaction between ITS and Retbleed as CDT (Call Depth Tracking) is a mitigation for both, and either its=stuff or retbleed=stuff will attempt to enable CDT. retbleed_update_mitigation() runs first and will check the necessary pre-conditions for CDT if either ITS or Retbleed stuffing is selected. If checks pass and ITS stuffing is selected, it will select stuffing for Retbleed as well. its_update_mitigation() runs after and will either select stuffing if retbleed stuffing was enabled, or fall back to the default (aligned thunks) if stuffing could not be enabled. Enablement of CDT is done exclusively in retbleed_apply_mitigation(). its_apply_mitigation() is only used to enable aligned thunks. Signed-off-by: David Kaplan <david.kaplan@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/20250516193212.128782-1-david.kaplan@amd.com
1 parent 412751a commit 61ab72c

File tree

1 file changed

+90
-77
lines changed

1 file changed

+90
-77
lines changed

arch/x86/kernel/cpu/bugs.c

Lines changed: 90 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ static void __init bhi_select_mitigation(void);
9292
static void __init bhi_update_mitigation(void);
9393
static void __init bhi_apply_mitigation(void);
9494
static void __init its_select_mitigation(void);
95+
static void __init its_update_mitigation(void);
96+
static void __init its_apply_mitigation(void);
9597

9698
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
9799
u64 x86_spec_ctrl_base;
@@ -235,6 +237,11 @@ void __init cpu_select_mitigations(void)
235237
* spectre_v2=ibrs.
236238
*/
237239
retbleed_update_mitigation();
240+
/*
241+
* its_update_mitigation() depends on spectre_v2_update_mitigation()
242+
* and retbleed_update_mitigation().
243+
*/
244+
its_update_mitigation();
238245

239246
/*
240247
* spectre_v2_user_update_mitigation() depends on
@@ -263,6 +270,7 @@ void __init cpu_select_mitigations(void)
263270
srbds_apply_mitigation();
264271
srso_apply_mitigation();
265272
gds_apply_mitigation();
273+
its_apply_mitigation();
266274
bhi_apply_mitigation();
267275
}
268276

@@ -1115,6 +1123,17 @@ enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = SPECTRE_V2_NONE;
11151123
#undef pr_fmt
11161124
#define pr_fmt(fmt) "RETBleed: " fmt
11171125

1126+
enum its_mitigation {
1127+
ITS_MITIGATION_OFF,
1128+
ITS_MITIGATION_AUTO,
1129+
ITS_MITIGATION_VMEXIT_ONLY,
1130+
ITS_MITIGATION_ALIGNED_THUNKS,
1131+
ITS_MITIGATION_RETPOLINE_STUFF,
1132+
};
1133+
1134+
static enum its_mitigation its_mitigation __ro_after_init =
1135+
IS_ENABLED(CONFIG_MITIGATION_ITS) ? ITS_MITIGATION_AUTO : ITS_MITIGATION_OFF;
1136+
11181137
enum retbleed_mitigation {
11191138
RETBLEED_MITIGATION_NONE,
11201139
RETBLEED_MITIGATION_AUTO,
@@ -1242,11 +1261,19 @@ static void __init retbleed_update_mitigation(void)
12421261
/*
12431262
* retbleed=stuff is only allowed on Intel. If stuffing can't be used
12441263
* then a different mitigation will be selected below.
1264+
*
1265+
* its=stuff will also attempt to enable stuffing.
12451266
*/
1246-
if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF) {
1267+
if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF ||
1268+
its_mitigation == ITS_MITIGATION_RETPOLINE_STUFF) {
12471269
if (spectre_v2_enabled != SPECTRE_V2_RETPOLINE) {
12481270
pr_err("WARNING: retbleed=stuff depends on spectre_v2=retpoline\n");
12491271
retbleed_mitigation = RETBLEED_MITIGATION_AUTO;
1272+
} else {
1273+
if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF)
1274+
pr_info("Retbleed mitigation updated to stuffing\n");
1275+
1276+
retbleed_mitigation = RETBLEED_MITIGATION_STUFF;
12501277
}
12511278
}
12521279
/*
@@ -1338,32 +1365,13 @@ static void __init retbleed_apply_mitigation(void)
13381365
#undef pr_fmt
13391366
#define pr_fmt(fmt) "ITS: " fmt
13401367

1341-
enum its_mitigation_cmd {
1342-
ITS_CMD_OFF,
1343-
ITS_CMD_ON,
1344-
ITS_CMD_VMEXIT,
1345-
ITS_CMD_RSB_STUFF,
1346-
};
1347-
1348-
enum its_mitigation {
1349-
ITS_MITIGATION_OFF,
1350-
ITS_MITIGATION_VMEXIT_ONLY,
1351-
ITS_MITIGATION_ALIGNED_THUNKS,
1352-
ITS_MITIGATION_RETPOLINE_STUFF,
1353-
};
1354-
13551368
static const char * const its_strings[] = {
13561369
[ITS_MITIGATION_OFF] = "Vulnerable",
13571370
[ITS_MITIGATION_VMEXIT_ONLY] = "Mitigation: Vulnerable, KVM: Not affected",
13581371
[ITS_MITIGATION_ALIGNED_THUNKS] = "Mitigation: Aligned branch/return thunks",
13591372
[ITS_MITIGATION_RETPOLINE_STUFF] = "Mitigation: Retpolines, Stuffing RSB",
13601373
};
13611374

1362-
static enum its_mitigation its_mitigation __ro_after_init = ITS_MITIGATION_ALIGNED_THUNKS;
1363-
1364-
static enum its_mitigation_cmd its_cmd __ro_after_init =
1365-
IS_ENABLED(CONFIG_MITIGATION_ITS) ? ITS_CMD_ON : ITS_CMD_OFF;
1366-
13671375
static int __init its_parse_cmdline(char *str)
13681376
{
13691377
if (!str)
@@ -1375,16 +1383,16 @@ static int __init its_parse_cmdline(char *str)
13751383
}
13761384

13771385
if (!strcmp(str, "off")) {
1378-
its_cmd = ITS_CMD_OFF;
1386+
its_mitigation = ITS_MITIGATION_OFF;
13791387
} else if (!strcmp(str, "on")) {
1380-
its_cmd = ITS_CMD_ON;
1388+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
13811389
} else if (!strcmp(str, "force")) {
1382-
its_cmd = ITS_CMD_ON;
1390+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
13831391
setup_force_cpu_bug(X86_BUG_ITS);
13841392
} else if (!strcmp(str, "vmexit")) {
1385-
its_cmd = ITS_CMD_VMEXIT;
1393+
its_mitigation = ITS_MITIGATION_VMEXIT_ONLY;
13861394
} else if (!strcmp(str, "stuff")) {
1387-
its_cmd = ITS_CMD_RSB_STUFF;
1395+
its_mitigation = ITS_MITIGATION_RETPOLINE_STUFF;
13881396
} else {
13891397
pr_err("Ignoring unknown indirect_target_selection option (%s).", str);
13901398
}
@@ -1395,85 +1403,90 @@ early_param("indirect_target_selection", its_parse_cmdline);
13951403

13961404
static void __init its_select_mitigation(void)
13971405
{
1398-
enum its_mitigation_cmd cmd = its_cmd;
1399-
14001406
if (!boot_cpu_has_bug(X86_BUG_ITS) || cpu_mitigations_off()) {
14011407
its_mitigation = ITS_MITIGATION_OFF;
14021408
return;
14031409
}
14041410

1405-
/* Retpoline+CDT mitigates ITS, bail out */
1406-
if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
1407-
boot_cpu_has(X86_FEATURE_CALL_DEPTH)) {
1408-
its_mitigation = ITS_MITIGATION_RETPOLINE_STUFF;
1409-
goto out;
1410-
}
1411+
if (its_mitigation == ITS_MITIGATION_AUTO)
1412+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
1413+
1414+
if (its_mitigation == ITS_MITIGATION_OFF)
1415+
return;
14111416

1412-
/* Exit early to avoid irrelevant warnings */
1413-
if (cmd == ITS_CMD_OFF) {
1414-
its_mitigation = ITS_MITIGATION_OFF;
1415-
goto out;
1416-
}
1417-
if (spectre_v2_enabled == SPECTRE_V2_NONE) {
1418-
pr_err("WARNING: Spectre-v2 mitigation is off, disabling ITS\n");
1419-
its_mitigation = ITS_MITIGATION_OFF;
1420-
goto out;
1421-
}
14221417
if (!IS_ENABLED(CONFIG_MITIGATION_RETPOLINE) ||
14231418
!IS_ENABLED(CONFIG_MITIGATION_RETHUNK)) {
14241419
pr_err("WARNING: ITS mitigation depends on retpoline and rethunk support\n");
14251420
its_mitigation = ITS_MITIGATION_OFF;
1426-
goto out;
1421+
return;
14271422
}
1423+
14281424
if (IS_ENABLED(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B)) {
14291425
pr_err("WARNING: ITS mitigation is not compatible with CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B\n");
14301426
its_mitigation = ITS_MITIGATION_OFF;
1431-
goto out;
1432-
}
1433-
if (boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
1434-
pr_err("WARNING: ITS mitigation is not compatible with lfence mitigation\n");
1435-
its_mitigation = ITS_MITIGATION_OFF;
1436-
goto out;
1427+
return;
14371428
}
14381429

1439-
if (cmd == ITS_CMD_RSB_STUFF &&
1440-
(!boot_cpu_has(X86_FEATURE_RETPOLINE) || !IS_ENABLED(CONFIG_MITIGATION_CALL_DEPTH_TRACKING))) {
1430+
if (its_mitigation == ITS_MITIGATION_RETPOLINE_STUFF &&
1431+
!IS_ENABLED(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)) {
14411432
pr_err("RSB stuff mitigation not supported, using default\n");
1442-
cmd = ITS_CMD_ON;
1433+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
14431434
}
14441435

1445-
switch (cmd) {
1446-
case ITS_CMD_OFF:
1436+
if (its_mitigation == ITS_MITIGATION_VMEXIT_ONLY &&
1437+
!boot_cpu_has_bug(X86_BUG_ITS_NATIVE_ONLY))
1438+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
1439+
}
1440+
1441+
static void __init its_update_mitigation(void)
1442+
{
1443+
if (!boot_cpu_has_bug(X86_BUG_ITS) || cpu_mitigations_off())
1444+
return;
1445+
1446+
switch (spectre_v2_enabled) {
1447+
case SPECTRE_V2_NONE:
1448+
pr_err("WARNING: Spectre-v2 mitigation is off, disabling ITS\n");
14471449
its_mitigation = ITS_MITIGATION_OFF;
14481450
break;
1449-
case ITS_CMD_VMEXIT:
1450-
if (boot_cpu_has_bug(X86_BUG_ITS_NATIVE_ONLY)) {
1451-
its_mitigation = ITS_MITIGATION_VMEXIT_ONLY;
1452-
goto out;
1453-
}
1454-
fallthrough;
1455-
case ITS_CMD_ON:
1456-
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
1457-
if (!boot_cpu_has(X86_FEATURE_RETPOLINE))
1458-
setup_force_cpu_cap(X86_FEATURE_INDIRECT_THUNK_ITS);
1459-
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
1460-
set_return_thunk(its_return_thunk);
1451+
case SPECTRE_V2_RETPOLINE:
1452+
/* Retpoline+CDT mitigates ITS */
1453+
if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF)
1454+
its_mitigation = ITS_MITIGATION_RETPOLINE_STUFF;
14611455
break;
1462-
case ITS_CMD_RSB_STUFF:
1463-
its_mitigation = ITS_MITIGATION_RETPOLINE_STUFF;
1464-
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
1465-
setup_force_cpu_cap(X86_FEATURE_CALL_DEPTH);
1466-
set_return_thunk(call_depth_return_thunk);
1467-
if (retbleed_mitigation == RETBLEED_MITIGATION_NONE) {
1468-
retbleed_mitigation = RETBLEED_MITIGATION_STUFF;
1469-
pr_info("Retbleed mitigation updated to stuffing\n");
1470-
}
1456+
case SPECTRE_V2_LFENCE:
1457+
case SPECTRE_V2_EIBRS_LFENCE:
1458+
pr_err("WARNING: ITS mitigation is not compatible with lfence mitigation\n");
1459+
its_mitigation = ITS_MITIGATION_OFF;
1460+
break;
1461+
default:
14711462
break;
14721463
}
1473-
out:
1464+
1465+
/*
1466+
* retbleed_update_mitigation() will try to do stuffing if its=stuff.
1467+
* If it can't, such as if spectre_v2!=retpoline, then fall back to
1468+
* aligned thunks.
1469+
*/
1470+
if (its_mitigation == ITS_MITIGATION_RETPOLINE_STUFF &&
1471+
retbleed_mitigation != RETBLEED_MITIGATION_STUFF)
1472+
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
1473+
14741474
pr_info("%s\n", its_strings[its_mitigation]);
14751475
}
14761476

1477+
static void __init its_apply_mitigation(void)
1478+
{
1479+
/* its=stuff forces retbleed stuffing and is enabled there. */
1480+
if (its_mitigation != ITS_MITIGATION_ALIGNED_THUNKS)
1481+
return;
1482+
1483+
if (!boot_cpu_has(X86_FEATURE_RETPOLINE))
1484+
setup_force_cpu_cap(X86_FEATURE_INDIRECT_THUNK_ITS);
1485+
1486+
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
1487+
set_return_thunk(its_return_thunk);
1488+
}
1489+
14771490
#undef pr_fmt
14781491
#define pr_fmt(fmt) "Spectre V2 : " fmt
14791492

0 commit comments

Comments
 (0)