[PATCH v6 16/24] vfio: Make vfio_device_first_open() to cover the noiommu mode in cdev path

Yi Liu
2023-03-08T13:33:00Z

vfio_device_first_open() now covers the below two cases:

1) user uses iommufd (e.g. the group path in iommufd compat mode);
2) user uses container (e.g. the group path in legacy mode);

The above two paths have their own noiommu mode support accordingly.

The cdev path also uses iommufd, so for the case user provides a valid
iommufd, this helper is able to support it. But for noiommu mode, the
cdev path just provides a NULL iommufd. So this needs to be able to cover
it. As there is no special things to do for the cdev path in noiommu
mode, it can be covered by simply differentiate it from the container
case. If user is not using iommufd nor container, it is the noiommu
mode.

Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/vfio/group.c | 15 +++++++++++++++
drivers/vfio/vfio.h | 1 +
drivers/vfio/vfio_main.c | 21 +++++++++++++++++----
3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index f067a6a7bbd2..51c027134814 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -780,6 +780,21 @@ void vfio_device_group_unregister(struct vfio_device *device)
mutex_unlock(&device->group->device_lock);
}

+/*
+ * This shall be used without group lock as group and group->container
+ * should be fixed before group is set to df->group.
+ */
+bool vfio_device_group_uses_container(struct vfio_device_file *df)
+{
+ /*
+ * Use the df->group instead of the df->device->group as no
+ * lock is acquired here.
+ */
+ if (WARN_ON(!df->group))
+ return false;
+ return READ_ONCE(df->group->container);
+}
+
int vfio_device_group_use_iommu(struct vfio_device *device)
{
struct vfio_group *group = device->group;
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 11397cc95e0b..615ffd58562b 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -95,6 +95,7 @@ int vfio_device_set_group(struct vfio_device *device,
void vfio_device_remove_group(struct vfio_device *device);
void vfio_device_group_register(struct vfio_device *device);
void vfio_device_group_unregister(struct vfio_device *device);
+bool vfio_device_group_uses_container(struct vfio_device_file *df);
int vfio_device_group_use_iommu(struct vfio_device *device);
void vfio_device_group_unuse_iommu(struct vfio_device *device);
void vfio_device_group_close(struct vfio_device_file *df);
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index aa31aae33407..8c73df1a400e 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -423,16 +423,29 @@ static int vfio_device_first_open(struct vfio_device_file *df)
{
struct vfio_device *device = df->device;
struct iommufd_ctx *iommufd = df->iommufd;
- int ret;
+ int ret = 0;

lockdep_assert_held(&device->dev_set->lock);

if (!try_module_get(device->dev->driver->owner))
return -ENODEV;

+ /*
+ * The handling here depends on what the user is using.
+ *
+ * If user uses iommufd in the group compat mode or the
+ * cdev path, call vfio_iommufd_bind().
+ *
+ * If user uses container in the group legacy mode, call
+ * vfio_device_group_use_iommu().
+ *
+ * If user doesn't use iommufd nor container, this is
+ * the noiommufd mode in the cdev path, nothing needs
+ * to be done here just go ahead to open device.
+ */
if (iommufd)
ret = vfio_iommufd_bind(device, iommufd);
- else
+ else if (vfio_device_group_uses_container(df))
ret = vfio_device_group_use_iommu(device);
if (ret)
goto err_module_put;
@@ -447,7 +460,7 @@ static int vfio_device_first_open(struct vfio_device_file *df)
err_unuse_iommu:
if (iommufd)
vfio_iommufd_unbind(device);
- else
+ else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
err_module_put:
module_put(device->dev->driver->owner);
@@ -465,7 +478,7 @@ static void vfio_device_last_close(struct vfio_device_file *df)
device->ops->close_device(device);
if (iommufd)
vfio_iommufd_unbind(device);
- else
+ else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
module_put(device->dev->driver->owner);
}
--
2.34.1