Skip to content

Commit c11f83e

Browse files
committed
KVM: vmx: implement MSR_IA32_TSX_CTRL disable RTM functionality
The current guest mitigation of TAA is both too heavy and not really sufficient. It is too heavy because it will cause some affected CPUs (those that have MDS_NO but lack TAA_NO) to fall back to VERW and get the corresponding slowdown. It is not really sufficient because it will cause the MDS_NO bit to disappear upon microcode update, so that VMs started before the microcode update will not be runnable anymore afterwards, even with tsx=on. Instead, if tsx=on on the host, we can emulate MSR_IA32_TSX_CTRL for the guest and let it run without the VERW mitigation. Even though MSR_IA32_TSX_CTRL is quite heavyweight, and we do not want to write it on every vmentry, we can use the shared MSR functionality because the host kernel need not protect itself from TSX-based side-channels. Tested-by: Jim Mattson <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent edef5c3 commit c11f83e

File tree

2 files changed

+40
-21
lines changed

2 files changed

+40
-21
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ const u32 vmx_msr_index[] = {
450450
MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
451451
#endif
452452
MSR_EFER, MSR_TSC_AUX, MSR_STAR,
453+
MSR_IA32_TSX_CTRL,
453454
};
454455

455456
#if IS_ENABLED(CONFIG_HYPERV)
@@ -1683,6 +1684,9 @@ static void setup_msrs(struct vcpu_vmx *vmx)
16831684
index = __find_msr_index(vmx, MSR_TSC_AUX);
16841685
if (index >= 0 && guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDTSCP))
16851686
move_msr_up(vmx, index, save_nmsrs++);
1687+
index = __find_msr_index(vmx, MSR_IA32_TSX_CTRL);
1688+
if (index >= 0)
1689+
move_msr_up(vmx, index, save_nmsrs++);
16861690

16871691
vmx->save_nmsrs = save_nmsrs;
16881692
vmx->guest_msrs_ready = false;
@@ -1782,6 +1786,11 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
17821786
#endif
17831787
case MSR_EFER:
17841788
return kvm_get_msr_common(vcpu, msr_info);
1789+
case MSR_IA32_TSX_CTRL:
1790+
if (!msr_info->host_initiated &&
1791+
!(vcpu->arch.arch_capabilities & ARCH_CAP_TSX_CTRL_MSR))
1792+
return 1;
1793+
goto find_shared_msr;
17851794
case MSR_IA32_UMWAIT_CONTROL:
17861795
if (!msr_info->host_initiated && !vmx_has_waitpkg(vmx))
17871796
return 1;
@@ -1884,8 +1893,9 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
18841893
if (!msr_info->host_initiated &&
18851894
!guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
18861895
return 1;
1887-
/* Else, falls through */
1896+
goto find_shared_msr;
18881897
default:
1898+
find_shared_msr:
18891899
msr = find_msr_entry(vmx, msr_info->index);
18901900
if (msr) {
18911901
msr_info->data = msr->data;
@@ -2001,6 +2011,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
20012011
MSR_IA32_SPEC_CTRL,
20022012
MSR_TYPE_RW);
20032013
break;
2014+
case MSR_IA32_TSX_CTRL:
2015+
if (!msr_info->host_initiated &&
2016+
!(vcpu->arch.arch_capabilities & ARCH_CAP_TSX_CTRL_MSR))
2017+
return 1;
2018+
if (data & ~(TSX_CTRL_RTM_DISABLE | TSX_CTRL_CPUID_CLEAR))
2019+
return 1;
2020+
goto find_shared_msr;
20042021
case MSR_IA32_PRED_CMD:
20052022
if (!msr_info->host_initiated &&
20062023
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
@@ -2152,8 +2169,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
21522169
/* Check reserved bit, higher 32 bits should be zero */
21532170
if ((data >> 32) != 0)
21542171
return 1;
2155-
/* Else, falls through */
2172+
goto find_shared_msr;
2173+
21562174
default:
2175+
find_shared_msr:
21572176
msr = find_msr_entry(vmx, msr_index);
21582177
if (msr) {
21592178
u64 old_msr_data = msr->data;
@@ -4234,7 +4253,20 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
42344253
continue;
42354254
vmx->guest_msrs[j].index = i;
42364255
vmx->guest_msrs[j].data = 0;
4237-
vmx->guest_msrs[j].mask = -1ull;
4256+
4257+
switch (index) {
4258+
case MSR_IA32_TSX_CTRL:
4259+
/*
4260+
* No need to pass TSX_CTRL_CPUID_CLEAR through, so
4261+
* let's avoid changing CPUID bits under the host
4262+
* kernel's feet.
4263+
*/
4264+
vmx->guest_msrs[j].mask = ~(u64)TSX_CTRL_CPUID_CLEAR;
4265+
break;
4266+
default:
4267+
vmx->guest_msrs[j].mask = -1ull;
4268+
break;
4269+
}
42384270
++vmx->nmsrs;
42394271
}
42404272

arch/x86/kvm/x86.c

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,29 +1314,16 @@ static u64 kvm_get_arch_capabilities(void)
13141314
data |= ARCH_CAP_MDS_NO;
13151315

13161316
/*
1317-
* On TAA affected systems, export MDS_NO=0 when:
1318-
* - TSX is enabled on the host, i.e. X86_FEATURE_RTM=1.
1319-
* - Updated microcode is present. This is detected by
1320-
* the presence of ARCH_CAP_TSX_CTRL_MSR and ensures
1321-
* that VERW clears CPU buffers.
1322-
*
1323-
* When MDS_NO=0 is exported, guests deploy clear CPU buffer
1324-
* mitigation and don't complain:
1325-
*
1326-
* "Vulnerable: Clear CPU buffers attempted, no microcode"
1327-
*
1328-
* If TSX is disabled on the system, guests are also mitigated against
1329-
* TAA and clear CPU buffer mitigation is not required for guests.
1317+
* On TAA affected systems:
1318+
* - nothing to do if TSX is disabled on the host.
1319+
* - we emulate TSX_CTRL if present on the host.
1320+
* This lets the guest use VERW to clear CPU buffers.
13301321
*/
13311322
if (!boot_cpu_has(X86_FEATURE_RTM))
1332-
data &= ~ARCH_CAP_TAA_NO;
1323+
data &= ~(ARCH_CAP_TAA_NO | ARCH_CAP_TSX_CTRL_MSR);
13331324
else if (!boot_cpu_has_bug(X86_BUG_TAA))
13341325
data |= ARCH_CAP_TAA_NO;
1335-
else if (data & ARCH_CAP_TSX_CTRL_MSR)
1336-
data &= ~ARCH_CAP_MDS_NO;
13371326

1338-
/* KVM does not emulate MSR_IA32_TSX_CTRL. */
1339-
data &= ~ARCH_CAP_TSX_CTRL_MSR;
13401327
return data;
13411328
}
13421329
EXPORT_SYMBOL_GPL(kvm_get_arch_capabilities);

0 commit comments

Comments
 (0)