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@xxxxxxxxxx> --- drivers/iommu/iommufd/main.c | 40 ++++++++++++++++++++++++++++++++++++ include/linux/iommufd.h | 4 ++++ 2 files changed, 44 insertions(+) diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c index 96ef81530809..5b401c80cca8 100644 --- a/drivers/iommu/iommufd/main.c +++ b/drivers/iommu/iommufd/main.c @@ -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, }; /** diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h index 707b6d4b20a3..4a9c6b281d35 100644 --- a/include/linux/iommufd.h +++ b/include/linux/iommufd.h @@ -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 { -- 2.43.0