Commit 44ebaa17 authored by Jason Gunthorpe's avatar Jason Gunthorpe
Browse files

iommufd: Accept a DMABUF through IOMMU_IOAS_MAP_FILE

Finally call iopt_alloc_dmabuf_pages() if the user passed in a DMABUF
through IOMMU_IOAS_MAP_FILE. This makes the feature visible to userspace.

Link: https://patch.msgid.link/r/8-v2-b2c110338e3f+5c2-iommufd_dmabuf_jgg@nvidia.com


Reviewed-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Tested-by: default avatarShuai Xue <xueshuai@linux.alibaba.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 217725f0
Loading
Loading
Loading
Loading
+33 −10
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 * The datastructure uses the iopt_pages to optimize the storage of the PFNs
 * between the domains and xarray.
 */
#include <linux/dma-buf.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/file.h>
@@ -484,19 +485,41 @@ int iopt_map_file_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
			unsigned int flags)
{
	struct iopt_pages *pages;
	struct dma_buf *dmabuf;
	unsigned long start_byte;
	unsigned long last;

	if (!length)
		return -EINVAL;
	if (check_add_overflow(start, length - 1, &last))
		return -EOVERFLOW;

	start_byte = start - ALIGN_DOWN(start, PAGE_SIZE);
	dmabuf = dma_buf_get(fd);
	if (!IS_ERR(dmabuf)) {
		pages = iopt_alloc_dmabuf_pages(ictx, dmabuf, start_byte, start,
						length,
						iommu_prot & IOMMU_WRITE);
		if (IS_ERR(pages)) {
			dma_buf_put(dmabuf);
			return PTR_ERR(pages);
		}
	} else {
		struct file *file;

		file = fget(fd);
		if (!file)
			return -EBADF;

	pages = iopt_alloc_file_pages(file, start, length,
		pages = iopt_alloc_file_pages(file, start_byte, start, length,
					      iommu_prot & IOMMU_WRITE);
		fput(file);
		if (IS_ERR(pages))
			return PTR_ERR(pages);
	}

	return iopt_map_common(ictx, iopt, pages, iova, length,
			       start - pages->start, iommu_prot, flags);
			       start_byte, iommu_prot, flags);
}

struct iova_bitmap_fn_arg {
+3 −1
Original line number Diff line number Diff line
@@ -265,7 +265,9 @@ static inline bool iopt_dmabuf_revoked(struct iopt_pages *pages)

struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
					 unsigned long length, bool writable);
struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
struct iopt_pages *iopt_alloc_file_pages(struct file *file,
					 unsigned long start_byte,
					 unsigned long start,
					 unsigned long length, bool writable);
struct iopt_pages *iopt_alloc_dmabuf_pages(struct iommufd_ctx *ictx,
					   struct dma_buf *dmabuf,
+5 −8
Original line number Diff line number Diff line
@@ -1413,22 +1413,19 @@ struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
	return pages;
}

struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
struct iopt_pages *iopt_alloc_file_pages(struct file *file,
					 unsigned long start_byte,
					 unsigned long start,
					 unsigned long length, bool writable)

{
	struct iopt_pages *pages;
	unsigned long start_down = ALIGN_DOWN(start, PAGE_SIZE);
	unsigned long end;

	if (length && check_add_overflow(start, length - 1, &end))
		return ERR_PTR(-EOVERFLOW);

	pages = iopt_alloc_pages(start - start_down, length, writable);
	pages = iopt_alloc_pages(start_byte, length, writable);
	if (IS_ERR(pages))
		return pages;
	pages->file = get_file(file);
	pages->start = start_down;
	pages->start = start - start_byte;
	pages->type = IOPT_ADDRESS_FILE;
	return pages;
}