@@ -92,6 +92,8 @@ static void __init bhi_select_mitigation(void);
9292static void __init bhi_update_mitigation (void );
9393static void __init bhi_apply_mitigation (void );
9494static 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 */
9799u64 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+
11181137enum 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-
13551368static 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-
13671375static 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
13961404static 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