@@ -50,6 +50,7 @@ static void __init l1d_flush_select_mitigation(void);
5050static void __init srso_select_mitigation (void );
5151static void __init gds_select_mitigation (void );
5252static void __init its_select_mitigation (void );
53+ static void __init tsa_select_mitigation (void );
5354
5455/* The base value of the SPEC_CTRL MSR without task-specific bits set */
5556u64 x86_spec_ctrl_base ;
@@ -188,6 +189,7 @@ void __init cpu_select_mitigations(void)
188189 srso_select_mitigation ();
189190 gds_select_mitigation ();
190191 its_select_mitigation ();
192+ tsa_select_mitigation ();
191193}
192194
193195/*
@@ -2074,6 +2076,94 @@ static void update_mds_branch_idle(void)
20742076#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
20752077#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n"
20762078
2079+ #undef pr_fmt
2080+ #define pr_fmt (fmt ) "Transient Scheduler Attacks: " fmt
2081+
2082+ enum tsa_mitigations {
2083+ TSA_MITIGATION_NONE ,
2084+ TSA_MITIGATION_UCODE_NEEDED ,
2085+ TSA_MITIGATION_USER_KERNEL ,
2086+ TSA_MITIGATION_VM ,
2087+ TSA_MITIGATION_FULL ,
2088+ };
2089+
2090+ static const char * const tsa_strings [] = {
2091+ [TSA_MITIGATION_NONE ] = "Vulnerable" ,
2092+ [TSA_MITIGATION_UCODE_NEEDED ] = "Vulnerable: Clear CPU buffers attempted, no microcode" ,
2093+ [TSA_MITIGATION_USER_KERNEL ] = "Mitigation: Clear CPU buffers: user/kernel boundary" ,
2094+ [TSA_MITIGATION_VM ] = "Mitigation: Clear CPU buffers: VM" ,
2095+ [TSA_MITIGATION_FULL ] = "Mitigation: Clear CPU buffers" ,
2096+ };
2097+
2098+ static enum tsa_mitigations tsa_mitigation __ro_after_init =
2099+ IS_ENABLED (CONFIG_MITIGATION_TSA ) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE ;
2100+
2101+ static int __init tsa_parse_cmdline (char * str )
2102+ {
2103+ if (!str )
2104+ return - EINVAL ;
2105+
2106+ if (!strcmp (str , "off" ))
2107+ tsa_mitigation = TSA_MITIGATION_NONE ;
2108+ else if (!strcmp (str , "on" ))
2109+ tsa_mitigation = TSA_MITIGATION_FULL ;
2110+ else if (!strcmp (str , "user" ))
2111+ tsa_mitigation = TSA_MITIGATION_USER_KERNEL ;
2112+ else if (!strcmp (str , "vm" ))
2113+ tsa_mitigation = TSA_MITIGATION_VM ;
2114+ else
2115+ pr_err ("Ignoring unknown tsa=%s option.\n" , str );
2116+
2117+ return 0 ;
2118+ }
2119+ early_param ("tsa" , tsa_parse_cmdline );
2120+
2121+ static void __init tsa_select_mitigation (void )
2122+ {
2123+ if (tsa_mitigation == TSA_MITIGATION_NONE )
2124+ return ;
2125+
2126+ if (cpu_mitigations_off () || !boot_cpu_has_bug (X86_BUG_TSA )) {
2127+ tsa_mitigation = TSA_MITIGATION_NONE ;
2128+ return ;
2129+ }
2130+
2131+ if (!boot_cpu_has (X86_FEATURE_VERW_CLEAR ))
2132+ tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED ;
2133+
2134+ switch (tsa_mitigation ) {
2135+ case TSA_MITIGATION_USER_KERNEL :
2136+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2137+ break ;
2138+
2139+ case TSA_MITIGATION_VM :
2140+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2141+ break ;
2142+
2143+ case TSA_MITIGATION_UCODE_NEEDED :
2144+ if (!boot_cpu_has (X86_FEATURE_HYPERVISOR ))
2145+ goto out ;
2146+
2147+ pr_notice ("Forcing mitigation on in a VM\n" );
2148+
2149+ /*
2150+ * On the off-chance that microcode has been updated
2151+ * on the host, enable the mitigation in the guest just
2152+ * in case.
2153+ */
2154+ fallthrough ;
2155+ case TSA_MITIGATION_FULL :
2156+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2157+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2158+ break ;
2159+ default :
2160+ break ;
2161+ }
2162+
2163+ out :
2164+ pr_info ("%s\n" , tsa_strings [tsa_mitigation ]);
2165+ }
2166+
20772167void cpu_bugs_smt_update (void )
20782168{
20792169 mutex_lock (& spec_ctrl_mutex );
@@ -2130,6 +2220,24 @@ void cpu_bugs_smt_update(void)
21302220 break ;
21312221 }
21322222
2223+ switch (tsa_mitigation ) {
2224+ case TSA_MITIGATION_USER_KERNEL :
2225+ case TSA_MITIGATION_VM :
2226+ case TSA_MITIGATION_FULL :
2227+ case TSA_MITIGATION_UCODE_NEEDED :
2228+ /*
2229+ * TSA-SQ can potentially lead to info leakage between
2230+ * SMT threads.
2231+ */
2232+ if (sched_smt_active ())
2233+ static_branch_enable (& cpu_buf_idle_clear );
2234+ else
2235+ static_branch_disable (& cpu_buf_idle_clear );
2236+ break ;
2237+ case TSA_MITIGATION_NONE :
2238+ break ;
2239+ }
2240+
21332241 mutex_unlock (& spec_ctrl_mutex );
21342242}
21352243
@@ -3078,6 +3186,11 @@ static ssize_t gds_show_state(char *buf)
30783186 return sysfs_emit (buf , "%s\n" , gds_strings [gds_mitigation ]);
30793187}
30803188
3189+ static ssize_t tsa_show_state (char * buf )
3190+ {
3191+ return sysfs_emit (buf , "%s\n" , tsa_strings [tsa_mitigation ]);
3192+ }
3193+
30813194static ssize_t cpu_show_common (struct device * dev , struct device_attribute * attr ,
30823195 char * buf , unsigned int bug )
30833196{
@@ -3139,6 +3252,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
31393252 case X86_BUG_ITS :
31403253 return its_show_state (buf );
31413254
3255+ case X86_BUG_TSA :
3256+ return tsa_show_state (buf );
3257+
31423258 default :
31433259 break ;
31443260 }
@@ -3223,6 +3339,11 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
32233339{
32243340 return cpu_show_common (dev , attr , buf , X86_BUG_ITS );
32253341}
3342+
3343+ ssize_t cpu_show_tsa (struct device * dev , struct device_attribute * attr , char * buf )
3344+ {
3345+ return cpu_show_common (dev , attr , buf , X86_BUG_TSA );
3346+ }
32263347#endif
32273348
32283349void __warn_thunk (void )
0 commit comments