@@ -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 ;
@@ -185,6 +186,7 @@ void __init cpu_select_mitigations(void)
185186 srso_select_mitigation ();
186187 gds_select_mitigation ();
187188 its_select_mitigation ();
189+ tsa_select_mitigation ();
188190}
189191
190192/*
@@ -2103,6 +2105,94 @@ static void update_mds_branch_idle(void)
21032105#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"
21042106#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"
21052107
2108+ #undef pr_fmt
2109+ #define pr_fmt (fmt ) "Transient Scheduler Attacks: " fmt
2110+
2111+ enum tsa_mitigations {
2112+ TSA_MITIGATION_NONE ,
2113+ TSA_MITIGATION_UCODE_NEEDED ,
2114+ TSA_MITIGATION_USER_KERNEL ,
2115+ TSA_MITIGATION_VM ,
2116+ TSA_MITIGATION_FULL ,
2117+ };
2118+
2119+ static const char * const tsa_strings [] = {
2120+ [TSA_MITIGATION_NONE ] = "Vulnerable" ,
2121+ [TSA_MITIGATION_UCODE_NEEDED ] = "Vulnerable: Clear CPU buffers attempted, no microcode" ,
2122+ [TSA_MITIGATION_USER_KERNEL ] = "Mitigation: Clear CPU buffers: user/kernel boundary" ,
2123+ [TSA_MITIGATION_VM ] = "Mitigation: Clear CPU buffers: VM" ,
2124+ [TSA_MITIGATION_FULL ] = "Mitigation: Clear CPU buffers" ,
2125+ };
2126+
2127+ static enum tsa_mitigations tsa_mitigation __ro_after_init =
2128+ IS_ENABLED (CONFIG_MITIGATION_TSA ) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE ;
2129+
2130+ static int __init tsa_parse_cmdline (char * str )
2131+ {
2132+ if (!str )
2133+ return - EINVAL ;
2134+
2135+ if (!strcmp (str , "off" ))
2136+ tsa_mitigation = TSA_MITIGATION_NONE ;
2137+ else if (!strcmp (str , "on" ))
2138+ tsa_mitigation = TSA_MITIGATION_FULL ;
2139+ else if (!strcmp (str , "user" ))
2140+ tsa_mitigation = TSA_MITIGATION_USER_KERNEL ;
2141+ else if (!strcmp (str , "vm" ))
2142+ tsa_mitigation = TSA_MITIGATION_VM ;
2143+ else
2144+ pr_err ("Ignoring unknown tsa=%s option.\n" , str );
2145+
2146+ return 0 ;
2147+ }
2148+ early_param ("tsa" , tsa_parse_cmdline );
2149+
2150+ static void __init tsa_select_mitigation (void )
2151+ {
2152+ if (tsa_mitigation == TSA_MITIGATION_NONE )
2153+ return ;
2154+
2155+ if (cpu_mitigations_off () || !boot_cpu_has_bug (X86_BUG_TSA )) {
2156+ tsa_mitigation = TSA_MITIGATION_NONE ;
2157+ return ;
2158+ }
2159+
2160+ if (!boot_cpu_has (X86_FEATURE_VERW_CLEAR ))
2161+ tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED ;
2162+
2163+ switch (tsa_mitigation ) {
2164+ case TSA_MITIGATION_USER_KERNEL :
2165+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2166+ break ;
2167+
2168+ case TSA_MITIGATION_VM :
2169+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2170+ break ;
2171+
2172+ case TSA_MITIGATION_UCODE_NEEDED :
2173+ if (!boot_cpu_has (X86_FEATURE_HYPERVISOR ))
2174+ goto out ;
2175+
2176+ pr_notice ("Forcing mitigation on in a VM\n" );
2177+
2178+ /*
2179+ * On the off-chance that microcode has been updated
2180+ * on the host, enable the mitigation in the guest just
2181+ * in case.
2182+ */
2183+ fallthrough ;
2184+ case TSA_MITIGATION_FULL :
2185+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2186+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2187+ break ;
2188+ default :
2189+ break ;
2190+ }
2191+
2192+ out :
2193+ pr_info ("%s\n" , tsa_strings [tsa_mitigation ]);
2194+ }
2195+
21062196void cpu_bugs_smt_update (void )
21072197{
21082198 mutex_lock (& spec_ctrl_mutex );
@@ -2156,6 +2246,24 @@ void cpu_bugs_smt_update(void)
21562246 break ;
21572247 }
21582248
2249+ switch (tsa_mitigation ) {
2250+ case TSA_MITIGATION_USER_KERNEL :
2251+ case TSA_MITIGATION_VM :
2252+ case TSA_MITIGATION_FULL :
2253+ case TSA_MITIGATION_UCODE_NEEDED :
2254+ /*
2255+ * TSA-SQ can potentially lead to info leakage between
2256+ * SMT threads.
2257+ */
2258+ if (sched_smt_active ())
2259+ static_branch_enable (& cpu_buf_idle_clear );
2260+ else
2261+ static_branch_disable (& cpu_buf_idle_clear );
2262+ break ;
2263+ case TSA_MITIGATION_NONE :
2264+ break ;
2265+ }
2266+
21592267 mutex_unlock (& spec_ctrl_mutex );
21602268}
21612269
@@ -3084,6 +3192,11 @@ static ssize_t gds_show_state(char *buf)
30843192 return sysfs_emit (buf , "%s\n" , gds_strings [gds_mitigation ]);
30853193}
30863194
3195+ static ssize_t tsa_show_state (char * buf )
3196+ {
3197+ return sysfs_emit (buf , "%s\n" , tsa_strings [tsa_mitigation ]);
3198+ }
3199+
30873200static ssize_t cpu_show_common (struct device * dev , struct device_attribute * attr ,
30883201 char * buf , unsigned int bug )
30893202{
@@ -3145,6 +3258,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
31453258 case X86_BUG_ITS :
31463259 return its_show_state (buf );
31473260
3261+ case X86_BUG_TSA :
3262+ return tsa_show_state (buf );
3263+
31483264 default :
31493265 break ;
31503266 }
@@ -3229,6 +3345,11 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
32293345{
32303346 return cpu_show_common (dev , attr , buf , X86_BUG_ITS );
32313347}
3348+
3349+ ssize_t cpu_show_tsa (struct device * dev , struct device_attribute * attr , char * buf )
3350+ {
3351+ return cpu_show_common (dev , attr , buf , X86_BUG_TSA );
3352+ }
32323353#endif
32333354
32343355void __warn_thunk (void )
0 commit comments