Skip to content

Commit fe140e6

Browse files
shvipinsean-jc
authored andcommitted
KVM: x86/mmu: Remove KVM's MMU shrinker
Remove KVM's MMU shrinker and (almost) all of its related code, as the current implementation is very disruptive to VMs (if it ever runs), without providing any meaningful benefit[1]. Alternatively, KVM could repurpose its shrinker, e.g. to reclaim pages from the per-vCPU caches[2], but given that no one has complained about lack of TDP MMU support for the shrinker in the 3+ years since the TDP MMU was enabled by default, it's safe to say that there is likely no real use case for initiating reclaim of KVM's page tables from the shrinker. And while clever/cute, reclaiming the per-vCPU caches doesn't scale the same way that reclaiming in-use page table pages does. E.g. the amount of memory being used by a VM doesn't always directly correlate with the number vCPUs, and even when it does, reclaiming a few pages from per-vCPU caches likely won't make much of a dent in the VM's total memory usage, especially for VMs with huge amounts of memory. Lastly, if it turns out that there is a strong use case for dropping the per-vCPU caches, re-introducing the shrinker registration is trivial compared to the complexity of actually reclaiming pages from the caches. [1] https://lore.kernel.org/lkml/Y45dldZnI6OIf+a5@google.com [2] https://lore.kernel.org/kvm/20241004195540.210396-3-vipinsh@google.com Suggested-by: Sean Christopherson <seanjc@google.com> Suggested-by: David Matlack <dmatlack@google.com> Signed-off-by: Vipin Sharma <vipinsh@google.com> Link: https://lore.kernel.org/r/20241101201437.1604321-2-vipinsh@google.com [sean: keep zapped_obsolete_pages for now, massage changelog] Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 06c4cd9 commit fe140e6

File tree

1 file changed

+2
-103
lines changed

1 file changed

+2
-103
lines changed

arch/x86/kvm/mmu/mmu.c

Lines changed: 2 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ struct kvm_shadow_walk_iterator {
179179

180180
static struct kmem_cache *pte_list_desc_cache;
181181
struct kmem_cache *mmu_page_header_cache;
182-
static struct percpu_counter kvm_total_used_mmu_pages;
183182

184183
static void mmu_spte_set(u64 *sptep, u64 spte);
185184

@@ -1622,27 +1621,15 @@ static void kvm_mmu_check_sptes_at_free(struct kvm_mmu_page *sp)
16221621
#endif
16231622
}
16241623

1625-
/*
1626-
* This value is the sum of all of the kvm instances's
1627-
* kvm->arch.n_used_mmu_pages values. We need a global,
1628-
* aggregate version in order to make the slab shrinker
1629-
* faster
1630-
*/
1631-
static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, long nr)
1632-
{
1633-
kvm->arch.n_used_mmu_pages += nr;
1634-
percpu_counter_add(&kvm_total_used_mmu_pages, nr);
1635-
}
1636-
16371624
static void kvm_account_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
16381625
{
1639-
kvm_mod_used_mmu_pages(kvm, +1);
1626+
kvm->arch.n_used_mmu_pages++;
16401627
kvm_account_pgtable_pages((void *)sp->spt, +1);
16411628
}
16421629

16431630
static void kvm_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
16441631
{
1645-
kvm_mod_used_mmu_pages(kvm, -1);
1632+
kvm->arch.n_used_mmu_pages--;
16461633
kvm_account_pgtable_pages((void *)sp->spt, -1);
16471634
}
16481635

@@ -6492,11 +6479,6 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
64926479
kvm_tdp_mmu_zap_invalidated_roots(kvm);
64936480
}
64946481

6495-
static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)
6496-
{
6497-
return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages));
6498-
}
6499-
65006482
void kvm_mmu_init_vm(struct kvm *kvm)
65016483
{
65026484
kvm->arch.shadow_mmio_value = shadow_mmio_value;
@@ -7112,72 +7094,6 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
71127094
}
71137095
}
71147096

