@@ -94,6 +94,8 @@ static void __init bhi_apply_mitigation(void);
9494static void __init its_select_mitigation (void );
9595static void __init its_update_mitigation (void );
9696static void __init its_apply_mitigation (void );
97+ static void __init tsa_select_mitigation (void );
98+ static void __init tsa_apply_mitigation (void );
9799
98100/* The base value of the SPEC_CTRL MSR without task-specific bits set */
99101u64 x86_spec_ctrl_base ;
@@ -225,6 +227,7 @@ void __init cpu_select_mitigations(void)
225227 gds_select_mitigation ();
226228 its_select_mitigation ();
227229 bhi_select_mitigation ();
230+ tsa_select_mitigation ();
228231
229232 /*
230233 * After mitigations are selected, some may need to update their
@@ -272,6 +275,7 @@ void __init cpu_select_mitigations(void)
272275 gds_apply_mitigation ();
273276 its_apply_mitigation ();
274277 bhi_apply_mitigation ();
278+ tsa_apply_mitigation ();
275279}
276280
277281/*
@@ -1487,6 +1491,94 @@ static void __init its_apply_mitigation(void)
14871491 set_return_thunk (its_return_thunk );
14881492}
14891493
1494+ #undef pr_fmt
1495+ #define pr_fmt (fmt ) "Transient Scheduler Attacks: " fmt
1496+
1497+ enum tsa_mitigations {
1498+ TSA_MITIGATION_NONE ,
1499+ TSA_MITIGATION_AUTO ,
1500+ TSA_MITIGATION_UCODE_NEEDED ,
1501+ TSA_MITIGATION_USER_KERNEL ,
1502+ TSA_MITIGATION_VM ,
1503+ TSA_MITIGATION_FULL ,
1504+ };
1505+
1506+ static const char * const tsa_strings [] = {
1507+ [TSA_MITIGATION_NONE ] = "Vulnerable" ,
1508+ [TSA_MITIGATION_UCODE_NEEDED ] = "Vulnerable: No microcode" ,
1509+ [TSA_MITIGATION_USER_KERNEL ] = "Mitigation: Clear CPU buffers: user/kernel boundary" ,
1510+ [TSA_MITIGATION_VM ] = "Mitigation: Clear CPU buffers: VM" ,
1511+ [TSA_MITIGATION_FULL ] = "Mitigation: Clear CPU buffers" ,
1512+ };
1513+
1514+ static enum tsa_mitigations tsa_mitigation __ro_after_init =
1515+ IS_ENABLED (CONFIG_MITIGATION_TSA ) ? TSA_MITIGATION_AUTO : TSA_MITIGATION_NONE ;
1516+
1517+ static int __init tsa_parse_cmdline (char * str )
1518+ {
1519+ if (!str )
1520+ return - EINVAL ;
1521+
1522+ if (!strcmp (str , "off" ))
1523+ tsa_mitigation = TSA_MITIGATION_NONE ;
1524+ else if (!strcmp (str , "on" ))
1525+ tsa_mitigation = TSA_MITIGATION_FULL ;
1526+ else if (!strcmp (str , "user" ))
1527+ tsa_mitigation = TSA_MITIGATION_USER_KERNEL ;
1528+ else if (!strcmp (str , "vm" ))
1529+ tsa_mitigation = TSA_MITIGATION_VM ;
1530+ else
1531+ pr_err ("Ignoring unknown tsa=%s option.\n" , str );
1532+
1533+ return 0 ;
1534+ }
1535+ early_param ("tsa" , tsa_parse_cmdline );
1536+
1537+ static void __init tsa_select_mitigation (void )
1538+ {
1539+ if (cpu_mitigations_off () || !boot_cpu_has_bug (X86_BUG_TSA )) {
1540+ tsa_mitigation = TSA_MITIGATION_NONE ;
1541+ return ;
1542+ }
1543+
1544+ if (tsa_mitigation == TSA_MITIGATION_NONE )
1545+ return ;
1546+
1547+ if (!boot_cpu_has (X86_FEATURE_VERW_CLEAR )) {
1548+ tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED ;
1549+ goto out ;
1550+ }
1551+
1552+ if (tsa_mitigation == TSA_MITIGATION_AUTO )
1553+ tsa_mitigation = TSA_MITIGATION_FULL ;
1554+
1555+ /*
1556+ * No need to set verw_clear_cpu_buf_mitigation_selected - it
1557+ * doesn't fit all cases here and it is not needed because this
1558+ * is the only VERW-based mitigation on AMD.
1559+ */
1560+ out :
1561+ pr_info ("%s\n" , tsa_strings [tsa_mitigation ]);
1562+ }
1563+
1564+ static void __init tsa_apply_mitigation (void )
1565+ {
1566+ switch (tsa_mitigation ) {
1567+ case TSA_MITIGATION_USER_KERNEL :
1568+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
1569+ break ;
1570+ case TSA_MITIGATION_VM :
1571+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
1572+ break ;
1573+ case TSA_MITIGATION_FULL :
1574+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
1575+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
1576+ break ;
1577+ default :
1578+ break ;
1579+ }
1580+ }
1581+
14901582#undef pr_fmt
14911583#define pr_fmt (fmt ) "Spectre V2 : " fmt
14921584
@@ -2316,6 +2408,25 @@ void cpu_bugs_smt_update(void)
23162408 break ;
23172409 }
23182410
2411+ switch (tsa_mitigation ) {
2412+ case TSA_MITIGATION_USER_KERNEL :
2413+ case TSA_MITIGATION_VM :
2414+ case TSA_MITIGATION_AUTO :
2415+ case TSA_MITIGATION_FULL :
2416+ /*
2417+ * TSA-SQ can potentially lead to info leakage between
2418+ * SMT threads.
2419+ */
2420+ if (sched_smt_active ())
2421+ static_branch_enable (& cpu_buf_idle_clear );
2422+ else
2423+ static_branch_disable (& cpu_buf_idle_clear );
2424+ break ;
2425+ case TSA_MITIGATION_NONE :
2426+ case TSA_MITIGATION_UCODE_NEEDED :
2427+ break ;
2428+ }
2429+
23192430 mutex_unlock (& spec_ctrl_mutex );
23202431}
23212432
@@ -3265,6 +3376,11 @@ static ssize_t gds_show_state(char *buf)
32653376 return sysfs_emit (buf , "%s\n" , gds_strings [gds_mitigation ]);
32663377}
32673378
3379+ static ssize_t tsa_show_state (char * buf )
3380+ {
3381+ return sysfs_emit (buf , "%s\n" , tsa_strings [tsa_mitigation ]);
3382+ }
3383+
32683384static ssize_t cpu_show_common (struct device * dev , struct device_attribute * attr ,
32693385 char * buf , unsigned int bug )
32703386{
@@ -3328,6 +3444,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
33283444 case X86_BUG_ITS :
33293445 return its_show_state (buf );
33303446
3447+ case X86_BUG_TSA :
3448+ return tsa_show_state (buf );
3449+
33313450 default :
33323451 break ;
33333452 }
@@ -3414,6 +3533,11 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
34143533{
34153534 return cpu_show_common (dev , attr , buf , X86_BUG_ITS );
34163535}
3536+
3537+ ssize_t cpu_show_tsa (struct device * dev , struct device_attribute * attr , char * buf )
3538+ {
3539+ return cpu_show_common (dev , attr , buf , X86_BUG_TSA );
3540+ }
34173541#endif
34183542
34193543void __warn_thunk (void )
0 commit comments