KVM: MMU: handle n_free_mmu_pages > n_alloc_mmu_pages in kvm_mmu_change_mmu_pages

kvm_mmu_change_mmu_pages mishandles the case where n_alloc_mmu_pages is
smaller then n_free_mmu_pages, by not checking if the result of
the subtraction is negative.

Its a valid condition which can happen if a large number of pages has
been recently freed.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>

authored by Marcelo Tosatti and committed by Avi Kivity 025dbbf3 4b656b12

+8 -7
+8 -7
arch/x86/kvm/mmu.c
··· 1407 */ 1408 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages) 1409 { 1410 /* 1411 * If we set the number of mmu pages to be smaller be than the 1412 * number of actived pages , we must to free some mmu pages before we 1413 * change the value 1414 */ 1415 1416 - if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) > 1417 - kvm_nr_mmu_pages) { 1418 - int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages 1419 - - kvm->arch.n_free_mmu_pages; 1420 - 1421 - while (n_used_mmu_pages > kvm_nr_mmu_pages) { 1422 struct kvm_mmu_page *page; 1423 1424 page = container_of(kvm->arch.active_mmu_pages.prev, 1425 struct kvm_mmu_page, link); 1426 kvm_mmu_zap_page(kvm, page); 1427 - n_used_mmu_pages--; 1428 } 1429 kvm->arch.n_free_mmu_pages = 0; 1430 }
··· 1407 */ 1408 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages) 1409 { 1410 + int used_pages; 1411 + 1412 + used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages; 1413 + used_pages = max(0, used_pages); 1414 + 1415 /* 1416 * If we set the number of mmu pages to be smaller be than the 1417 * number of actived pages , we must to free some mmu pages before we 1418 * change the value 1419 */ 1420 1421 + if (used_pages > kvm_nr_mmu_pages) { 1422 + while (used_pages > kvm_nr_mmu_pages) { 1423 struct kvm_mmu_page *page; 1424 1425 page = container_of(kvm->arch.active_mmu_pages.prev, 1426 struct kvm_mmu_page, link); 1427 kvm_mmu_zap_page(kvm, page); 1428 + used_pages--; 1429 } 1430 kvm->arch.n_free_mmu_pages = 0; 1431 }