[PATCH 1/3] KVM: nVMX: Always flush vpid02 on first use

From: Yosry Ahmed

Date: Tue Jun 16 2026 - 17:47:40 EST


Make sure vpid02 is always flushed on first use by setting last_vpid=0
when allocating vpid02. nested_vmx_transition_tlb_flush() will always
detect a VPID change on first VM-Enter after VMXON, because VPID=0 in
vmcb12 is not allowed if L1 enables VPID.

This avoids using stale TLB entries from a previous lifetime of the
VPID, that might have been associated with a different vCPU (or a
completely different VM).

Note that last_vpid is already being initialized as 0 when the vCPU is
created, but it is not reset when vpid02 is freed on VMXOFF. Hence, the
problem can only occur if L1 does VMXOFF -> VMXON, runs an L2, and KVM
happens to reuse a VPID that has TLB entries on the physical CPU.

Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yosry Ahmed <yosry@xxxxxxxxxx>
---
arch/x86/kvm/vmx/nested.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index b2c851cc7d5c8..a49115d9a5a54 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -1290,6 +1290,9 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu,
* is the VPID incorporated into the MMU context. I.e. KVM must assume
* that the new vpid12 has never been used and thus represents a new
* guest ASID that cannot have entries in the TLB.
+ *
+ * Note, last_vpid is initialized as 0, so the first nested VM-Enter
+ * after VMXON will always flush the TLB to avoid using stale entries.
*/
if (is_vmenter && vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
vmx->nested.last_vpid = vmcs12->virtual_processor_id;
@@ -5447,6 +5450,13 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)

vmx->nested.vpid02 = allocate_vpid();

+ /*
+ * Clear last_vpid to ensure that the VPID is flushed on the first
+ * nested VM-Enter. Otherwise, stale TLB entries from a previous life of
+ * the VPID (e.g. different vCPU or even different VM) could be used.
+ */
+ vmx->nested.last_vpid = 0;
+
vmx->nested.vmcs02_initialized = false;
vmx->nested.vmxon = true;

--
2.54.0.1136.gdb2ca164c4-goog