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: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Shuai Xue <xueshuai@linux.alibaba.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Jason Gunthorpe 2025-11-21 11:51:05 -04:00
parent 217725f0b2
commit 44ebaa1744
3 changed files with 41 additions and 19 deletions

View File

@ -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 file *file;
struct dma_buf *dmabuf;
unsigned long start_byte;
unsigned long last;
file = fget(fd);
if (!file)
return -EBADF;
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_byte, start, length,
iommu_prot & IOMMU_WRITE);
fput(file);
if (IS_ERR(pages))
return PTR_ERR(pages);
}
pages = iopt_alloc_file_pages(file, 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 {

View File

@ -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,

View File

@ -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;
}