Skip to content

Commit e6ff1d6

Browse files
committed
KVM: VMX: Handle MMIO Stale Data in VM-Enter assembly via ALTERNATIVES_2
Rework the handling of the MMIO Stale Data mitigation to clear CPU buffers immediately prior to VM-Enter, i.e. in the same location that KVM emits a VERW for unconditional (at runtime) clearing. Co-locating the code and using a single ALTERNATIVES_2 makes it more obvious how VMX mitigates the various vulnerabilities. Deliberately order the alternatives as: 0. Do nothing 1. Clear if vCPU can access MMIO 2. Clear always since the last alternative wins in ALTERNATIVES_2(), i.e. so that KVM will honor the strictest mitigation (always clear CPU buffers) if multiple mitigations are selected. E.g. even if the kernel chooses to mitigate MMIO Stale Data via X86_FEATURE_CLEAR_CPU_BUF_VM_MMIO, another mitigation may enable X86_FEATURE_CLEAR_CPU_BUF_VM, and that other thing needs to win. Note, decoupling the MMIO mitigation from the L1TF mitigation also fixes a mostly-benign flaw where KVM wouldn't do any clearing/flushing if the L1TF mitigation is configured to conditionally flush the L1D, and the MMIO mitigation but not any other "clear CPU buffers" mitigation is enabled. For that specific scenario, KVM would skip clearing CPU buffers for the MMIO mitigation even though the kernel requested a clear on every VM-Enter. Note #2, the flaw goes back to the introduction of the MDS mitigation. The MDS mitigation was inadvertently fixed by commit 43fb862 ("KVM/VMX: Move VERW closer to VMentry for MDS mitigation"), but previous kernels that flush CPU buffers in vmx_vcpu_enter_exit() are affected (though it's unlikely the flaw is meaningfully exploitable even older kernels). Fixes: 650b68a ("x86/kvm/vmx: Add MDS protection when L1D Flush is not active") Suggested-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Reviewed-by: Brendan Jackman <jackmanb@google.com> Link: https://patch.msgid.link/20251113233746.1703361-6-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent f6106d4 commit e6ff1d6

File tree

2 files changed

+14
-15
lines changed

2 files changed

+14
-15
lines changed

arch/x86/kvm/vmx/vmenter.S

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
* @regs: unsigned long * (to guest registers)
7272
* @flags: VMX_RUN_VMRESUME: use VMRESUME instead of VMLAUNCH
7373
* VMX_RUN_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl
74+
* VMX_RUN_CLEAR_CPU_BUFFERS_FOR_MMIO: vCPU can access host MMIO
7475
*
7576
* Returns:
7677
* 0 on VM-Exit, 1 on VM-Fail
@@ -154,8 +155,19 @@ SYM_FUNC_START(__vmx_vcpu_run)
154155
/* Load guest RAX. This kills the @regs pointer! */
155156
mov VCPU_RAX(%_ASM_AX), %_ASM_AX
156157

157-
/* Clobbers EFLAGS.ZF */
158-
VM_CLEAR_CPU_BUFFERS
158+
/*
159+
* Note, ALTERNATIVE_2 works in reverse order. If CLEAR_CPU_BUF_VM is
160+
* enabled, do VERW unconditionally. If CPU_BUF_VM_MMIO is enabled,
161+
* check @flags to see if the vCPU has access to host MMIO, and if so,
162+
* do VERW. Else, do nothing (no mitigations needed/enabled).
163+
*/
164+
ALTERNATIVE_2 "", \
165+
__stringify(testl $VMX_RUN_CLEAR_CPU_BUFFERS_FOR_MMIO, WORD_SIZE(%_ASM_SP); \
166+
jz .Lskip_mmio_verw; \
167+
VERW; \
168+
.Lskip_mmio_verw:), \
169+
X86_FEATURE_CLEAR_CPU_BUF_VM_MMIO, \
170+
__stringify(VERW), X86_FEATURE_CLEAR_CPU_BUF_VM
159171

160172
/* Check @flags to see if VMLAUNCH or VMRESUME is needed. */
161173
testl $VMX_RUN_VMRESUME, WORD_SIZE(%_ASM_SP)

arch/x86/kvm/vmx/vmx.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7313,21 +7313,8 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
73137313

73147314
guest_state_enter_irqoff();
73157315

7316-
/*
7317-
* L1D Flush includes CPU buffer clear to mitigate MDS, but VERW
7318-
* mitigation for MDS is done late in VMentry and is still
7319-
* executed in spite of L1D Flush. This is because an extra VERW
7320-
* should not matter much after the big hammer L1D Flush.
7321-
*
7322-
* cpu_buf_vm_clear is used when system is not vulnerable to MDS/TAA,
7323-
* and is affected by MMIO Stale Data. In such cases mitigation in only
7324-
* needed against an MMIO capable guest.
7325-
*/
73267316
if (static_branch_unlikely(&vmx_l1d_should_flush))
73277317
vmx_l1d_flush(vcpu);
7328-
else if (cpu_feature_enabled(X86_FEATURE_CLEAR_CPU_BUF_VM_MMIO) &&
7329-
(flags & VMX_RUN_CLEAR_CPU_BUFFERS_FOR_MMIO))
7330-
x86_clear_cpu_buffers();
73317318

73327319
vmx_disable_fb_clear(vmx);
73337320

0 commit comments

Comments
 (0)