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

[xen staging] x86/tsx: Expose RTM_ALWAYS_ABORT to guests



commit c94e2105924347de0d9f32065370e802a20cc829
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Sat Apr 6 20:36:54 2024 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Apr 9 16:37:30 2024 +0100

    x86/tsx: Expose RTM_ALWAYS_ABORT to guests
    
    A TSX Abort is one option mitigate Native-BHI, but a guest kernel doesn't 
get
    to see this if Xen has turned RTM off using MSR_TSX_{CTRL,FORCE_ABORT}.
    
    Therefore, the meaning of RTM_ALWAYS_ABORT has been adjusted to "XBEGIN 
won't
    fault", and it should be exposed to guests so they can make a better 
decision.
    
    Expose it in the max policy for any RTM-capable system.  Offer it by default
    only if RTM has been disabled.
    
    Update test-tsx to account for this new meaning.  While adjusting the logic 
in
    test_guest_policies(), take the opportunity to use feature names (now 
they're
    available) to make the logic easier to follow.
    
    This is part of XSA-456 / CVE-2024-2201.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 tools/tests/tsx/test-tsx.c                  | 39 +++++++++++++++++++----------
 xen/arch/x86/cpu-policy.c                   | 20 +++++++++++++++
 xen/include/public/arch-x86/cpufeatureset.h |  2 +-
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/tools/tests/tsx/test-tsx.c b/tools/tests/tsx/test-tsx.c
index b7e1972ce8..5af04953f3 100644
--- a/tools/tests/tsx/test-tsx.c
+++ b/tools/tests/tsx/test-tsx.c
@@ -311,25 +311,25 @@ static void test_guest_policies(const struct cpu_policy 
*max,
     dump_tsx_details(max, "Max:");
     dump_tsx_details(def, "Def:");
 
-    if ( ((max->feat.raw[0].d | def->feat.raw[0].d) &
-          (bitmaskof(X86_FEATURE_TSX_FORCE_ABORT) |
-           bitmaskof(X86_FEATURE_RTM_ALWAYS_ABORT) |
-           bitmaskof(X86_FEATURE_SRBDS_CTRL))) ||
-         ((max->arch_caps.raw | def->arch_caps.raw) & ARCH_CAPS_TSX_CTRL) )
+    if ( max->feat.tsx_force_abort || def->feat.tsx_force_abort ||
+         max->feat.srbds_ctrl      || def->feat.srbds_ctrl ||
+         max->arch_caps.tsx_ctrl   || def->arch_caps.tsx_ctrl )
         fail("  Xen-only TSX controls offered to guest\n");
 
     switch ( rtm_behaviour )
     {
     case RTM_UD:
-        if ( (max->feat.raw[0].b | def->feat.raw[0].b) &
-             (bitmaskof(X86_FEATURE_HLE) | bitmaskof(X86_FEATURE_RTM)) )
-             fail("  HLE/RTM offered to guests despite not being available\n");
+        if ( max->feat.hle              || def->feat.hle ||
+             max->feat.rtm              || def->feat.rtm ||
+             max->feat.rtm_always_abort || def->feat.rtm_always_abort )
+            fail("  HLE/RTM/RTM_AA offered to guests despite not being 
available\n");
         break;
 
     case RTM_ABORT:
-        if ( def->feat.raw[0].b &
-             (bitmaskof(X86_FEATURE_HLE) | bitmaskof(X86_FEATURE_RTM)) )
+        if ( def->feat.hle || def->feat.rtm )
              fail("  HLE/RTM offered to guests by default despite not being 
usable\n");
+        if ( !def->feat.rtm_always_abort )
+             fail("  RTM_AA not offered to guests by default despite being 
available\n");
         break;
 
     case RTM_OK:
@@ -340,6 +340,9 @@ static void test_guest_policies(const struct cpu_policy 
*max,
 
     if ( def->feat.hle )
         fail("  Fail: HLE offered in default policy\n");
+
+    if ( def->feat.rtm && def->feat.rtm_always_abort )
+        fail("  Fail: Both RTM and RTM_AA offered in default policy\n");
 }
 
 static void test_def_max_policies(void)
@@ -388,14 +391,13 @@ static void test_guest(struct xen_domctl_createdomain *c)
 
     if ( guest_policy.policy.feat.hle ||
          guest_policy.policy.feat.tsx_force_abort ||
-         guest_policy.policy.feat.rtm_always_abort ||
          guest_policy.policy.feat.srbds_ctrl ||
          guest_policy.policy.arch_caps.tsx_ctrl )
         fail("  Unexpected features advertised\n");
 
     if ( host.policy.feat.rtm )
     {
-        unsigned int _7b0;
+        unsigned int _7b0, _7d0;
 
         /*
          * If host RTM is available, all combinations of guest flags should be
@@ -403,6 +405,8 @@ static void test_guest(struct xen_domctl_createdomain *c)
          */
         _7b0 = (guest_policy.policy.feat.raw[0].b ^=
                 (bitmaskof(X86_FEATURE_HLE) | bitmaskof(X86_FEATURE_RTM)));
+        _7d0 = (guest_policy.policy.feat.raw[0].d ^=
+                bitmaskof(X86_FEATURE_RTM_ALWAYS_ABORT));
 
         /* Set the new policy. */
         rc = xc_cpu_policy_set_domain(xch, domid, &guest_policy);
@@ -426,10 +430,17 @@ static void test_guest(struct xen_domctl_createdomain *c)
 
         if ( guest_policy.policy.feat.raw[0].b != _7b0 )
         {
-            fail("  Expected CPUID.7[1].b 0x%08x differs from actual 0x%08x\n",
+            fail("  Expected CPUID.7[0].b 0x%08x differs from actual 0x%08x\n",
                  _7b0, guest_policy.policy.feat.raw[0].b);
             goto out;
         }
+
+        if ( guest_policy.policy.feat.raw[0].d != _7d0 )
+        {
+            fail("  Expected CPUID.7[0].d 0x%08x differs from actual 0x%08x\n",
+                 _7d0, guest_policy.policy.feat.raw[0].d);
+            goto out;
+        }
     }
 
  out:
@@ -514,6 +525,8 @@ static void test_tsx(void)
                         i, errno, strerror(errno));
     }
 
+    dump_tsx_details(&host.policy, "Host:");
+
     rc = xc_physinfo(xch, &physinfo);
     if ( rc )
         return fail("Failed to obtain physinfo: %d - %s\n",
diff --git a/xen/arch/x86/cpu-policy.c b/xen/arch/x86/cpu-policy.c
index 5952ff20e6..4b6d962763 100644
--- a/xen/arch/x86/cpu-policy.c
+++ b/xen/arch/x86/cpu-policy.c
@@ -462,6 +462,21 @@ static void __init 
guest_common_max_feature_adjustments(uint32_t *fs)
      */
     __set_bit(X86_FEATURE_HTT, fs);
     __set_bit(X86_FEATURE_CMP_LEGACY, fs);
+
+    /*
+     * To mitigate Native-BHI, one option is to use a TSX Abort on capable
+     * systems.  This is safe even if RTM has been disabled for other reasons
+     * via MSR_TSX_{CTRL,FORCE_ABORT}.  However, a guest kernel doesn't get to
+     * know this type of information.
+     *
+     * Therefore the meaning of RTM_ALWAYS_ABORT has been adjusted, to instead
+     * mean "XBEGIN won't fault".  This is enough for a guest kernel to make
+     * an informed choice WRT mitigating Native-BHI.
+     *
+     * If RTM-capable, we can run a VM which has seen RTM_ALWAYS_ABORT.
+     */
+    if ( test_bit(X86_FEATURE_RTM, fs) )
+        __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs);
 }
 
 static void __init guest_common_default_feature_adjustments(uint32_t *fs)
@@ -534,9 +549,14 @@ static void __init 
guest_common_default_feature_adjustments(uint32_t *fs)
      * function as expected, but is technically compatible with the ISA.
      *
      * Do not advertise RTM to guests by default if it won't actually work.
+     * Instead, advertise RTM_ALWAYS_ABORT indicating that TSX Aborts are safe
+     * to use, e.g. for mitigating Native-BHI.
      */
     if ( rtm_disabled )
+    {
         __clear_bit(X86_FEATURE_RTM, fs);
+        __set_bit(X86_FEATURE_RTM_ALWAYS_ABORT, fs);
+    }
 }
 
 static void __init guest_common_feature_adjustments(uint32_t *fs)
diff --git a/xen/include/public/arch-x86/cpufeatureset.h 
b/xen/include/public/arch-x86/cpufeatureset.h
index 6bb1ee3b0a..53f13dec31 100644
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -264,7 +264,7 @@ XEN_CPUFEATURE(FSRM,          9*32+ 4) /*A  Fast Short REP 
MOVS */
 XEN_CPUFEATURE(AVX512_VP2INTERSECT, 9*32+8) /*a  VP2INTERSECT{D,Q} insns */
 XEN_CPUFEATURE(SRBDS_CTRL,    9*32+ 9) /*   MSR_MCU_OPT_CTRL and 
RNGDS_MITG_DIS. */
 XEN_CPUFEATURE(MD_CLEAR,      9*32+10) /*!A VERW clears microarchitectural 
buffers */
-XEN_CPUFEATURE(RTM_ALWAYS_ABORT, 9*32+11) /*! June 2021 TSX defeaturing in 
microcode. */
+XEN_CPUFEATURE(RTM_ALWAYS_ABORT, 9*32+11) /*! RTM disabled (but XBEGIN wont 
fault) */
 XEN_CPUFEATURE(TSX_FORCE_ABORT, 9*32+13) /* MSR_TSX_FORCE_ABORT.RTM_ABORT */
 XEN_CPUFEATURE(SERIALIZE,     9*32+14) /*A  SERIALIZE insn */
 XEN_CPUFEATURE(HYBRID,        9*32+15) /*   Heterogeneous platform */
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.