@@ -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/*
@@ -2093,6 +2095,94 @@ static void update_mds_branch_idle(void)
20932095#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"
20942096#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"
20952097
2098+ #undef pr_fmt
2099+ #define pr_fmt (fmt ) "Transient Scheduler Attacks: " fmt
2100+
2101+ enum tsa_mitigations {
2102+ TSA_MITIGATION_NONE ,
2103+ TSA_MITIGATION_UCODE_NEEDED ,
2104+ TSA_MITIGATION_USER_KERNEL ,
2105+ TSA_MITIGATION_VM ,
2106+ TSA_MITIGATION_FULL ,
2107+ };
2108+
2109+ static const char * const tsa_strings [] = {
2110+ [TSA_MITIGATION_NONE ] = "Vulnerable" ,
2111+ [TSA_MITIGATION_UCODE_NEEDED ] = "Vulnerable: Clear CPU buffers attempted, no microcode" ,
2112+ [TSA_MITIGATION_USER_KERNEL ] = "Mitigation: Clear CPU buffers: user/kernel boundary" ,
2113+ [TSA_MITIGATION_VM ] = "Mitigation: Clear CPU buffers: VM" ,
2114+ [TSA_MITIGATION_FULL ] = "Mitigation: Clear CPU buffers" ,
2115+ };
2116+
2117+ static enum tsa_mitigations tsa_mitigation __ro_after_init =
2118+ IS_ENABLED (CONFIG_MITIGATION_TSA ) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE ;
2119+
2120+ static int __init tsa_parse_cmdline (char * str )
2121+ {
2122+ if (!str )
2123+ return - EINVAL ;
2124+
2125+ if (!strcmp (str , "off" ))
2126+ tsa_mitigation = TSA_MITIGATION_NONE ;
2127+ else if (!strcmp (str , "on" ))
2128+ tsa_mitigation = TSA_MITIGATION_FULL ;
2129+ else if (!strcmp (str , "user" ))
2130+ tsa_mitigation = TSA_MITIGATION_USER_KERNEL ;
2131+ else if (!strcmp (str , "vm" ))
2132+ tsa_mitigation = TSA_MITIGATION_VM ;
2133+ else
2134+ pr_err ("Ignoring unknown tsa=%s option.\n" , str );
2135+
2136+ return 0 ;
2137+ }
2138+ early_param ("tsa" , tsa_parse_cmdline );
2139+
2140+ static void __init tsa_select_mitigation (void )
2141+ {
2142+ if (tsa_mitigation == TSA_MITIGATION_NONE )
2143+ return ;
2144+
2145+ if (cpu_mitigations_off () || !boot_cpu_has_bug (X86_BUG_TSA )) {
2146+ tsa_mitigation = TSA_MITIGATION_NONE ;
2147+ return ;
2148+ }
2149+
2150+ if (!boot_cpu_has (X86_FEATURE_VERW_CLEAR ))
2151+ tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED ;
2152+
2153+ switch (tsa_mitigation ) {
2154+ case TSA_MITIGATION_USER_KERNEL :
2155+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2156+ break ;
2157+
2158+ case TSA_MITIGATION_VM :
2159+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2160+ break ;
2161+
2162+ case TSA_MITIGATION_UCODE_NEEDED :
2163+ if (!boot_cpu_has (X86_FEATURE_HYPERVISOR ))
2164+ goto out ;
2165+
2166+ pr_notice ("Forcing mitigation on in a VM\n" );
2167+
2168+ /*
2169+ * On the off-chance that microcode has been updated
2170+ * on the host, enable the mitigation in the guest just
2171+ * in case.
2172+ */
2173+ fallthrough ;
2174+ case TSA_MITIGATION_FULL :
2175+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF );
2176+ setup_force_cpu_cap (X86_FEATURE_CLEAR_CPU_BUF_VM );
2177+ break ;
2178+ default :
2179+ break ;
2180+ }
2181+
2182+ out :
2183+ pr_info ("%s\n" , tsa_strings [tsa_mitigation ]);
2184+ }
2185+
20962186void cpu_bugs_smt_update (void )
20972187{
20982188 mutex_lock (& spec_ctrl_mutex );
@@ -2146,6 +2236,24 @@ void cpu_bugs_smt_update(void)
21462236 break ;
21472237 }
21482238
2239+ switch (tsa_mitigation ) {
2240+ case TSA_MITIGATION_USER_KERNEL :
2241+ case TSA_MITIGATION_VM :
2242+ case TSA_MITIGATION_FULL :
2243+ case TSA_MITIGATION_UCODE_NEEDED :
2244+ /*
2245+ * TSA-SQ can potentially lead to info leakage between
2246+ * SMT threads.
2247+ */
2248+ if (sched_smt_active ())
2249+ static_branch_enable (& cpu_buf_idle_clear );
2250+ else
2251+ static_branch_disable (& cpu_buf_idle_clear );
2252+ break ;
2253+ case TSA_MITIGATION_NONE :
2254+ break ;
2255+ }
2256+
21492257 mutex_unlock (& spec_ctrl_mutex );
21502258}
21512259
@@ -3075,6 +3183,11 @@ static ssize_t gds_show_state(char *buf)
30753183 return sysfs_emit (buf , "%s\n" , gds_strings [gds_mitigation ]);
30763184}
30773185
3186+ static ssize_t tsa_show_state (char * buf )
3187+ {
3188+ return sysfs_emit (buf , "%s\n" , tsa_strings [tsa_mitigation ]);
3189+ }
3190+
30783191static ssize_t cpu_show_common (struct device * dev , struct device_attribute * attr ,
30793192 char * buf , unsigned int bug )
30803193{
@@ -3136,6 +3249,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
31363249 case X86_BUG_ITS :
31373250 return its_show_state (buf );
31383251
3252+ case X86_BUG_TSA :
3253+ return tsa_show_state (buf );
3254+
31393255 default :
31403256 break ;
31413257 }
@@ -3220,4 +3336,9 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
32203336{
32213337 return cpu_show_common (dev , attr , buf , X86_BUG_ITS );
32223338}
3339+
3340+ ssize_t cpu_show_tsa (struct device * dev , struct device_attribute * attr , char * buf )
3341+ {
3342+ return cpu_show_common (dev , attr , buf , X86_BUG_TSA );
3343+ }
32233344#endif
0 commit comments