On Fri, Feb 13, 2026, Jim Mattson wrote:
> On Fri, Feb 13, 2026 at 7:20 AM Sean Christopherson <[email protected]> wrote:
> > > > +static inline void svm_set_hpat(struct vcpu_svm *svm, u64 data)
> > > > +{
> > > > + svm->vcpu.arch.pat = data;
> > > > + if (npt_enabled) {
> >
> > Peeking at the future patches, if we make this:
> >
> > if (!npt_enabled)
> > return;
> >
> > then we can end up with this:
> >
> > if (npt_enabled)
> > return;
> >
> > vmcb_set_gpat(svm->vmcb01.ptr, data);
> > if (is_guest_mode(&svm->vcpu) && !nested_npt_enabled(svm))
> > vmcb_set_gpat(svm->nested.vmcb02.ptr, data);
> >
> > if (svm->nested.legacy_gpat_semantics)
> > svm_set_l2_pat(svm, data);
> >
> > Because legacy_gpat_semantics can only be true if npt_enabled is true.
> > Without
> > that guard, KVM _looks_ buggy because it's setting gpat in the VMCB even
> > when
> > it shouldn't exist.
> >
> > Actually, calling svm_set_l2_pat() when !is_guest_mode() is wrong too, no?
> > E.g.
> > shouldn't we end up with this?
>
> Sigh. legacy_gpat_semantics is supposed to be set only when
> is_guest_mode() and nested_npt_enabled(). I forgot about back-to-back
> invocations of KVM_SET_NESTED_STATE. Are there other ways of leaving
> guest mode or disabling nested NPT before the next KVM_RUN?
KVM_SET_VCPU_EVENTS will do it if userspace forces a change in SMM state:
if (!!(vcpu->arch.hflags & HF_SMM_MASK) != events->smi.smm) {
kvm_leave_nested(vcpu);
kvm_smm_changed(vcpu, events->smi.smm);
}
I honestly wasn't even thinking of anything in particular, it just looked weird.
> > > > + vmcb_set_gpat(svm->vmcb01.ptr, data);
> > > > + if (is_guest_mode(&svm->vcpu) && !nested_npt_enabled(svm))
> > > > + vmcb_set_gpat(svm->nested.vmcb02.ptr, data);
> > > > + }
> > > > +}
> > >
> > > Is it me, or is it a bit confusing that svm_set_gpat() sets L2's gPAT
> > > not L1's, and svm_set_hpat() calls vmcb_set_gpat()?
> >
> > It's not just you. I don't find it confusing per se, more that it's really
> > subtle.
> >
> > > "gpat" means different things in the context of the VMCB or otherwise,
> > > which kinda makes sense but is also not super clear. Maybe
> > > svm_set_l1_gpat() and svm_set_l2_gpat() is more clear?
> >
> > I think just svm_set_l1_pat() and svm_set_l2_pat(), because gpat straight up
> > doesn't exist when NPT is disabled/unsupported.
>
> My intention was that "gpat" and "hpat" were from the perspective of the vCPU.
>
> I dislike svm_set_l1_pat() and svm_set_l2_pat(). As you point out
> above, there is no independent L2 PAT when nested NPT is disabled. I
> think that's less obvious than the fact that there is no gPAT from the
> vCPU's perspective. My preference is to follow the APM terminology
> when possible. Making up our own terms just leads to confusion.
How about svm_set_pat() and svm_get_gpat()? Because hPAT doesn't exist when NPT
is unsupported/disabled, but KVM still needs to set the vCPU's emulated PAT
value.