Skip to content

Commit

Permalink
KVM: lock slots_lock around device assignment
Browse files Browse the repository at this point in the history
(cherry picked from commit 21a1416)

As pointed out by Jason Baron, when assigning a device to a guest
we first set the iommu domain pointer, which enables mapping
and unmapping of memory slots to the iommu.  This leaves a window
where this path is enabled, but we haven't synchronized the iommu
mappings to the existing memory slots.  Thus a slot being removed
at that point could send us down unexpected code paths removing
non-existent pinnings and iommu mappings.  Take the slots_lock
around creating the iommu domain and initial mappings as well as
around iommu teardown to avoid this race.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
  • Loading branch information
awilliam authored and bwhacks committed May 30, 2012
1 parent 645b177 commit 50fcec9
Showing 1 changed file with 15 additions and 8 deletions.
23 changes: 15 additions & 8 deletions virt/kvm/iommu.c
Expand Up @@ -239,9 +239,13 @@ int kvm_iommu_map_guest(struct kvm *kvm)
return -ENODEV; return -ENODEV;
} }


mutex_lock(&kvm->slots_lock);

kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type); kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type);
if (!kvm->arch.iommu_domain) if (!kvm->arch.iommu_domain) {
return -ENOMEM; r = -ENOMEM;
goto out_unlock;
}


if (!allow_unsafe_assigned_interrupts && if (!allow_unsafe_assigned_interrupts &&
!iommu_domain_has_cap(kvm->arch.iommu_domain, !iommu_domain_has_cap(kvm->arch.iommu_domain,
Expand All @@ -252,17 +256,16 @@ int kvm_iommu_map_guest(struct kvm *kvm)
" module option.\n", __func__); " module option.\n", __func__);
iommu_domain_free(kvm->arch.iommu_domain); iommu_domain_free(kvm->arch.iommu_domain);
kvm->arch.iommu_domain = NULL; kvm->arch.iommu_domain = NULL;
return -EPERM; r = -EPERM;
goto out_unlock;
} }


r = kvm_iommu_map_memslots(kvm); r = kvm_iommu_map_memslots(kvm);
if (r) if (r)
goto out_unmap; kvm_iommu_unmap_memslots(kvm);

return 0;


out_unmap: out_unlock:
kvm_iommu_unmap_memslots(kvm); mutex_unlock(&kvm->slots_lock);
return r; return r;
} }


Expand Down Expand Up @@ -338,7 +341,11 @@ int kvm_iommu_unmap_guest(struct kvm *kvm)
if (!domain) if (!domain)
return 0; return 0;


mutex_lock(&kvm->slots_lock);
kvm_iommu_unmap_memslots(kvm); kvm_iommu_unmap_memslots(kvm);
kvm->arch.iommu_domain = NULL;
mutex_unlock(&kvm->slots_lock);

iommu_domain_free(domain); iommu_domain_free(domain);
return 0; return 0;
} }

0 comments on commit 50fcec9

Please sign in to comment.