7115-
static unsigned long mmu_shrink_scan(struct shrinker *shrink,
7116-
struct shrink_control *sc)
7117-
{
7118-
struct kvm *kvm;
7119-
int nr_to_scan = sc->nr_to_scan;
7120-
unsigned long freed = 0;
7121-
7122-
mutex_lock(&kvm_lock);
7123-
7124-
list_for_each_entry(kvm, &vm_list, vm_list) {
7125-
int idx;
7126-
7127-
/*
7128-
* Never scan more than sc->nr_to_scan VM instances.
7129-
* Will not hit this condition practically since we do not try
7130-
* to shrink more than one VM and it is very unlikely to see
7131-
* !n_used_mmu_pages so many times.
7132-
*/
7133-
if (!nr_to_scan--)
7134-
break;
7135-
/*
7136-
* n_used_mmu_pages is accessed without holding kvm->mmu_lock
7137-
* here. We may skip a VM instance errorneosly, but we do not
7138-
* want to shrink a VM that only started to populate its MMU
7139-
* anyway.
7140-
*/
7141-
if (!kvm->arch.n_used_mmu_pages &&
7142-
!kvm_has_zapped_obsolete_pages(kvm))
7143-
continue;
7144-
7145-
idx = srcu_read_lock(&kvm->srcu);
7146-
write_lock(&kvm->mmu_lock);
7147-
7148-
if (kvm_has_zapped_obsolete_pages(kvm)) {
7149-
kvm_mmu_commit_zap_page(kvm,
7150-
&kvm->arch.zapped_obsolete_pages);
7151-
goto unlock;
7152-
}
7153-
7154-
freed = kvm_mmu_zap_oldest_mmu_pages(kvm, sc->nr_to_scan);
7155-
7156-
unlock:
7157-
write_unlock(&kvm->mmu_lock);
7158-
srcu_read_unlock(&kvm->srcu, idx);
7159-
7160-
/*
7161-
* unfair on small ones
7162-
* per-vm shrinkers cry out
7163-
* sadness comes quickly
7164-
*/
7165-
list_move_tail(&kvm->vm_list, &vm_list);
7166-
break;
7167-
}
7168-
7169-
mutex_unlock(&kvm_lock);
7170-
return freed;
7171-
}
7172-
7173-
static unsigned long mmu_shrink_count(struct shrinker *shrink,
7174-
struct shrink_control *sc)
7175-
{
7176-
return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
7177-
}
7178-
7179-
static struct shrinker *mmu_shrinker;
7180-
71817097
static void mmu_destroy_caches(void)
71827098
{
71837099
kmem_cache_destroy(pte_list_desc_cache);
@@ -7304,23 +7220,8 @@ int kvm_mmu_vendor_module_init(void)
73047220
if (!mmu_page_header_cache)
73057221
goto out;
73067222

7307-
if (percpu_counter_init(&kvm_total_used_mmu_pages, 0, GFP_KERNEL))
7308-
goto out;
7309-
7310-
mmu_shrinker = shrinker_alloc(0, "x86-mmu");
7311-
if (!mmu_shrinker)
7312-
goto out_shrinker;
7313-
7314-
mmu_shrinker->count_objects = mmu_shrink_count;
7315-
mmu_shrinker->scan_objects = mmu_shrink_scan;
7316-
mmu_shrinker->seeks = DEFAULT_SEEKS * 10;
7317-
7318-
shrinker_register(mmu_shrinker);
7319-
73207223
return 0;
73217224

7322-
out_shrinker:
7323-
percpu_counter_destroy(&kvm_total_used_mmu_pages);
73247225
out:
73257226
mmu_destroy_caches();
73267227
return ret;
@@ -7337,8 +7238,6 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
73377238
void kvm_mmu_vendor_module_exit(void)
73387239
{
73397240
mmu_destroy_caches();
7340-
percpu_counter_destroy(&kvm_total_used_mmu_pages);
7341-
shrinker_free(mmu_shrinker);
73427241
}
73437242

73447243
/*

0 commit comments

Comments
 (0)