lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 180/207] KVM: x86/mmu: Remove spurious TLB flushes in TDP MMU zap collapsible path
    Date
    From: Sean Christopherson <seanjc@google.com>

    [ Upstream commit 4b85c921cd393764d22c0cdab6d7d5d120aa0980 ]

    Drop the "flush" param and return values to/from the TDP MMU's helper for
    zapping collapsible SPTEs. Because the helper runs with mmu_lock held
    for read, not write, it uses tdp_mmu_zap_spte_atomic(), and the atomic
    zap handles the necessary remote TLB flush.

    Similarly, because mmu_lock is dropped and re-acquired between zapping
    legacy MMUs and zapping TDP MMUs, kvm_mmu_zap_collapsible_sptes() must
    handle remote TLB flushes from the legacy MMU before calling into the TDP
    MMU.

    Fixes: e2209710ccc5d ("KVM: x86/mmu: Skip rmap operations if rmaps not allocated")
    Signed-off-by: Sean Christopherson <seanjc@google.com>
    Message-Id: <20211120045046.3940942-4-seanjc@google.com>
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    arch/x86/kvm/mmu/mmu.c | 9 ++-------
    arch/x86/kvm/mmu/tdp_mmu.c | 22 +++++++---------------
    arch/x86/kvm/mmu/tdp_mmu.h | 5 ++---
    3 files changed, 11 insertions(+), 25 deletions(-)

    diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
    index f2e74e8c1651a..0a88cb4f731f4 100644
    --- a/arch/x86/kvm/mmu/mmu.c
    +++ b/arch/x86/kvm/mmu/mmu.c
    @@ -5855,8 +5855,6 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
    void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
    const struct kvm_memory_slot *slot)
    {
    - bool flush;
    -
    if (kvm_memslots_have_rmaps(kvm)) {
    write_lock(&kvm->mmu_lock);
    /*
    @@ -5864,17 +5862,14 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
    * logging at a 4k granularity and never creates collapsible
    * 2m SPTEs during dirty logging.
    */
    - flush = slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true);
    - if (flush)
    + if (slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true))
    kvm_arch_flush_remote_tlbs_memslot(kvm, slot);
    write_unlock(&kvm->mmu_lock);
    }

    if (is_tdp_mmu_enabled(kvm)) {
    read_lock(&kvm->mmu_lock);
    - flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, false);
    - if (flush)
    - kvm_arch_flush_remote_tlbs_memslot(kvm, slot);
    + kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot);
    read_unlock(&kvm->mmu_lock);
    }
    }
    diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
    index aa75689a91b4c..0e4227b59d7bb 100644
    --- a/arch/x86/kvm/mmu/tdp_mmu.c
    +++ b/arch/x86/kvm/mmu/tdp_mmu.c
    @@ -1413,10 +1413,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
    * Clear leaf entries which could be replaced by large mappings, for
    * GFNs within the slot.
    */
    -static bool zap_collapsible_spte_range(struct kvm *kvm,
    +static void zap_collapsible_spte_range(struct kvm *kvm,
    struct kvm_mmu_page *root,
    - const struct kvm_memory_slot *slot,
    - bool flush)
    + const struct kvm_memory_slot *slot)
    {
    gfn_t start = slot->base_gfn;
    gfn_t end = start + slot->npages;
    @@ -1427,10 +1426,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm,

    tdp_root_for_each_pte(iter, root, start, end) {
    retry:
    - if (tdp_mmu_iter_cond_resched(kvm, &iter, flush, true)) {
    - flush = false;
    + if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
    continue;
    - }

    if (!is_shadow_present_pte(iter.old_spte) ||
    !is_last_spte(iter.old_spte, iter.level))
    @@ -1442,6 +1439,7 @@ static bool zap_collapsible_spte_range(struct kvm *kvm,
    pfn, PG_LEVEL_NUM))
    continue;

    + /* Note, a successful atomic zap also does a remote TLB flush. */
    if (!tdp_mmu_zap_spte_atomic(kvm, &iter)) {
    /*
    * The iter must explicitly re-read the SPTE because
    @@ -1450,30 +1448,24 @@ static bool zap_collapsible_spte_range(struct kvm *kvm,
    iter.old_spte = READ_ONCE(*rcu_dereference(iter.sptep));
    goto retry;
    }
    - flush = true;
    }

    rcu_read_unlock();
    -
    - return flush;
    }

    /*
    * Clear non-leaf entries (and free associated page tables) which could
    * be replaced by large mappings, for GFNs within the slot.
    */
    -bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
    - const struct kvm_memory_slot *slot,
    - bool flush)
    +void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
    + const struct kvm_memory_slot *slot)
    {
    struct kvm_mmu_page *root;

    lockdep_assert_held_read(&kvm->mmu_lock);

    for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true)
    - flush = zap_collapsible_spte_range(kvm, root, slot, flush);
    -
    - return flush;
    + zap_collapsible_spte_range(kvm, root, slot);
    }

    /*
    diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
    index 358f447d40120..ba3681cd38ab4 100644
    --- a/arch/x86/kvm/mmu/tdp_mmu.h
    +++ b/arch/x86/kvm/mmu/tdp_mmu.h
    @@ -66,9 +66,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
    struct kvm_memory_slot *slot,
    gfn_t gfn, unsigned long mask,
    bool wrprot);
    -bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
    - const struct kvm_memory_slot *slot,
    - bool flush);
    +void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
    + const struct kvm_memory_slot *slot);

    bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
    struct kvm_memory_slot *slot, gfn_t gfn,
    --
    2.33.0


    \
     
     \ /
      Last update: 2021-12-06 17:10    [W:4.450 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site