[v4,4/5] vduse: Add file operation for mmap
Commit Message
Add the operation for mmap, This function will be used by the user space
application to map the pages to the user space.
Signed-off-by: Cindy Lu <lulu@redhat.com>
---
drivers/vdpa/vdpa_user/vduse_dev.c | 57 ++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
@@ -1465,6 +1465,61 @@ static struct vduse_dev *vduse_dev_get_from_minor(int minor)
return dev;
}
+static vm_fault_t vduse_vm_fault(struct vm_fault *vmf)
+{
+ struct vduse_dev *dev = vmf->vma->vm_file->private_data;
+ struct vm_area_struct *vma = vmf->vma;
+ u16 index = vma->vm_pgoff;
+ struct vduse_virtqueue *vq;
+ unsigned long vaddr;
+
+ /* index 1+vq_number page reserved for virtqueue state*/
+ vq = dev->vqs[index];
+ vaddr = vq->vdpa_reconnect_vaddr;
+ if (remap_pfn_range(vma, vmf->address & PAGE_MASK,
+ PFN_DOWN(virt_to_phys((void *)vaddr)), PAGE_SIZE,
+ vma->vm_page_prot))
+ return VM_FAULT_SIGBUS;
+ return VM_FAULT_NOPAGE;
+}
+
+static const struct vm_operations_struct vduse_vm_ops = {
+ .fault = vduse_vm_fault,
+};
+
+static int vduse_dev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct vduse_dev *dev = file->private_data;
+ unsigned long vaddr = 0;
+ unsigned long index = vma->vm_pgoff;
+ struct vduse_virtqueue *vq;
+
+ if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+ return -EINVAL;
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
+ if (index > dev->vq_num)
+ return -EINVAL;
+
+ vq = dev->vqs[index];
+ vaddr = vq->vdpa_reconnect_vaddr;
+ if (vaddr == 0)
+ return -EOPNOTSUPP;
+
+ if (virt_to_phys((void *)vaddr) & (PAGE_SIZE - 1))
+ return -EINVAL;
+
+ /* Check if the Userspace App mapped the correct size */
+ if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+ return -EOPNOTSUPP;
+
+ vm_flags_set(vma, VM_DONTEXPAND);
+ vma->vm_ops = &vduse_vm_ops;
+
+ return 0;
+}
+
static int vduse_dev_open(struct inode *inode, struct file *file)
{
int ret;
@@ -1497,6 +1552,8 @@ static const struct file_operations vduse_dev_fops = {
.unlocked_ioctl = vduse_dev_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.llseek = noop_llseek,
+ .mmap = vduse_dev_mmap,
+
};
static ssize_t irq_cb_affinity_show(struct vduse_virtqueue *vq, char *buf)