Message ID | 20211115234603.2908381-2-bgardon@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Currently disabling dirty logging with the TDP MMU is extremely slow. On a 96 vCPU / 96G VM it takes ~45 seconds to disable dirty logging with the TDP MMU, as opposed to ~3.5 seconds with the legacy MMU. This series optimizes TLB flushes and intro | expand |
On 11/16/21 00:45, Ben Gardon wrote: > tdp_mmu_zap_spte_atomic flushes on every zap already, so no need to > flush again after it's done. > > Reviewed-by: David Matlack <dmatlack@google.com> > > Signed-off-by: Ben Gardon <bgardon@google.com> > --- > arch/x86/kvm/mmu/mmu.c | 4 +--- > arch/x86/kvm/mmu/tdp_mmu.c | 21 ++++++--------------- > arch/x86/kvm/mmu/tdp_mmu.h | 5 ++--- > 3 files changed, 9 insertions(+), 21 deletions(-) > > diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c > index 354d2ca92df4..baa94acab516 100644 > --- a/arch/x86/kvm/mmu/mmu.c > +++ b/arch/x86/kvm/mmu/mmu.c > @@ -5870,9 +5870,7 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, > > if (is_tdp_mmu_enabled(kvm)) { > read_lock(&kvm->mmu_lock); > - flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, flush); > - 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 7c5dd83e52de..b3c78568ae60 100644 > --- a/arch/x86/kvm/mmu/tdp_mmu.c > +++ b/arch/x86/kvm/mmu/tdp_mmu.c > @@ -1364,10 +1364,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; > @@ -1378,10 +1377,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)) > @@ -1401,30 +1398,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 476b133544dd..3899004a5d91 100644 > --- a/arch/x86/kvm/mmu/tdp_mmu.h > +++ b/arch/x86/kvm/mmu/tdp_mmu.h > @@ -64,9 +64,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, > Queued, thanks. Paolo
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 354d2ca92df4..baa94acab516 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5870,9 +5870,7 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, if (is_tdp_mmu_enabled(kvm)) { read_lock(&kvm->mmu_lock); - flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, flush); - 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 7c5dd83e52de..b3c78568ae60 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1364,10 +1364,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; @@ -1378,10 +1377,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)) @@ -1401,30 +1398,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 476b133544dd..3899004a5d91 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.h +++ b/arch/x86/kvm/mmu/tdp_mmu.h @@ -64,9 +64,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,