Re: [PATCH v3 06/27] KVM: SVM: Fallback to flush everything if FLUSHBYASID is not available

From: Jim Mattson

Date: Wed Oct 14 2026 - 19:27:36 EST


On Wed, Oct 14, 2026 at 3:50 PM Yosry Ahmed <yosry@xxxxxxxxxx> wrote:
>
> On Wed, Oct 14, 2026 at 3:45 PM Jim Mattson <jmattson@xxxxxxxxxx> wrote:
> >
> > On Mon, Oct 12, 2026 at 4:36 PM Yosry Ahmed <yosry@xxxxxxxxxx> wrote:
> > >
> > > Currently, if FLUSHBYASID is not available when performing a TLB flush,
> > > the fallback is decrementing the ASID generation to trigger allocating a
> > > new ASID. In preparation for using a static ASID per vCPU (like VMX),
> > > just fallback to flushing everything if FLUSHBYASID is not available.
> > > This is probably worse from a performance perspective, but FLUSHBYASID
> > > has been around for ~15 years and it's not worth carrying the
> > > complexity.
> > >
> > > Move the fallback logic into vmcb_set_flush_asid(), as more callers will
> > > be added and will need the fallback as well. The only other current
> > > caller is from SEV code, and no CPUs support SEV but not FLUSHBYASID (at
> > > least according to AI).
> >
> > A more compelling argument is that sev_hardware_setup() requires FLUSHBYASID.
>
> Huh, I didn't realize this.
>
> >
> > > Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx>
> > > Signed-off-by: Yosry Ahmed <yosry@xxxxxxxxxx>
> > > ---
> > > arch/x86/kvm/svm/svm.c | 5 +----
> > > arch/x86/kvm/svm/svm.h | 5 ++++-
> > > 2 files changed, 5 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > > index ad4f172f170d9..0c3befd9bc850 100644
> > > --- a/arch/x86/kvm/svm/svm.c
> > > +++ b/arch/x86/kvm/svm/svm.c
> > > @@ -4326,10 +4326,7 @@ static void svm_flush_tlb_asid(struct kvm_vcpu *vcpu)
> > > * unconditionally does a TLB flush on both nested VM-Enter and nested
> > > * VM-Exit (via kvm_mmu_reset_context()).
> > > */
> > > - if (cpu_feature_enabled(X86_FEATURE_FLUSHBYASID))
> > > - vmcb_set_flush_asid(svm->vmcb);
> > > - else
> > > - svm->current_vmcb->asid_generation--;
> > > + vmcb_set_flush_asid(svm->vmcb);
> > > }
> > >
> > > static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
> > > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> > > index ba5077b9838c0..3b59561d6cc2c 100644
> > > --- a/arch/x86/kvm/svm/svm.h
> > > +++ b/arch/x86/kvm/svm/svm.h
> > > @@ -482,7 +482,10 @@ static inline void vmcb_set_gpat(struct vmcb *vmcb, u64 data)
> > >
> > > static inline void vmcb_set_flush_asid(struct vmcb *vmcb)
> > > {
> > > - vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
> > > + if (cpu_feature_enabled(X86_FEATURE_FLUSHBYASID))
> > > + vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
> > > + else
> > > + vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
> >
> > This is unnecessary. Hardware that doesn't have FLUSHBYASID only looks
> > at tlb_ctl bit 0 to decide whether or not to flush the entire TLB.
> > The other bits are ignored.
>
> I think it's clearer to do the fallback since the APM doesn't
> specifically call this out, or maybe it does but I can't find it.

Fair point. I dug up a copy of the SVM manual from 2005, and it
actually seems to indicate that there isn't a bit toggle, but rather
the entire field value is consulted:

> The TLB_CONTROL field in the VMCB currently has one command implemented. When the VMM sets the TLB_CONTROL field to 1, the VMRUN instruction flushes the TLB for all ASIDs, for both global and non-global pages.

That isn't how the hardware works, though.