Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e52db69 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents ed8ada39 d93b3ac0
Loading
Loading
Loading
Loading
+21 −19
Original line number Original line Diff line number Diff line
@@ -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,17 +682,22 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
		}
		}
	}
	}


	if (ret) {
	WARN_ON(ret);
		struct vfio_dma *tmp;
	mutex_unlock(&iommu->lock);
	return ret;

out_unpin:
	vfio_unpin_pages(pfn, npage, prot, true);

out:
	iova = map->iova;
	iova = map->iova;
	size = map->size;
	size = map->size;
		while ((tmp = vfio_find_dma(iommu, iova, size))) {
	while ((dma = vfio_find_dma(iommu, iova, size))) {
		int r = vfio_remove_dma_overlap(iommu, iova,
		int r = vfio_remove_dma_overlap(iommu, iova,
							&size, tmp);
						&size, dma);
		if (WARN_ON(r || !size))
		if (WARN_ON(r || !size))
			break;
			break;
	}
	}
	}


	mutex_unlock(&iommu->lock);
	mutex_unlock(&iommu->lock);
	return ret;
	return ret;