Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / virt / kvm / iommu.c
index a195c07..5dbb35d 100644 (file)
@@ -101,6 +101,10 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
                while ((gfn << PAGE_SHIFT) & (page_size - 1))
                        page_size >>= 1;
 
+               /* Make sure hva is aligned to the page size we want to map */
+               while (gfn_to_hva_memslot(slot, gfn) & (page_size - 1))
+                       page_size >>= 1;
+
                /*
                 * Pin all pages we are about to map in memory. This is
                 * important because we unmap and unpin in 4kb steps later.
@@ -239,9 +243,13 @@ int kvm_iommu_map_guest(struct kvm *kvm)
                return -ENODEV;
        }
 
+       mutex_lock(&kvm->slots_lock);
+
        kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type);
-       if (!kvm->arch.iommu_domain)
-               return -ENOMEM;
+       if (!kvm->arch.iommu_domain) {
+               r = -ENOMEM;
+               goto out_unlock;
+       }
 
        if (!allow_unsafe_assigned_interrupts &&
            !iommu_domain_has_cap(kvm->arch.iommu_domain,
@@ -252,17 +260,16 @@ int kvm_iommu_map_guest(struct kvm *kvm)
                       " module option.\n", __func__);
                iommu_domain_free(kvm->arch.iommu_domain);
                kvm->arch.iommu_domain = NULL;
-               return -EPERM;
+               r = -EPERM;
+               goto out_unlock;
        }
 
        r = kvm_iommu_map_memslots(kvm);
        if (r)
-               goto out_unmap;
-
-       return 0;
+               kvm_iommu_unmap_memslots(kvm);
 
-out_unmap:
-       kvm_iommu_unmap_memslots(kvm);
+out_unlock:
+       mutex_unlock(&kvm->slots_lock);
        return r;
 }
 
@@ -309,6 +316,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
        }
 }
 
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+       kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages);
+}
+
 static int kvm_iommu_unmap_memslots(struct kvm *kvm)
 {
        int i, idx;
@@ -317,10 +329,9 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
        idx = srcu_read_lock(&kvm->srcu);
        slots = kvm_memslots(kvm);
 
-       for (i = 0; i < slots->nmemslots; i++) {
-               kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
-                                   slots->memslots[i].npages);
-       }
+       for (i = 0; i < slots->nmemslots; i++)
+               kvm_iommu_unmap_pages(kvm, &slots->memslots[i]);
+
        srcu_read_unlock(&kvm->srcu, idx);
 
        return 0;
@@ -334,7 +345,11 @@ int kvm_iommu_unmap_guest(struct kvm *kvm)
        if (!domain)
                return 0;
 
+       mutex_lock(&kvm->slots_lock);
        kvm_iommu_unmap_memslots(kvm);
+       kvm->arch.iommu_domain = NULL;
+       mutex_unlock(&kvm->slots_lock);
+
        iommu_domain_free(domain);
        return 0;
 }