Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/arch/x86 Pull up following revision(s) (requested by ...



details:   https://anonhg.NetBSD.org/src/rev/ac396f8f1c78
branches:  netbsd-8
changeset: 460995:ac396f8f1c78
user:      martin <martin%NetBSD.org@localhost>
date:      Tue Nov 12 18:28:40 2019 +0000

description:
Pull up following revision(s) (requested by maxv in ticket #1433):

        sys/arch/x86/include/specialreg.h: revision 1.157
        sys/arch/x86/x86/spectre.c: revision 1.31

Mitigation for CVE-2019-11135: TSX Asynchronous Abort (TAA).

Two sysctls are added:
        machdep.taa.mitigated = {0/1} user-settable
        machdep.taa.method = {string} constructed by the kernel

There are two cases:

  (1) If the CPU is affected by MDS, then the MDS mitigation will also
mitigate TAA, and we have nothing else to do. We make the 'mitigated' leaf
read-only, and force:

        machdep.taa.mitigated = machdep.mds.mitigated
        machdep.taa.method = [MDS]

The kernel already enables the MDS mitigation by default.

  (2) If the CPU is not affected by MDS but is affected by TAA, then we use
the new TSX_CTRL MSR to disable RTM. This MSR is provided via a microcode
update, now available on the Intel website. The kernel will automatically
enable the TAA mitigation if the updated microcode is present. If the new
microcode is not present, the user can load it via cpuctl, and set
machdep.taa.mitigated=1.

diffstat:

 sys/arch/x86/include/specialreg.h |    7 +-
 sys/arch/x86/x86/spectre.c        |  234 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 228 insertions(+), 13 deletions(-)

diffs (truncated from 313 to 300 lines):

diff -r 8a9da0b069ee -r ac396f8f1c78 sys/arch/x86/include/specialreg.h
--- a/sys/arch/x86/include/specialreg.h Mon Nov 11 17:18:14 2019 +0000
+++ b/sys/arch/x86/include/specialreg.h Tue Nov 12 18:28:40 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: specialreg.h,v 1.98.2.15 2019/08/16 15:36:17 martin Exp $      */
+/*     $NetBSD: specialreg.h,v 1.98.2.16 2019/11/12 18:28:40 martin Exp $      */
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -762,9 +762,14 @@
 #define        IA32_ARCH_SKIP_L1DFL_VMENTRY 0x08
 #define        IA32_ARCH_SSB_NO        0x10
 #define        IA32_ARCH_MDS_NO        0x20
+#define        IA32_ARCH_TSX_CTRL      0x80
+#define        IA32_ARCH_TAA_NO        0x100
 #define MSR_IA32_FLUSH_CMD     0x10b
 #define        IA32_FLUSH_CMD_L1D_FLUSH 0x01
 #define MSR_TSX_FORCE_ABORT    0x10f
+#define MSR_IA32_TSX_CTRL      0x122
+#define        IA32_TSX_CTRL_RTM_DISABLE       __BIT(0)
+#define        IA32_TSX_CTRL_TSX_CPUID_CLEAR   __BIT(1)
 #define MSR_BBL_CR_ADDR                0x116   /* PII+ only */
 #define MSR_BBL_CR_DECC                0x118   /* PII+ only */
 #define MSR_BBL_CR_CTL         0x119   /* PII+ only */
diff -r 8a9da0b069ee -r ac396f8f1c78 sys/arch/x86/x86/spectre.c
--- a/sys/arch/x86/x86/spectre.c        Mon Nov 11 17:18:14 2019 +0000
+++ b/sys/arch/x86/x86/spectre.c        Tue Nov 12 18:28:40 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: spectre.c,v 1.19.2.4 2019/06/02 08:29:30 martin Exp $  */
+/*     $NetBSD: spectre.c,v 1.19.2.5 2019/11/12 18:28:40 martin Exp $  */
 
 /*
  * Copyright (c) 2018 NetBSD Foundation, Inc.
@@ -30,11 +30,11 @@
  */
 
 /*
- * Mitigations for the SpectreV2 and SpectreV4 CPU flaws.
+ * Mitigations for the SpectreV2, SpectreV4, MDS and TAA CPU flaws.
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.19.2.4 2019/06/02 08:29:30 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.19.2.5 2019/11/12 18:28:40 martin Exp $");
 
 #include "opt_spectre.h"
 
@@ -652,14 +652,194 @@
 
 /* -------------------------------------------------------------------------- */
 
+enum taa_mitigation {
+       TAA_MITIGATION_NONE,
+       TAA_MITIGATION_TAA_NO,
+       TAA_MITIGATION_MDS,
+       TAA_MITIGATION_RTM_DISABLE
+};
+
+static char taa_mitigation_name[64] = "(none)";
+
+static enum taa_mitigation taa_mitigation_method = TAA_MITIGATION_NONE;
+static bool taa_mitigation_enabled __read_mostly = false;
+static bool *taa_mitigation_enabled_ptr = &taa_mitigation_enabled;
+
+static void
+mitigation_taa_apply_cpu(struct cpu_info *ci, bool enabled)
+{
+       uint64_t msr;
+
+       switch (taa_mitigation_method) {
+       case TAA_MITIGATION_NONE:
+       case TAA_MITIGATION_TAA_NO:
+       case TAA_MITIGATION_MDS:
+               panic("impossible");
+       case TAA_MITIGATION_RTM_DISABLE:
+               msr = rdmsr(MSR_IA32_TSX_CTRL);
+               if (enabled) {
+                       msr |= IA32_TSX_CTRL_RTM_DISABLE;
+               } else {
+                       msr &= ~IA32_TSX_CTRL_RTM_DISABLE;
+               }
+               wrmsr(MSR_IA32_TSX_CTRL, msr);
+               break;
+       }
+}
+
+static void
+mitigation_taa_change_cpu(void *arg1, void *arg2)
+{
+       struct cpu_info *ci = curcpu();
+       bool enabled = (bool)arg1;
+
+       mitigation_taa_apply_cpu(ci, enabled);
+}
+
+static void
+taa_detect_method(void)
+{
+       u_int descs[4];
+       uint64_t msr;
+
+       taa_mitigation_enabled_ptr = &taa_mitigation_enabled;
+
+       if (cpu_vendor != CPUVENDOR_INTEL) {
+               taa_mitigation_method = TAA_MITIGATION_TAA_NO;
+               return;
+       }
+       if (!(cpu_feature[5] & CPUID_SEF_RTM)) {
+               taa_mitigation_method = TAA_MITIGATION_TAA_NO;
+               return;
+       }
+
+       /*
+        * If the CPU doesn't have MDS_NO set, then the TAA mitigation is based
+        * on the MDS mitigation.
+        */
+       if (cpuid_level < 7) {
+               taa_mitigation_method = TAA_MITIGATION_MDS;
+               taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
+               return;
+       }
+       x86_cpuid(0x7, descs);
+       if (!(descs[3] & CPUID_SEF_ARCH_CAP)) {
+               taa_mitigation_method = TAA_MITIGATION_MDS;
+               taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
+               return;
+       }
+       msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
+       if (!(msr & IA32_ARCH_MDS_NO)) {
+               taa_mitigation_method = TAA_MITIGATION_MDS;
+               taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
+               return;
+       }
+
+       /*
+        * Otherwise, we need the TAA-specific mitigation.
+        */
+       if (msr & IA32_ARCH_TAA_NO) {
+               taa_mitigation_method = TAA_MITIGATION_TAA_NO;
+               return;
+       }
+       if (msr & IA32_ARCH_TSX_CTRL) {
+               taa_mitigation_method = TAA_MITIGATION_RTM_DISABLE;
+               return;
+       }
+}
+
+static void
+taa_set_name(void)
+{
+       char name[64] = "";
+
+       switch (taa_mitigation_method) {
+       case TAA_MITIGATION_NONE:
+               strlcpy(name, "(none)", sizeof(name));
+               break;
+       case TAA_MITIGATION_TAA_NO:
+               strlcpy(name, "[TAA_NO]", sizeof(name));
+               break;
+       case TAA_MITIGATION_MDS:
+               strlcpy(name, "[MDS]", sizeof(name));
+               break;
+       case TAA_MITIGATION_RTM_DISABLE:
+               if (!taa_mitigation_enabled) {
+                       strlcpy(name, "(none)", sizeof(name));
+               } else {
+                       strlcpy(name, "[RTM_DISABLE]", sizeof(name));
+               }
+               break;
+       }
+
+       strlcpy(taa_mitigation_name, name, sizeof(taa_mitigation_name));
+}
+
+static int
+mitigation_taa_change(bool enabled)
+{
+       uint64_t xc;
+
+       taa_detect_method();
+
+       switch (taa_mitigation_method) {
+       case TAA_MITIGATION_NONE:
+               printf("[!] No mitigation available\n");
+               return EOPNOTSUPP;
+       case TAA_MITIGATION_TAA_NO:
+               printf("[+] The CPU is not affected by TAA\n");
+               return 0;
+       case TAA_MITIGATION_MDS:
+               printf("[!] Mitigation based on MDS, use machdep.mds\n");
+               taa_set_name();
+               return EINVAL;
+       case TAA_MITIGATION_RTM_DISABLE:
+               printf("[+] %s TAA Mitigation...",
+                   enabled ? "Enabling" : "Disabling");
+               xc = xc_broadcast(XC_HIGHPRI, mitigation_taa_change_cpu,
+                   (void *)enabled, NULL);
+               xc_wait(xc);
+               printf(" done!\n");
+               taa_mitigation_enabled = enabled;
+               taa_set_name();
+               return 0;
+       default:
+               panic("impossible");
+       }
+}
+
+static int
+sysctl_machdep_taa_mitigated(SYSCTLFN_ARGS)
+{
+       struct sysctlnode node;
+       int error;
+       bool val;
+
+       val = *(bool *)rnode->sysctl_data;
+
+       node = *rnode;
+       node.sysctl_data = &val;
+
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error != 0 || newp == NULL)
+               return error;
+
+       if (val == *taa_mitigation_enabled_ptr)
+               return 0;
+       return mitigation_taa_change(val);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * cpu0 is the one that detects the method and sets the global 'enabled'
+ * variable for each mitigation.
+ */
 void
 cpu_speculation_init(struct cpu_info *ci)
 {
        /*
         * Spectre V2.
-        *
-        * cpu0 is the one that detects the method and sets the global
-        * variable.
         */
 #if 0
        if (ci == &cpu_info_primary) {
@@ -675,9 +855,6 @@
 
        /*
         * Spectre V4.
-        *
-        * cpu0 is the one that detects the method and sets the global
-        * variable.
         */
 #if 0
        if (ci == &cpu_info_primary) {
@@ -693,9 +870,6 @@
 
        /*
         * Microarchitectural Data Sampling.
-        *
-        * cpu0 is the one that detects the method and sets the global
-        * variable.
         */
        if (ci == &cpu_info_primary) {
                mds_detect_method();
@@ -707,6 +881,20 @@
            mds_mitigation_method != MDS_MITIGATION_MDS_NO) {
                mitigation_mds_apply_cpu(ci, true);
        }
+
+       /*
+        * TSX Asynchronous Abort.
+        */
+       if (ci == &cpu_info_primary) {
+               taa_detect_method();
+               taa_mitigation_enabled =
+                   (taa_mitigation_method == TAA_MITIGATION_RTM_DISABLE) ||
+                   (taa_mitigation_method == TAA_MITIGATION_TAA_NO);
+               taa_set_name();
+       }
+       if (taa_mitigation_method == TAA_MITIGATION_RTM_DISABLE) {
+               mitigation_taa_apply_cpu(ci, true);
+       }
 }
 
 void sysctl_speculation_init(struct sysctllog **);
@@ -806,4 +994,26 @@
                       NULL, 0,
                       mds_mitigation_name, 0,
                       CTL_CREATE, CTL_EOL);
+
+       /* TSX Asynchronous Abort */
+       spec_rnode = NULL;
+       sysctl_createv(clog, 0, NULL, &spec_rnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "taa", NULL,
+                      NULL, 0, NULL, 0,
+                      CTL_MACHDEP, CTL_CREATE);
+       sysctl_createv(clog, 0, &spec_rnode, NULL,
+                      CTLFLAG_READWRITE,



Home | Main Index | Thread Index | Old Index