Page MenuHomeFreeBSD

D22374.id64384.diff
No OneTemporary

D22374.id64384.diff

Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -1779,6 +1779,7 @@
TUNABLE_INT_FETCH("machdep.syscall_ret_l1d_flush",
&syscall_ret_l1d_flush_mode);
TUNABLE_INT_FETCH("hw.mds_disable", &hw_mds_disable);
+ TUNABLE_INT_FETCH("hw.tsx_disable", &hw_tsx_disable);
finishidentcpu(); /* Final stage of CPU initialization */
initializecpu(); /* Initialize CPU registers */
Index: sys/dev/cpuctl/cpuctl.c
===================================================================
--- sys/dev/cpuctl/cpuctl.c
+++ sys/dev/cpuctl/cpuctl.c
@@ -546,6 +546,7 @@
pmap_allow_2m_x_ept_recalculate();
#endif
hw_mds_recalculate();
+ hw_tsx_recalculate();
printcpuinfo();
return (0);
}
Index: sys/x86/include/x86_var.h
===================================================================
--- sys/x86/include/x86_var.h
+++ sys/x86/include/x86_var.h
@@ -93,6 +93,7 @@
extern int hw_ibrs_active;
extern int hw_mds_disable;
extern int hw_ssb_active;
+extern int hw_tsx_disable;
struct pcb;
struct thread;
@@ -136,6 +137,7 @@
void hw_ibrs_recalculate(void);
void hw_mds_recalculate(void);
void hw_ssb_recalculate(bool all_cpus);
+void hw_tsx_recalculate(void);
void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame);
void nmi_call_kdb_smp(u_int type, struct trapframe *frame);
void nmi_handle_intr(u_int type, struct trapframe *frame);
Index: sys/x86/x86/cpu_machdep.c
===================================================================
--- sys/x86/x86/cpu_machdep.c
+++ sys/x86/x86/cpu_machdep.c
@@ -1135,6 +1135,170 @@
"Microarchitectural Data Sampling Mitigation "
"(0 - off, 1 - on VERW, 2 - on SW, 3 - on AUTO");
+int hw_tsx_disable;
+int hw_tsx_state;
+enum {
+ TSX_TAA_NONE = 0,
+ TSX_TAA_DISABLE = 1,
+ TSX_TAA_VERW = 2,
+ TSX_TAA_AUTO = 3
+};
+
+static void
+hw_tsx_set_one(bool enable)
+{
+ uint64_t v;
+
+ v = rdmsr(MSR_IA32_TSX_CTRL);
+ if (enable)
+ v |= (uint64_t)(IA32_TSX_CTRL_RTM_DISABLE |
+ IA32_TSX_CTRL_TSX_CPUID_CLEAR);
+ else
+ v &= ~(uint64_t)(IA32_TSX_CTRL_RTM_DISABLE |
+ IA32_TSX_CTRL_TSX_CPUID_CLEAR);
+
+ wrmsr(MSR_IA32_TSX_CTRL, v);
+}
+
+static void
+hw_tsx_set(bool enable, bool all)
+{
+ struct thread *td;
+ int bound_cpu, i, is_bound;
+
+ if (all) {
+ td = curthread;
+ thread_lock(td);
+ is_bound = sched_is_bound(td);
+ bound_cpu = td->td_oncpu;
+ CPU_FOREACH(i) {
+ sched_bind(td, i);
+ hw_tsx_set_one(enable);
+ }
+ if (is_bound)
+ sched_bind(td, bound_cpu);
+ else
+ sched_unbind(td);
+ thread_unlock(td);
+ } else
+ hw_tsx_set_one(enable);
+
+}
+
+void
+hw_tsx_recalculate(void)
+{
+ int tsx_need = 0, tsx_state = 0;
+
+ /* Check CPUID.07h.EBX.HLE and RTM for the presence of TSX */
+ if ((cpu_stdext_feature & CPUID_STDEXT_HLE) == 0 ||
+ (cpu_stdext_feature & CPUID_STDEXT_RTM) == 0) {
+ /* TSX is not present */
+ hw_tsx_state = 0;
+ return;
+ }
+
+ /* Check to see what mitigation options the CPU gives us */
+ if (cpu_ia32_arch_caps & IA32_ARCH_CAP_TAA_NO)
+ tsx_need = TSX_TAA_NONE;
+ else if (cpu_ia32_arch_caps & IA32_ARCH_CAP_TSX_CTRL)
+ tsx_need = TSX_TAA_DISABLE;
+ else {
+ /* No TSX specific remedies are available. */
+ if (hw_tsx_disable == TSX_TAA_DISABLE)
+ /* The user asked for the disable option, but
+ * it's not available. */
+ return;
+ else
+ tsx_need = TSX_TAA_VERW;
+ }
+
+ /* Can we automatically take action, or are we being forced? */
+ if (hw_tsx_disable == TSX_TAA_AUTO)
+ tsx_state = tsx_need;
+ else
+ tsx_state = hw_tsx_disable;
+
+ /* No state change, nothing to do */
+ if (tsx_state == hw_tsx_state)
+ return;
+
+ /* Does the MSR need to be turned on or off? */
+ if (tsx_state == TSX_TAA_DISABLE)
+ hw_tsx_set(1 /* enable */, 1 /* all */);
+ else if (hw_tsx_state == TSX_TAA_DISABLE)
+ hw_tsx_set(0 /* disable */, 1 /* all */);
+
+ /* Does MDS need to be set to turn on VERW? */
+ if (tsx_state == TSX_TAA_VERW) {
+ hw_mds_disable = 1;
+ hw_mds_recalculate();
+ } else if (hw_tsx_state == TSX_TAA_VERW) {
+ hw_mds_disable = 0;
+ hw_mds_recalculate();
+ }
+
+ hw_tsx_state = tsx_state;
+ return;
+}
+
+static void
+hw_tsx_recalculate_boot(void * arg __unused)
+{
+
+ hw_tsx_recalculate();
+}
+SYSINIT(tsx_recalc, SI_SUB_SMP, SI_ORDER_ANY, hw_tsx_recalculate_boot, NULL);
+
+static int
+sysctl_tsx_disable_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = hw_tsx_disable;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (val < 0 || val > 3)
+ return (EINVAL);
+ hw_tsx_disable = val;
+ hw_tsx_recalculate();
+ return (0);
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, tsx_disable, CTLTYPE_INT |
+ CTLFLAG_RWTUN | CTLFLAG_NOFETCH | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_tsx_disable_handler, "I",
+ "TSX Asynchronous Abort Mitigation "
+ "(0 - off, 1 - disable TSX, 2 - MDS/VERW, 3 - on AUTO");
+
+static int
+sysctl_hw_tsx_disable_state_handler(SYSCTL_HANDLER_ARGS)
+{
+ const char *state;
+
+ switch (hw_tsx_state) {
+ case TSX_TAA_NONE:
+ state = "inactive";
+ break;
+ case TSX_TAA_DISABLE:
+ state = "TSX disabled";
+ break;
+ case TSX_TAA_VERW:
+ state = "MDS/VERW";
+ break;
+ default:
+ state = "unknown";
+ }
+
+ return (SYSCTL_OUT(req, state, strlen(state)));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, tsx_disable_state,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_hw_tsx_disable_state_handler, "A",
+ "Transactional Memory Asynchronous Abort Mitigation state");
+
/*
* Enable and restore kernel text write permissions.
* Callers must ensure that disable_wp()/restore_wp() are executed

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 21, 9:47 AM (17 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27111048
Default Alt Text
D22374.id64384.diff (5 KB)

Event Timeline