Loading arch/x86/kvm/mmu.c +56 −2 Original line number Diff line number Diff line Loading @@ -1966,7 +1966,53 @@ void kvm_mmu_zap_all(struct kvm *kvm) kvm_flush_remote_tlbs(kvm); } void kvm_mmu_module_exit(void) void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm) { struct kvm_mmu_page *page; page = container_of(kvm->arch.active_mmu_pages.prev, struct kvm_mmu_page, link); kvm_mmu_zap_page(kvm, page); } static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) { struct kvm *kvm; struct kvm *kvm_freed = NULL; int cache_count = 0; spin_lock(&kvm_lock); list_for_each_entry(kvm, &vm_list, vm_list) { int npages; spin_lock(&kvm->mmu_lock); npages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages; cache_count += npages; if (!kvm_freed && nr_to_scan > 0 && npages > 0) { kvm_mmu_remove_one_alloc_mmu_page(kvm); cache_count--; kvm_freed = kvm; } nr_to_scan--; spin_unlock(&kvm->mmu_lock); } if (kvm_freed) list_move_tail(&kvm_freed->vm_list, &vm_list); spin_unlock(&kvm_lock); return cache_count; } static struct shrinker mmu_shrinker = { .shrink = mmu_shrink, .seeks = DEFAULT_SEEKS * 10, }; void mmu_destroy_caches(void) { if (pte_chain_cache) kmem_cache_destroy(pte_chain_cache); Loading @@ -1976,6 +2022,12 @@ void kvm_mmu_module_exit(void) kmem_cache_destroy(mmu_page_header_cache); } void kvm_mmu_module_exit(void) { mmu_destroy_caches(); unregister_shrinker(&mmu_shrinker); } int kvm_mmu_module_init(void) { pte_chain_cache = kmem_cache_create("kvm_pte_chain", Loading @@ -1995,10 +2047,12 @@ int kvm_mmu_module_init(void) if (!mmu_page_header_cache) goto nomem; register_shrinker(&mmu_shrinker); return 0; nomem: kvm_mmu_module_exit(); mmu_destroy_caches(); return -ENOMEM; } Loading Loading
arch/x86/kvm/mmu.c +56 −2 Original line number Diff line number Diff line Loading @@ -1966,7 +1966,53 @@ void kvm_mmu_zap_all(struct kvm *kvm) kvm_flush_remote_tlbs(kvm); } void kvm_mmu_module_exit(void) void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm) { struct kvm_mmu_page *page; page = container_of(kvm->arch.active_mmu_pages.prev, struct kvm_mmu_page, link); kvm_mmu_zap_page(kvm, page); } static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) { struct kvm *kvm; struct kvm *kvm_freed = NULL; int cache_count = 0; spin_lock(&kvm_lock); list_for_each_entry(kvm, &vm_list, vm_list) { int npages; spin_lock(&kvm->mmu_lock); npages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages; cache_count += npages; if (!kvm_freed && nr_to_scan > 0 && npages > 0) { kvm_mmu_remove_one_alloc_mmu_page(kvm); cache_count--; kvm_freed = kvm; } nr_to_scan--; spin_unlock(&kvm->mmu_lock); } if (kvm_freed) list_move_tail(&kvm_freed->vm_list, &vm_list); spin_unlock(&kvm_lock); return cache_count; } static struct shrinker mmu_shrinker = { .shrink = mmu_shrink, .seeks = DEFAULT_SEEKS * 10, }; void mmu_destroy_caches(void) { if (pte_chain_cache) kmem_cache_destroy(pte_chain_cache); Loading @@ -1976,6 +2022,12 @@ void kvm_mmu_module_exit(void) kmem_cache_destroy(mmu_page_header_cache); } void kvm_mmu_module_exit(void) { mmu_destroy_caches(); unregister_shrinker(&mmu_shrinker); } int kvm_mmu_module_init(void) { pte_chain_cache = kmem_cache_create("kvm_pte_chain", Loading @@ -1995,10 +2047,12 @@ int kvm_mmu_module_init(void) if (!mmu_page_header_cache) goto nomem; register_shrinker(&mmu_shrinker); return 0; nomem: kvm_mmu_module_exit(); mmu_destroy_caches(); return -ENOMEM; } Loading