mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit c94e210592)
This commit is contained in:
1 parent
801e251556
commit
02a424a7a8
3 files changed
+47
-14
No files matched your search
+26
-13
@@ -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",
|
||||
|
||||
@@ -468,6 +468,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)
|
||||
@@ -540,9 +555,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)
|
||||
|
||||
@@ -261,7 +261,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 */
|
||||
|
||||