This moves the noiommu device determination and noiommu taint out of
vfio_group_find_or_alloc(). noiommu device is determined in
__vfio_register_dev() and result is stored in flag vfio_device->noiommu,
the noiommu taint is added in the end of __vfio_register_dev().

This is also a preparation for compiling out vfio_group infrastructure
as it makes the noiommu detection and taint common between the cdev path
and group path though cdev path does not support noiommu.

Suggested-by: Alex Williamson <[email protected]>
Signed-off-by: Yi Liu <[email protected]>
---
 drivers/vfio/group.c     | 15 ---------------
 drivers/vfio/vfio_main.c | 31 ++++++++++++++++++++++++++++++-
 include/linux/vfio.h     |  1 +
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index 653b62f93474..64cdd0ea8825 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -668,21 +668,6 @@ static struct vfio_group *vfio_group_find_or_alloc(struct 
device *dev)
        struct vfio_group *group;
 
        iommu_group = iommu_group_get(dev);
-       if (!iommu_group && vfio_noiommu) {
-               /*
-                * With noiommu enabled, create an IOMMU group for devices that
-                * don't already have one, implying no IOMMU hardware/driver
-                * exists.  Taint the kernel because we're about to give a DMA
-                * capable device to a user without IOMMU protection.
-                */
-               group = vfio_noiommu_group_alloc(dev, VFIO_NO_IOMMU);
-               if (!IS_ERR(group)) {
-                       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-                       dev_warn(dev, "Adding kernel taint for vfio-noiommu 
group on device\n");
-               }
-               return group;
-       }
-
        if (!iommu_group)
                return ERR_PTR(-EINVAL);
 
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 6d8f9b0f3637..00a699b9f76b 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -265,6 +265,18 @@ static int vfio_init_device(struct vfio_device *device, 
struct device *dev,
        return ret;
 }
 
+static int vfio_device_set_noiommu(struct vfio_device *device)
+{
+       struct iommu_group *iommu_group = iommu_group_get(device->dev);
+
+       if (!iommu_group && !vfio_noiommu)
+               return -EINVAL;
+
+       device->noiommu = !iommu_group;
+       iommu_group_put(iommu_group); /* Accepts NULL */
+       return 0;
+}
+
 static int __vfio_register_dev(struct vfio_device *device,
                               enum vfio_group_type type)
 {
@@ -277,6 +289,13 @@ static int __vfio_register_dev(struct vfio_device *device,
                     !device->ops->detach_ioas)))
                return -EINVAL;
 
+       /* Only physical devices can be noiommu device */
+       if (type == VFIO_IOMMU) {
+               ret = vfio_device_set_noiommu(device);
+               if (ret)
+                       return ret;
+       }
+
        /*
         * If the driver doesn't specify a set then the device is added to a
         * singleton set just for itself.
@@ -288,7 +307,8 @@ static int __vfio_register_dev(struct vfio_device *device,
        if (ret)
                return ret;
 
-       ret = vfio_device_set_group(device, type);
+       ret = vfio_device_set_group(device,
+                                   device->noiommu ? VFIO_NO_IOMMU : type);
        if (ret)
                return ret;
 
@@ -301,6 +321,15 @@ static int __vfio_register_dev(struct vfio_device *device,
 
        vfio_device_group_register(device);
 
+       if (device->noiommu) {
+               /*
+                * noiommu deivces have no IOMMU hardware/driver.  Taint the
+                * kernel because we're about to give a DMA capable device to
+                * a user without IOMMU protection.
+                */
+               add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+               dev_warn(device->dev, "Adding kernel taint for vfio-noiommu on 
device\n");
+       }
        return 0;
 err_out:
        vfio_device_remove_group(device);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index e80a8ac86e46..183e620009e7 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -67,6 +67,7 @@ struct vfio_device {
        bool iommufd_attached;
 #endif
        bool cdev_opened:1;
+       bool noiommu:1;
 };
 
 /**
-- 
2.34.1

Reply via email to