diff options
author | Mark McLoughlin <markmc@redhat.com> | 2009-02-05 13:23:46 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-02-14 19:47:39 -0500 |
commit | 682edb4c01e690c7c7cd772dbd6f4e0fd74dc572 (patch) | |
tree | 21e41d8f67f3fc81df9744e91350e76b1787ec3b /virt/kvm | |
parent | b682b814e3cc340f905c14dff87ce8bdba7c5eba (diff) |
KVM: Fix assigned devices circular locking dependency
kvm->slots_lock is outer to kvm->lock, so take slots_lock
in kvm_vm_ioctl_assign_device() before taking kvm->lock,
rather than taking it in kvm_iommu_map_memslots().
Cc: stable@kernel.org
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r-- | virt/kvm/iommu.c | 6 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 3 |
2 files changed, 5 insertions, 4 deletions
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index e9693a29d00e..4c4037503600 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c | |||
@@ -73,14 +73,13 @@ static int kvm_iommu_map_memslots(struct kvm *kvm) | |||
73 | { | 73 | { |
74 | int i, r = 0; | 74 | int i, r = 0; |
75 | 75 | ||
76 | down_read(&kvm->slots_lock); | ||
77 | for (i = 0; i < kvm->nmemslots; i++) { | 76 | for (i = 0; i < kvm->nmemslots; i++) { |
78 | r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn, | 77 | r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn, |
79 | kvm->memslots[i].npages); | 78 | kvm->memslots[i].npages); |
80 | if (r) | 79 | if (r) |
81 | break; | 80 | break; |
82 | } | 81 | } |
83 | up_read(&kvm->slots_lock); | 82 | |
84 | return r; | 83 | return r; |
85 | } | 84 | } |
86 | 85 | ||
@@ -190,12 +189,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, | |||
190 | static int kvm_iommu_unmap_memslots(struct kvm *kvm) | 189 | static int kvm_iommu_unmap_memslots(struct kvm *kvm) |
191 | { | 190 | { |
192 | int i; | 191 | int i; |
193 | down_read(&kvm->slots_lock); | 192 | |
194 | for (i = 0; i < kvm->nmemslots; i++) { | 193 | for (i = 0; i < kvm->nmemslots; i++) { |
195 | kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn, | 194 | kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn, |
196 | kvm->memslots[i].npages); | 195 | kvm->memslots[i].npages); |
197 | } | 196 | } |
198 | up_read(&kvm->slots_lock); | ||
199 | 197 | ||
200 | return 0; | 198 | return 0; |
201 | } | 199 | } |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d9bbb20f230f..29a667ce35b0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -466,6 +466,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, | |||
466 | struct kvm_assigned_dev_kernel *match; | 466 | struct kvm_assigned_dev_kernel *match; |
467 | struct pci_dev *dev; | 467 | struct pci_dev *dev; |
468 | 468 | ||
469 | down_read(&kvm->slots_lock); | ||
469 | mutex_lock(&kvm->lock); | 470 | mutex_lock(&kvm->lock); |
470 | 471 | ||
471 | match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, | 472 | match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, |
@@ -527,6 +528,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, | |||
527 | 528 | ||
528 | out: | 529 | out: |
529 | mutex_unlock(&kvm->lock); | 530 | mutex_unlock(&kvm->lock); |
531 | up_read(&kvm->slots_lock); | ||
530 | return r; | 532 | return r; |
531 | out_list_del: | 533 | out_list_del: |
532 | list_del(&match->list); | 534 | list_del(&match->list); |
@@ -538,6 +540,7 @@ out_put: | |||
538 | out_free: | 540 | out_free: |
539 | kfree(match); | 541 | kfree(match); |
540 | mutex_unlock(&kvm->lock); | 542 | mutex_unlock(&kvm->lock); |
543 | up_read(&kvm->slots_lock); | ||
541 | return r; | 544 | return r; |
542 | } | 545 | } |
543 | #endif | 546 | #endif |