aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-04-11 11:51:49 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2012-04-11 21:55:25 -0400
commit32f6daad4651a748a58a3ab6da0611862175722f (patch)
tree09e2643d6df18db1ab7655fcb53ab797e9ac69c1 /virt/kvm/kvm_main.c
parentf19a0c2c2e6add90b7d6a1b7595abebfe2e4c37a (diff)
KVM: unmap pages from the iommu when slots are removed
We've been adding new mappings, but not destroying old mappings. This can lead to a page leak as pages are pinned using get_user_pages, but only unpinned with put_page if they still exist in the memslots list on vm shutdown. A memslot that is destroyed while an iommu domain is enabled for the guest will therefore result in an elevated page reference count that is never cleared. Additionally, without this fix, the iommu is only programmed with the first translation for a gpa. This can result in peer-to-peer errors if a mapping is destroyed and replaced by a new mapping at the same gpa as the iommu will still be pointing to the original, pinned memory address. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 42b73930a6de..9739b533ca2e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm,
808 if (r) 808 if (r)
809 goto out_free; 809 goto out_free;
810 810
811 /* map the pages in iommu page table */ 811 /* map/unmap the pages in iommu page table */
812 if (npages) { 812 if (npages) {
813 r = kvm_iommu_map_pages(kvm, &new); 813 r = kvm_iommu_map_pages(kvm, &new);
814 if (r) 814 if (r)
815 goto out_free; 815 goto out_free;
816 } 816 } else
817 kvm_iommu_unmap_pages(kvm, &old);
817 818
818 r = -ENOMEM; 819 r = -ENOMEM;
819 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), 820 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),