aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-06-05 05:17:03 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-16 05:05:45 -0400
commit7b53aa56508479507c6e5667bb252ca7c2cd19cf (patch)
treed2020d70e6578f0d6405cba3f3b5a1ccdc62a581
parent313899477f7578d37e82ead1af10f794a6da3c90 (diff)
KVM: Fix vcpu freeing for guest smp
A vcpu can pin up to four mmu shadow pages, which means the freeing loop will never terminate. Fix by first unpinning shadow pages on all vcpus, then freeing shadow pages. Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/kvm_main.c15
-rw-r--r--drivers/kvm/mmu.c4
2 files changed, 17 insertions, 2 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 3c3231d8dabf..3ff8ee56279c 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -381,6 +381,16 @@ static void free_pio_guest_pages(struct kvm_vcpu *vcpu)
381 } 381 }
382} 382}
383 383
384static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
385{
386 if (!vcpu->vmcs)
387 return;
388
389 vcpu_load(vcpu);
390 kvm_mmu_unload(vcpu);
391 vcpu_put(vcpu);
392}
393
384static void kvm_free_vcpu(struct kvm_vcpu *vcpu) 394static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
385{ 395{
386 if (!vcpu->vmcs) 396 if (!vcpu->vmcs)
@@ -401,6 +411,11 @@ static void kvm_free_vcpus(struct kvm *kvm)
401{ 411{
402 unsigned int i; 412 unsigned int i;
403 413
414 /*
415 * Unpin any mmu pages first.
416 */
417 for (i = 0; i < KVM_MAX_VCPUS; ++i)
418 kvm_unload_vcpu_mmu(&kvm->vcpus[i]);
404 for (i = 0; i < KVM_MAX_VCPUS; ++i) 419 for (i = 0; i < KVM_MAX_VCPUS; ++i)
405 kvm_free_vcpu(&kvm->vcpus[i]); 420 kvm_free_vcpu(&kvm->vcpus[i]);
406} 421}
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 5915d7a1c4f7..d4de988d1828 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -838,11 +838,12 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
838 int i; 838 int i;
839 struct kvm_mmu_page *page; 839 struct kvm_mmu_page *page;
840 840
841 if (!VALID_PAGE(vcpu->mmu.root_hpa))
842 return;
841#ifdef CONFIG_X86_64 843#ifdef CONFIG_X86_64
842 if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) { 844 if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
843 hpa_t root = vcpu->mmu.root_hpa; 845 hpa_t root = vcpu->mmu.root_hpa;
844 846
845 ASSERT(VALID_PAGE(root));
846 page = page_header(root); 847 page = page_header(root);
847 --page->root_count; 848 --page->root_count;
848 vcpu->mmu.root_hpa = INVALID_PAGE; 849 vcpu->mmu.root_hpa = INVALID_PAGE;
@@ -853,7 +854,6 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
853 hpa_t root = vcpu->mmu.pae_root[i]; 854 hpa_t root = vcpu->mmu.pae_root[i];
854 855
855 if (root) { 856 if (root) {
856 ASSERT(VALID_PAGE(root));
857 root &= PT64_BASE_ADDR_MASK; 857 root &= PT64_BASE_ADDR_MASK;
858 page = page_header(root); 858 page = page_header(root);
859 --page->root_count; 859 --page->root_count;