For the device fd opened from cdev, userspace needs to bind it to an
iommufd and attach it to IOAS managed by iommufd. With such operations,
userspace can set up a secure DMA context and hence access device.

This changes the existing vfio_iommufd_bind() to accept a pt_id pointer
as an optional input, and also an dev_id pointer to selectively return
the dev_id to prepare for adding bind_iommufd ioctl, which does the bind
first and then attach IOAS.

Signed-off-by: Yi Liu <yi.l....@intel.com>
Reviewed-by: Kevin Tian <kevin.t...@intel.com>
---
 drivers/vfio/group.c     | 17 ++++++++++++++---
 drivers/vfio/iommufd.c   | 21 +++++++++------------
 drivers/vfio/vfio.h      |  9 ++++++---
 drivers/vfio/vfio_main.c | 10 ++++++----
 4 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 2abf55c69281..9f3f6f0e4942 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -169,6 +169,7 @@ static void vfio_device_group_get_kvm_safe(struct 
vfio_device *device)
 static int vfio_device_group_open(struct vfio_device_file *df)
 {
        struct vfio_device *device = df->device;
+       u32 ioas_id;
        int ret;
 
        mutex_lock(&device->group->group_lock);
@@ -177,6 +178,13 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
                goto out_unlock;
        }
 
+       if (device->group->iommufd) {
+               ret = iommufd_vfio_compat_ioas_id(device->group->iommufd,
+                                                 &ioas_id);
+               if (ret)
+                       goto out_unlock;
+       }
+
        mutex_lock(&device->dev_set->lock);
 
        /*
@@ -188,9 +196,12 @@ static int vfio_device_group_open(struct vfio_device_file 
*df)
        if (device->open_count == 0)
                vfio_device_group_get_kvm_safe(device);
 
-       df->iommufd = device->group->iommufd;
-
-       ret = vfio_device_open(df);
+       if (device->group->iommufd) {
+               df->iommufd = device->group->iommufd;
+               ret = vfio_device_open(df, NULL, &ioas_id);
+       } else {
+               ret = vfio_device_open(df, NULL, NULL);
+       }
        if (ret)
                df->iommufd = NULL;
 
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 4f82a6fa7c6c..beef6ca21107 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -10,9 +10,9 @@
 MODULE_IMPORT_NS(IOMMUFD);
 MODULE_IMPORT_NS(IOMMUFD_VFIO);
 
-int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
+int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx,
+                     u32 *dev_id, u32 *pt_id)
 {
-       u32 ioas_id;
        u32 device_id;
        int ret;
 
@@ -29,17 +29,14 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct 
iommufd_ctx *ictx)
        if (ret)
                return ret;
 
-       ret = iommufd_vfio_compat_ioas_id(ictx, &ioas_id);
-       if (ret)
-               goto err_unbind;
-       ret = vdev->ops->attach_ioas(vdev, &ioas_id);
-       if (ret)
-               goto err_unbind;
+       if (pt_id) {
+               ret = vdev->ops->attach_ioas(vdev, pt_id);
+               if (ret)
+                       goto err_unbind;
+       }
 
-       /*
-        * The legacy path has no way to return the device id or the selected
-        * pt_id
-        */
+       if (dev_id)
+               *dev_id = device_id;
        return 0;
 
 err_unbind:
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index d56cdb114024..6f063e31d08a 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -26,7 +26,8 @@ struct vfio_device_file {
 
 void vfio_device_put_registration(struct vfio_device *device);
 bool vfio_device_try_get_registration(struct vfio_device *device);
-int vfio_device_open(struct vfio_device_file *df);
+int vfio_device_open(struct vfio_device_file *df,
+                    u32 *dev_id, u32 *pt_id);
 void vfio_device_close(struct vfio_device_file *df);
 struct vfio_device_file *
 vfio_allocate_device_file(struct vfio_device *device);
@@ -224,11 +225,13 @@ static inline void vfio_container_cleanup(void)
 #endif
 
 #if IS_ENABLED(CONFIG_IOMMUFD)
-int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx);
+int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx,
+                     u32 *dev_id, u32 *pt_id);
 void vfio_iommufd_unbind(struct vfio_device *device);
 #else
 static inline int vfio_iommufd_bind(struct vfio_device *device,
-                                   struct iommufd_ctx *ictx)
+                                   struct iommufd_ctx *ictx,
+                                   u32 *dev_id, u32 *pt_id)
 {
        return -EOPNOTSUPP;
 }
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 2267057240bd..b40c2d95f693 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -411,7 +411,8 @@ vfio_allocate_device_file(struct vfio_device *device)
        return df;
 }
 
-static int vfio_device_first_open(struct vfio_device_file *df)
+static int vfio_device_first_open(struct vfio_device_file *df,
+                                 u32 *dev_id, u32 *pt_id)
 {
        struct vfio_device *device = df->device;
        struct iommufd_ctx *iommufd = df->iommufd;
@@ -423,7 +424,7 @@ static int vfio_device_first_open(struct vfio_device_file 
*df)
                return -ENODEV;
 
        if (iommufd)
-               ret = vfio_iommufd_bind(device, iommufd);
+               ret = vfio_iommufd_bind(device, iommufd, dev_id, pt_id);
        else
                ret = vfio_device_group_use_iommu(device);
        if (ret)
@@ -462,7 +463,8 @@ static void vfio_device_last_close(struct vfio_device_file 
*df)
        module_put(device->dev->driver->owner);
 }
 
-int vfio_device_open(struct vfio_device_file *df)
+int vfio_device_open(struct vfio_device_file *df,
+                    u32 *dev_id, u32 *pt_id)
 {
        struct vfio_device *device = df->device;
        int ret = 0;
@@ -471,7 +473,7 @@ int vfio_device_open(struct vfio_device_file *df)
 
        device->open_count++;
        if (device->open_count == 1) {
-               ret = vfio_device_first_open(df);
+               ret = vfio_device_first_open(df, dev_id, pt_id);
                if (ret)
                        device->open_count--;
        }
-- 
2.34.1

Reply via email to