add a new transient operations for ioctl & mmap that allows using the new mmap maple tree, since these operations are used extensively, it's better to transition into new temporary ops, then after onboarding all the users to the new ops we will drop the old legacy ops proto and replace it with the new ones. Having new ops allows us to enforce the vmmap existence check when mmap ops is called, and make the migration more stable, and reviewable. ioctl needs to have access over the whole mt to add/query entries when needed, this allows inserting new range in the mt for example when DEVICE_GET_REGION_INFO is called by the user, this also enabled us to add other uapi to change mmap attrs in a certain range. When mmapping there must be a vmmap entry for that offset otherwise return -EINVAL. Signed-off-by: Mahmoud Adam --- This names is only used for the migration period that was I used 2 as a suffix, maybe _vmmap could also be used or similar. drivers/vfio/vfio_main.c | 12 ++++++++++++ include/linux/vfio.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 4c4af4de60d12..3275ff56eef47 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -1324,6 +1324,10 @@ static long vfio_device_fops_unl_ioctl(struct file *filep, break; default: + if (device->ops->ioctl2) { + ret = device->ops->ioctl2(device, cmd, arg, &df->mmap_mt); + break; + } if (unlikely(!device->ops->ioctl)) ret = -EINVAL; else @@ -1372,11 +1376,19 @@ static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma) { struct vfio_device_file *df = filep->private_data; struct vfio_device *device = df->device; + struct vfio_mmap *vmmap; /* Paired with smp_store_release() following vfio_df_open() */ if (!smp_load_acquire(&df->access_granted)) return -EINVAL; + if (device->ops->mmap2) { + vmmap = mtree_load(&df->mmap_mt, (vma->vm_pgoff << PAGE_SHIFT)); + if (!vmmap) + return -EINVAL; + return device->ops->mmap2(device, vma, vmmap); + } + if (unlikely(!device->ops->mmap)) return -EINVAL; diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 6e0aca05aa406..836ef72a38104 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -142,7 +142,11 @@ struct vfio_device_ops { size_t count, loff_t *size); long (*ioctl)(struct vfio_device *vdev, unsigned int cmd, unsigned long arg); + long (*ioctl2)(struct vfio_device *vdev, unsigned int cmd, + unsigned long arg, struct maple_tree *mmap_mt); int (*mmap)(struct vfio_device *vdev, struct vm_area_struct *vma); + int (*mmap2)(struct vfio_device *vdev, struct vm_area_struct *vma, + struct vfio_mmap *vmmap); void (*request)(struct vfio_device *vdev, unsigned int count); int (*match)(struct vfio_device *vdev, char *buf); void (*dma_unmap)(struct vfio_device *vdev, u64 iova, u64 length); -- 2.47.3 Amazon Web Services Development Center Germany GmbH Tamara-Danz-Str. 13 10243 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B Sitz: Berlin Ust-ID: DE 365 538 597