From: Yosry Ahmed <yosry@kernel.org>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Jim Mattson <jmattson@google.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Yosry Ahmed <yosry@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH 3/3] KVM: nVM: Ensure INVVPID is emulated on the correct physical CPU
Date: Tue, 16 Jun 2026 21:46:52 +0000 [thread overview]
Message-ID: <20260616214652.2157032-4-yosry@kernel.org> (raw)
In-Reply-To: <20260616214652.2157032-1-yosry@kernel.org>
When emulating INVVPID, KVM executes INVVPID on the physical CPU using
vpid02 (instead of the L1 assigned VPID), after doing some validations
on the operands. However, it is possible that the physical CPU KVM
executes INVVPID on is different from the CPU L2 is running on.
For example, in the following scenario:
- L2 runs on CPU #1 and exits to L1 (vmx->nested.vmcs02.cpu=1)
- L1 migrates to CPU #2 and executes INVVPID
- KVM executes INVVPID on CPU #2
- L1 migrates back to CPU #1 and runs L2 (vmx->nested.vmcs02.cpu=1)
The TLB entries on CPU #1 are never invalidated, because INVVPID was
executed on CPU #2, and vmcs02 never ran on a different pCPU (i.e.
vmx_vcpu_load_vmcs() will *not* request KVM_REQ_TLB_FLUSH).
Ensure that INVVPID is being executed on the same pCPU that L2 last ran
on, and if not, fallback to clearing last_vpid=0 to trigger a full VPID
flush on the next nested VM-Enter (as KVM will detect L1 using a
different VPID for L2). If L2 ends up running on a different pCPU, KVM
will flush the TLB anyway through vmx_vcpu_load_vmcs().
Cc: stable@vger.kernel.org
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
arch/x86/kvm/vmx/nested.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 596dec7ba2b78..2d1cd2c2a46d7 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -6085,6 +6085,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
u64 gla;
} operand;
int r, gpr_index;
+ int cpu;
if (!(vmx->nested.msrs.secondary_ctls_high &
SECONDARY_EXEC_ENABLE_VPID) ||
@@ -6133,11 +6134,19 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
* and never explicitly flush vpid01. INVVPID targets a VPID, not a
* VMCS, and so whether or not the current vmcs12 has VPID enabled is
* irrelevant (and there may not be a loaded vmcs12).
+ *
+ * If vmcs02 was last loaded on a different pCPU, then defer the flush
+ * by invalidating the nested VPID tracking to ensure that KVM performs
+ * the invalidation on the correct pCPU.
*/
- if (type == VMX_VPID_EXTENT_INDIVIDUAL_ADDR)
+ cpu = get_cpu();
+ if (cpu != vmx->nested.vmcs02.cpu)
+ vmx->nested.last_vpid = 0;
+ else if (type == VMX_VPID_EXTENT_INDIVIDUAL_ADDR)
vpid_sync_vcpu_addr(nested_get_vpid02(vcpu), operand.gla);
else
vpid_sync_context(nested_get_vpid02(vcpu));
+ put_cpu();
/*
* Sync the shadow page tables if EPT is disabled, L1 is invalidating
--
2.54.0.1136.gdb2ca164c4-goog
prev parent reply other threads:[~2026-06-16 21:47 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 21:46 [PATCH 0/3] KVM: nVMX: A few TLB flushing fixes Yosry Ahmed
2026-06-16 21:46 ` [PATCH 1/3] KVM: nVMX: Always flush vpid02 on first use Yosry Ahmed
2026-06-16 22:25 ` Jim Mattson
2026-06-16 21:46 ` [PATCH 2/3] KVM: nVMX: Decouple INVVPID operand checks from flushing of vpid02 Yosry Ahmed
2026-06-16 21:46 ` Yosry Ahmed [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260616214652.2157032-4-yosry@kernel.org \
--to=yosry@kernel.org \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox