aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAlex Williamson2012-12-10 11:32:57 -0600
committerMarcelo Tosatti2012-12-13 19:21:52 -0600
commite40f193f5bb022e927a57a4f5d5194e4f12ddb74 (patch)
treeb40ba3bafaf75eb6f27e41164b213cda708c7605 /virt
parent9c695d42dbd465bcaa865603b411a73c60e60978 (diff)
downloadam43-linux-kernel-e40f193f5bb022e927a57a4f5d5194e4f12ddb74.tar.gz
am43-linux-kernel-e40f193f5bb022e927a57a4f5d5194e4f12ddb74.tar.xz
am43-linux-kernel-e40f193f5bb022e927a57a4f5d5194e4f12ddb74.zip
KVM: Fix iommu map/unmap to handle memory slot moves
The iommu integration into memory slots expects memory slots to be added or removed and doesn't handle the move case. We can unmap slots from the iommu after we mark them invalid and map them before installing the final memslot array. Also re-order the kmemdup vs map so we don't leave iommu mappings if we get ENOMEM. Reviewed-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index e4d358195e5..9a56ca2fa25 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -822,6 +822,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
822 old_memslots = kvm->memslots; 822 old_memslots = kvm->memslots;
823 rcu_assign_pointer(kvm->memslots, slots); 823 rcu_assign_pointer(kvm->memslots, slots);
824 synchronize_srcu_expedited(&kvm->srcu); 824 synchronize_srcu_expedited(&kvm->srcu);
825 /* slot was deleted or moved, clear iommu mapping */
826 kvm_iommu_unmap_pages(kvm, &old);
825 /* From this point no new shadow pages pointing to a deleted, 827 /* From this point no new shadow pages pointing to a deleted,
826 * or moved, memslot will be created. 828 * or moved, memslot will be created.
827 * 829 *
@@ -837,20 +839,19 @@ int __kvm_set_memory_region(struct kvm *kvm,
837 if (r) 839 if (r)
838 goto out_free; 840 goto out_free;
839 841
840 /* map/unmap the pages in iommu page table */
841 if (npages) {
842 r = kvm_iommu_map_pages(kvm, &new);
843 if (r)
844 goto out_free;
845 } else
846 kvm_iommu_unmap_pages(kvm, &old);
847
848 r = -ENOMEM; 842 r = -ENOMEM;
849 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), 843 slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
850 GFP_KERNEL); 844 GFP_KERNEL);
851 if (!slots) 845 if (!slots)
852 goto out_free; 846 goto out_free;
853 847
848 /* map new memory slot into the iommu */
849 if (npages) {
850 r = kvm_iommu_map_pages(kvm, &new);
851 if (r)
852 goto out_slots;
853 }
854
854 /* actual memory is freed via old in kvm_free_physmem_slot below */ 855 /* actual memory is freed via old in kvm_free_physmem_slot below */
855 if (!npages) { 856 if (!npages) {
856 new.dirty_bitmap = NULL; 857 new.dirty_bitmap = NULL;
@@ -869,6 +870,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
869 870
870 return 0; 871 return 0;
871 872
873out_slots:
874 kfree(slots);
872out_free: 875out_free:
873 kvm_free_physmem_slot(&new, &old); 876 kvm_free_physmem_slot(&new, &old);
874out: 877out: