KVM: Fix iommu map/unmap to handle memory slot moves
[pandora-kernel.git] / virt / kvm / kvm_main.c
index a311660..d83aa5e 100644 (file)
@@ -788,6 +788,8 @@ skip_lpage:
                old_memslots = kvm->memslots;
                rcu_assign_pointer(kvm->memslots, slots);
                synchronize_srcu_expedited(&kvm->srcu);
+               /* slot was deleted or moved, clear iommu mapping */
+               kvm_iommu_unmap_pages(kvm, &old);
                /* From this point no new shadow pages pointing to a deleted,
                 * or moved, memslot will be created.
                 *
@@ -803,14 +805,6 @@ skip_lpage:
        if (r)
                goto out_free;
 
-       /* map/unmap the pages in iommu page table */
-       if (npages) {
-               r = kvm_iommu_map_pages(kvm, &new);
-               if (r)
-                       goto out_free;
-       } else
-               kvm_iommu_unmap_pages(kvm, &old);
-
        r = -ENOMEM;
        slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
        if (!slots)
@@ -820,6 +814,13 @@ skip_lpage:
                slots->nmemslots = mem->slot + 1;
        slots->generation++;
 
+       /* map new memory slot into the iommu */
+       if (npages) {
+               r = kvm_iommu_map_pages(kvm, &new);
+               if (r)
+                       goto out_slots;
+       }
+
        /* actual memory is freed via old in kvm_free_physmem_slot below */
        if (!npages) {
                new.rmap = NULL;
@@ -847,6 +848,8 @@ skip_lpage:
 
        return 0;
 
+out_slots:
+       kfree(slots);
 out_free:
        kvm_free_physmem_slot(&new, &old);
 out: