@@ -16,6 +16,7 @@
#include <linux/mutex.h>
#include <linux/bug.h>
#include <uapi/linux/iommufd.h>
+#include <linux/iommu.h>
#include <linux/iommufd.h>
#include "io_pagetable.h"
@@ -427,11 +428,50 @@ static long iommufd_fops_ioctl(struct file *filp, unsigned int cmd,
return ret;
}
+static int iommufd_fops_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct iommufd_ctx *ictx = filp->private_data;
+ size_t size = vma->vm_end - vma->vm_start;
+ u32 viommu_id = (u32)vma->vm_pgoff;
+ struct iommufd_viommu *viommu;
+ unsigned long pfn;
+ int rc;
+
+ if (size > PAGE_SIZE)
+ return -EINVAL;
+
+ viommu = container_of(iommufd_get_object(ictx, viommu_id,
+ IOMMUFD_OBJ_VIOMMU),
+ struct iommufd_viommu, obj);
+ if (IS_ERR(viommu))
+ return PTR_ERR(viommu);
+
+ if (!viommu->ops->get_mmap_pfn) {
+ rc = -EOPNOTSUPP;
+ goto out_put_viommu;
+ }
+
+ pfn = viommu->ops->get_mmap_pfn(viommu, size);
+ if (!pfn) {
+ rc = -ENOMEM;
+ goto out_put_viommu;
+ }
+
+ vma->vm_pgoff = 0;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
+ rc = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
+out_put_viommu:
+ iommufd_put_object(ictx, &viommu->obj);
+ return rc;
+}
+
static const struct file_operations iommufd_fops = {
.owner = THIS_MODULE,
.open = iommufd_fops_open,
.release = iommufd_fops_release,
.unlocked_ioctl = iommufd_fops_ioctl,
+ .mmap = iommufd_fops_mmap,
};
/**
@@ -104,6 +104,8 @@ struct iommufd_viommu {
* the include/uapi/linux/iommufd.h header.
* @vqueue_free: Free all driver-specific parts of an iommufd_vqueue. The memory
* of the iommufd_vqueue will be free-ed by iommufd core
+ * @get_mmap_pfn: Return the PFN of a viommu given a finite size, for user space
+ * to mmap the page(s).
*/
struct iommufd_viommu_ops {
void (*free)(struct iommufd_viommu *viommu);
@@ -114,6 +116,8 @@ struct iommufd_viommu_ops {
struct iommufd_viommu *viommu,
const struct iommu_user_data *user_data);
void (*vqueue_free)(struct iommufd_vqueue *vqueue);
+ unsigned long (*get_mmap_pfn)(struct iommufd_viommu *viommu,
+ size_t pgsize);
};
struct iommufd_vqueue {
Add for sharing the kernel page with user space. This allows to pass through HW resource (VCMDQ MMIO pages for example) to user space VMM and guest OS. Use vma->vm_pgoff as the carrier of a viommu_id. Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> --- drivers/iommu/iommufd/main.c | 40 ++++++++++++++++++++++++++++++++++++ include/linux/iommufd.h | 4 ++++ 2 files changed, 44 insertions(+)