vfio: Fix an incorrect break out of nested loop in iommu mapping code.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) iQIcBAABAgAGBQJSXEKXAAoJECObm247sIsiMVgP/0P9+2UC2HS8pdCN4UnaC2RW zUdDwyEZ9T5uT1l9rseI7pjVSbdbXt6MW+UFPE8h6SqRdr6udzfLGFE8IuHOoKmk pVQfkaHAsQLY7O+bfXpGM0liyNDGXfDfyxE1HJtn79Ggnc3ek0tUFUaSNZgHDTYH O9QWG3g6mTb/NpHjFgHlGnyulUhDNdcnvOfczk8PWnSHRKHeAhEoFE1EEkfQGm4a X5SlYEBTmK/86FKptdC0Zaq2saIxdHR3lJVIn6S19rejXHqJ7zz8hZhYmJD9kg7P nq11zwWeC0S2Izvls9Xb6Akxom4w5uoz9oOgUbu7abTI2QIABe2SBVKibdqTgq9e FShxUNKLwW0Zh3DQ/5MNFpxrUJI7+NECy5QImfXKDhXDaDwBmE0JgFQ+o+UNB9vI TFptJVdoahVz2Wp6M/5hMyR4Ol0XCQQijYnsqWlsAsJQr98a7qQU4aUTt64CgAJ0 eYPj0CqvP+1sV8x7n3xdK6C0eaHEJd7n68VlmnBzxzeBZHJ87PIR/3txy5AmYVXp 3s9hr7g5zhMK+6U5DPlEUmeCKoh+53Ub5hbi0Cw7/3nI/NSnvKxQXKdBtN4B+TpT QpyA6bLTy0qVgd2rvntqOv8lgSVumC5BoaSVHMy90xxDS1UHEa0M96+RQkiE/QGX fB3a1NIrd8l6uv52lkui =M8E+ -----END PGP SIGNATURE----- Merge tag 'vfio-v3.12-rc5' of git://github.com/awilliam/linux-vfio Pull vfio fix from Alex Williamson: "Fix an incorrect break out of nested loop in iommu mapping code" * tag 'vfio-v3.12-rc5' of git://github.com/awilliam/linux-vfio: VFIO: vfio_iommu_type1: fix bug caused by break in nested loop
This commit is contained in:
commit
1e52db6908
|
@ -545,6 +545,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
long npage;
|
long npage;
|
||||||
int ret = 0, prot = 0;
|
int ret = 0, prot = 0;
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
|
struct vfio_dma *dma = NULL;
|
||||||
|
unsigned long pfn;
|
||||||
|
|
||||||
end = map->iova + map->size;
|
end = map->iova + map->size;
|
||||||
|
|
||||||
|
@ -587,8 +589,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iova = map->iova; iova < end; iova += size, vaddr += size) {
|
for (iova = map->iova; iova < end; iova += size, vaddr += size) {
|
||||||
struct vfio_dma *dma = NULL;
|
|
||||||
unsigned long pfn;
|
|
||||||
long i;
|
long i;
|
||||||
|
|
||||||
/* Pin a contiguous chunk of memory */
|
/* Pin a contiguous chunk of memory */
|
||||||
|
@ -597,16 +597,15 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
if (npage <= 0) {
|
if (npage <= 0) {
|
||||||
WARN_ON(!npage);
|
WARN_ON(!npage);
|
||||||
ret = (int)npage;
|
ret = (int)npage;
|
||||||
break;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify pages are not already mapped */
|
/* Verify pages are not already mapped */
|
||||||
for (i = 0; i < npage; i++) {
|
for (i = 0; i < npage; i++) {
|
||||||
if (iommu_iova_to_phys(iommu->domain,
|
if (iommu_iova_to_phys(iommu->domain,
|
||||||
iova + (i << PAGE_SHIFT))) {
|
iova + (i << PAGE_SHIFT))) {
|
||||||
vfio_unpin_pages(pfn, npage, prot, true);
|
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
break;
|
goto out_unpin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,8 +615,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret != -EBUSY ||
|
if (ret != -EBUSY ||
|
||||||
map_try_harder(iommu, iova, pfn, npage, prot)) {
|
map_try_harder(iommu, iova, pfn, npage, prot)) {
|
||||||
vfio_unpin_pages(pfn, npage, prot, true);
|
goto out_unpin;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,9 +670,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
dma = kzalloc(sizeof(*dma), GFP_KERNEL);
|
dma = kzalloc(sizeof(*dma), GFP_KERNEL);
|
||||||
if (!dma) {
|
if (!dma) {
|
||||||
iommu_unmap(iommu->domain, iova, size);
|
iommu_unmap(iommu->domain, iova, size);
|
||||||
vfio_unpin_pages(pfn, npage, prot, true);
|
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
break;
|
goto out_unpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
dma->size = size;
|
dma->size = size;
|
||||||
|
@ -685,16 +682,21 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
WARN_ON(ret);
|
||||||
struct vfio_dma *tmp;
|
mutex_unlock(&iommu->lock);
|
||||||
iova = map->iova;
|
return ret;
|
||||||
size = map->size;
|
|
||||||
while ((tmp = vfio_find_dma(iommu, iova, size))) {
|
out_unpin:
|
||||||
int r = vfio_remove_dma_overlap(iommu, iova,
|
vfio_unpin_pages(pfn, npage, prot, true);
|
||||||
&size, tmp);
|
|
||||||
if (WARN_ON(r || !size))
|
out:
|
||||||
break;
|
iova = map->iova;
|
||||||
}
|
size = map->size;
|
||||||
|
while ((dma = vfio_find_dma(iommu, iova, size))) {
|
||||||
|
int r = vfio_remove_dma_overlap(iommu, iova,
|
||||||
|
&size, dma);
|
||||||
|
if (WARN_ON(r || !size))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&iommu->lock);
|
mutex_unlock(&iommu->lock);
|
||||||
|
|
Loading…
Reference in New Issue