Re: [PATCH v3 22/27] KVM: nSVM: Flush the TLB if L1 changes L2's ASID in vmcb12

From: Yosry Ahmed

Date: Thu Oct 15 2026 - 19:20:58 EST


On Thu, Oct 15, 2026 at 4:09 PM Jim Mattson <jmattson@xxxxxxxxxx> wrote:
>
> On Mon, Oct 12, 2026 at 4:36 PM Yosry Ahmed <yosry@xxxxxxxxxx> wrote:
> >
> > KVM uses a single ASID for L2 guests per-vCPU. Hence, when L1 changes
> > L2's ASID in vmcb12 (e.g. due to switching to a different L2
> > vCPU or simply to avoid flushing an existing ASID), KVM needs to flush
> > the L2 ASID to correctly emulate different ASIDs as different TLB
> > domains.
> >
> > Additionally, the nested NPT needs to be resync'd, as the MMU context
> > is not tagged by ASID, and KVM cannot reuse nested NPT entries across
> > different L2 ASIDs.
> >
> > Essentially, L1 switching L2's ASID is treated exactly the same as L1
> > flushing L2's ASID, which is consistent with the APM:
> >
> > Software may effectively flush the guest's TLB entries by allocating a
> > new ASID for the guest and not reusing the old ASID until the entire
> > TLB has been flushed at least once.
> >
> > This is similar to nVMX's handling of last_vpid, except that when L1
> > changes VPID12, KVM does *not* need to resync the nested EPT, because
> > VMX VPIDs, unlike SVM ASIDs, do not tag guest-physical translations
> > (i.e. nGPA to GPA translations).
> >
> > Reset last_asid when nested VMRUN fails to force a flush and sync on the
> > next nested VMRUN. The TLB flush request survives the failure, but the
> > request to sync the nested NPT does not, as it ends up being serviced in
> > L1's MMU context after the synthesized VM-Exit.
> >
> > Drop the commentary about vmcb12's ASID being copied around only for the
> > consistency checks, as they no longer apply, and opportunistically fix
> > whitespace alignment.
> >
> > This is currently functionally a noop, as a full flush and sync is
> > triggered on every nested transition, but is a step toward eliminating
> > that.
> >
> > Signed-off-by: Yosry Ahmed <yosry@xxxxxxxxxx>
> > ---
> > arch/x86/kvm/svm/nested.c | 29 +++++++++++++++++++++++------
> > arch/x86/kvm/svm/svm.h | 2 ++
> > 2 files changed, 25 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> > index e04cc4f7669ea..8e4686b0d603a 100644
> > --- a/arch/x86/kvm/svm/nested.c
> > +++ b/arch/x86/kvm/svm/nested.c
> > @@ -556,10 +556,8 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu,
> > to->nested_cr3 = from->nested_cr3;
> > to->pause_filter_count = from->pause_filter_count;
> > to->pause_filter_thresh = from->pause_filter_thresh;
> > -
> > - /* Copy asid here because nested_vmcb_check_controls() will check it */
> > - to->asid = from->asid;
> > - to->clean = from->clean;
> > + to->asid = from->asid;
> > + to->clean = from->clean;
> >
> > #ifdef CONFIG_KVM_HYPERV
> > /* Hyper-V extensions (Enlightened VMCB) */
> > @@ -691,23 +689,35 @@ static void nested_save_pending_event_to_vmcb12(struct vcpu_svm *svm,
> > static void nested_svm_entry_tlb_flush(struct kvm_vcpu *vcpu)
> > {
> > struct vcpu_svm *svm = to_svm(vcpu);
> > + bool new_asid = false;
> >
> > /* Handle pending Hyper-V TLB flush requests */
> > kvm_hv_nested_transtion_tlb_flush(vcpu, npt_enabled);
> >
> > + if (svm->nested.ctl.asid != svm->nested.last_asid) {
> > + svm->nested.last_asid = svm->nested.ctl.asid;
> > + new_asid = true;
> > + }
>
> To make sure we don't miss a flush after restore, do we need to clear
> last_asid in svm_set_nested_state()?

In [1], we set svm->nested.vmcb02.cpu = -1 in svm_allocate_nested(),
which should be called when EFER.SVME is set on restore, and should
force a TLB flush on the first vCPU run. That being said, if EFER.SVME
was already set (not a fresh vCPU), we won't necessarily flush the
TLB. KVM_SET_SREGS will _probably_ flush the TLB, but I don't think
it's guaranteed.

But wouldn't this also affect non-nested? Are we guaranteed to flush
L1's ASID after restore?

[1] https://lore.kernel.org/kvm/20260903175856.4065099-1-yosry@xxxxxxxxxx/