Skip to content

Commit 027bbb8

Browse files
pa1guptasuryasaimadhu
authored andcommitted
KVM: x86/speculation: Disable Fill buffer clear within guests
The enumeration of MD_CLEAR in CPUID(EAX=7,ECX=0).EDX{bit 10} is not an accurate indicator on all CPUs of whether the VERW instruction will overwrite fill buffers. FB_CLEAR enumeration in IA32_ARCH_CAPABILITIES{bit 17} covers the case of CPUs that are not vulnerable to MDS/TAA, indicating that microcode does overwrite fill buffers. Guests running in VMM environments may not be aware of all the capabilities/vulnerabilities of the host CPU. Specifically, a guest may apply MDS/TAA mitigations when a virtual CPU is enumerated as vulnerable to MDS/TAA even when the physical CPU is not. On CPUs that enumerate FB_CLEAR_CTRL the VMM may set FB_CLEAR_DIS to skip overwriting of fill buffers by the VERW instruction. This is done by setting FB_CLEAR_DIS during VMENTER and resetting on VMEXIT. For guests that enumerate FB_CLEAR (explicitly asking for fill buffer clear capability) the VMM will not use FB_CLEAR_DIS. Irrespective of guest state, host overwrites CPU buffers before VMENTER to protect itself from an MMIO capable guest, as part of mitigation for MMIO Stale Data vulnerabilities. Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Borislav Petkov <[email protected]>
1 parent a992b8a commit 027bbb8

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed

arch/x86/include/asm/msr-index.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@
133133
* VERW clears CPU fill buffer
134134
* even on MDS_NO CPUs.
135135
*/
136+
#define ARCH_CAP_FB_CLEAR_CTRL BIT(18) /*
137+
* MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]
138+
* bit available to control VERW
139+
* behavior.
140+
*/
136141

137142
#define MSR_IA32_FLUSH_CMD 0x0000010b
138143
#define L1D_FLUSH BIT(0) /*
@@ -150,6 +155,7 @@
150155
#define MSR_IA32_MCU_OPT_CTRL 0x00000123
151156
#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
152157
#define RTM_ALLOW BIT(1) /* TSX development mode */
158+
#define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */
153159

154160
#define MSR_IA32_SYSENTER_CS 0x00000174
155161
#define MSR_IA32_SYSENTER_ESP 0x00000175

arch/x86/kvm/vmx/vmx.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ static const struct {
229229
#define L1D_CACHE_ORDER 4
230230
static void *vmx_l1d_flush_pages;
231231

232+
/* Control for disabling CPU Fill buffer clear */
233+
static bool __read_mostly vmx_fb_clear_ctrl_available;
234+
232235
static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
233236
{
234237
struct page *page;
@@ -360,6 +363,60 @@ static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
360363
return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
361364
}
362365

366+
static void vmx_setup_fb_clear_ctrl(void)
367+
{
368+
u64 msr;
369+
370+
if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) &&
371+
!boot_cpu_has_bug(X86_BUG_MDS) &&
372+
!boot_cpu_has_bug(X86_BUG_TAA)) {
373+
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
374+
if (msr & ARCH_CAP_FB_CLEAR_CTRL)
375+
vmx_fb_clear_ctrl_available = true;
376+
}
377+
}
378+
379+
static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
380+
{
381+
u64 msr;
382+
383+
if (!vmx->disable_fb_clear)
384+
return;
385+
386+
rdmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
387+
msr |= FB_CLEAR_DIS;
388+
wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
389+
/* Cache the MSR value to avoid reading it later */
390+
vmx->msr_ia32_mcu_opt_ctrl = msr;
391+
}
392+
393+
static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx)
394+
{
395+
if (!vmx->disable_fb_clear)
396+
return;
397+
398+
vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS;
399+
wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl);
400+
}
401+
402+
static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
403+
{
404+
vmx->disable_fb_clear = vmx_fb_clear_ctrl_available;
405+
406+
/*
407+
* If guest will not execute VERW, there is no need to set FB_CLEAR_DIS
408+
* at VMEntry. Skip the MSR read/write when a guest has no use case to
409+
* execute VERW.
410+
*/
411+
if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) ||
412+
((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) &&
413+
(vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) &&
414+
(vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) &&
415+
(vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) &&
416+
(vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO)))
417+
vmx->disable_fb_clear = false;
418+
}
419+
363420
static const struct kernel_param_ops vmentry_l1d_flush_ops = {
364421
.set = vmentry_l1d_flush_set,
365422
.get = vmentry_l1d_flush_get,
@@ -2252,6 +2309,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
22522309
ret = kvm_set_msr_common(vcpu, msr_info);
22532310
}
22542311

2312+
/* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */
2313+
if (msr_index == MSR_IA32_ARCH_CAPABILITIES)
2314+
vmx_update_fb_clear_dis(vcpu, vmx);
2315+
22552316
return ret;
22562317
}
22572318

@@ -4553,6 +4614,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
45534614
kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
45544615

45554616
vpid_sync_context(vmx->vpid);
4617+
4618+
vmx_update_fb_clear_dis(vcpu, vmx);
45564619
}
45574620

45584621
static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)
@@ -6777,6 +6840,8 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
67776840
kvm_arch_has_assigned_device(vcpu->kvm))
67786841
mds_clear_cpu_buffers();
67796842

6843+
vmx_disable_fb_clear(vmx);
6844+
67806845
if (vcpu->arch.cr2 != native_read_cr2())
67816846
native_write_cr2(vcpu->arch.cr2);
67826847

@@ -6785,6 +6850,8 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
67856850

67866851
vcpu->arch.cr2 = native_read_cr2();
67876852

6853+
vmx_enable_fb_clear(vmx);
6854+
67886855
guest_state_exit_irqoff();
67896856
}
67906857

@@ -8185,6 +8252,8 @@ static int __init vmx_init(void)
81858252
return r;
81868253
}
81878254

8255+
vmx_setup_fb_clear_ctrl();
8256+
81888257
for_each_possible_cpu(cpu) {
81898258
INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
81908259

arch/x86/kvm/vmx/vmx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ struct vcpu_vmx {
348348
u64 msr_ia32_feature_control_valid_bits;
349349
/* SGX Launch Control public key hash */
350350
u64 msr_ia32_sgxlepubkeyhash[4];
351+
u64 msr_ia32_mcu_opt_ctrl;
352+
bool disable_fb_clear;
351353

352354
struct pt_desc pt_desc;
353355
struct lbr_desc lbr_desc;

arch/x86/kvm/x86.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,9 @@ static u64 kvm_get_arch_capabilities(void)
15871587
*/
15881588
}
15891589

1590+
/* Guests don't need to know "Fill buffer clear control" exists */
1591+
data &= ~ARCH_CAP_FB_CLEAR_CTRL;
1592+
15901593
return data;
15911594
}
15921595

tools/arch/x86/include/asm/msr-index.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@
133133
* VERW clears CPU fill buffer
134134
* even on MDS_NO CPUs.
135135
*/
136+
#define ARCH_CAP_FB_CLEAR_CTRL BIT(18) /*
137+
* MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]
138+
* bit available to control VERW
139+
* behavior.
140+
*/
136141

137142
#define MSR_IA32_FLUSH_CMD 0x0000010b
138143
#define L1D_FLUSH BIT(0) /*
@@ -150,6 +155,7 @@
150155
#define MSR_IA32_MCU_OPT_CTRL 0x00000123
151156
#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
152157
#define RTM_ALLOW BIT(1) /* TSX development mode */
158+
#define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */
153159

154160
#define MSR_IA32_SYSENTER_CS 0x00000174
155161
#define MSR_IA32_SYSENTER_ESP 0x00000175

0 commit comments

Comments
 (0)