Re: [PATCH] KVM: x86/mmu: Rename slot_handle_leaf to slot_handle_level_4k

David Matlack
2021-10-11T21:27:46Z

On Mon, Oct 11, 2021 at 2:25 PM David Matlack <dmatlack@google.com> wrote:
>
> On Mon, Oct 11, 2021 at 2:07 PM Ben Gardon <bgardon@google.com> wrote:
> >
> > On Mon, Oct 11, 2021 at 1:44 PM David Matlack <dmatlack@google.com> wrote:
> > >
> > > slot_handle_leaf is a misnomer because it only operates on 4K SPTEs
> > > whereas "leaf" is used to describe any valid terminal SPTE (4K or
> > > large page). Rename slot_handle_leaf to slot_handle_level_4k to
> > > avoid confusion.
> > >
> > > Making this change makes it more obvious there is a benign discrepency
> > > between the legacy MMU and the TDP MMU when it comes to dirty logging.
> > > The legacy MMU only operates on 4K SPTEs when zapping for collapsing
> > > and when clearing D-bits. The TDP MMU, on the other hand, operates on
> > > SPTEs on all levels. The TDP MMU behavior is technically overkill but
> > > not incorrect. So opportunistically add comments to explain the
> > > difference.
> >
> > Note that at least in the zapping case when disabling dirty logging,
> > the TDP MMU will still only zap pages if they're mapped smaller than
> > the highest granularity they could be. As a result it uses a slower
> > check, but shouldn't be doing many (if any) extra zaps.
>
> Agreed. The legacy MMU implementation relies on the fact that
> collapsible 2M SPTEs are never generated by dirty logging so it only
> needs to check 4K SPTEs.
>
> The TDP MMU implementation is actually more robust, since it checks
> every SPTE for collapsibility. The only reason it would be doing extra
> zaps if there is something other than dirty logging can cause an SPTE
> to be collapsible. (HugePage NX comes to mind.)

Ah but HugePage NX does not create 2M SPTEs so this wouldn't actually
result in extra zaps.

>
> >
> > >
> > > Signed-off-by: David Matlack <dmatlack@google.com>
> >
> > Reviewed-by: Ben Gardon <bgardon@google.com>
> >
> > > ---
> > > arch/x86/kvm/mmu/mmu.c | 18 +++++++++++++-----
> > > 1 file changed, 13 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> > > index 24a9f4c3f5e7..f00644e79ef5 100644
> > > --- a/arch/x86/kvm/mmu/mmu.c
> > > +++ b/arch/x86/kvm/mmu/mmu.c
> > > @@ -5382,8 +5382,8 @@ slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot,
> > > }
> > >
> > > static __always_inline bool
> > > -slot_handle_leaf(struct kvm *kvm, const struct kvm_memory_slot *memslot,
> > > - slot_level_handler fn, bool flush_on_yield)
> > > +slot_handle_level_4k(struct kvm *kvm, const struct kvm_memory_slot *memslot,
> > > + slot_level_handler fn, bool flush_on_yield)
> > > {
> > > return slot_handle_level(kvm, memslot, fn, PG_LEVEL_4K,
> > > PG_LEVEL_4K, flush_on_yield);
> > > @@ -5772,7 +5772,12 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
> > >
> > > if (kvm_memslots_have_rmaps(kvm)) {
> > > write_lock(&kvm->mmu_lock);
> > > - flush = slot_handle_leaf(kvm, slot, kvm_mmu_zap_collapsible_spte, true);
> > > + /*
> > > + * Strictly speaking only 4k SPTEs need to be zapped because
> > > + * KVM never creates intermediate 2m mappings when performing
> > > + * dirty logging.
> > > + */
> > > + flush = slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true);
> > > if (flush)
> > > kvm_arch_flush_remote_tlbs_memslot(kvm, slot);
> > > write_unlock(&kvm->mmu_lock);
> > > @@ -5809,8 +5814,11 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
> > >
> > > if (kvm_memslots_have_rmaps(kvm)) {
> > > write_lock(&kvm->mmu_lock);
> > > - flush = slot_handle_leaf(kvm, memslot, __rmap_clear_dirty,
> > > - false);
> > > + /*
> > > + * Strictly speaking only 4k SPTEs need to be cleared because
> > > + * KVM always performs dirty logging at a 4k granularity.
> > > + */
> > > + flush = slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false);
> > > write_unlock(&kvm->mmu_lock);
> > > }
> > >
> > > --
> > > 2.33.0.882.g93a45727a2-goog
> > >