vfio-iommufd: Add detach_ioas support for physical VFIO devices
authorYi Liu <yi.l.liu@intel.com>
Tue, 18 Jul 2023 13:55:38 +0000 (06:55 -0700)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 25 Jul 2023 16:19:12 +0000 (10:19 -0600)
This prepares for adding DETACH ioctl for physical VFIO devices.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Terrence Xu <terrence.xu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
Tested-by: Yanting Jiang <yanting.jiang@intel.com>
Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Tested-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20230718135551.6592-14-yi.l.liu@intel.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Documentation/driver-api/vfio.rst
drivers/vfio/fsl-mc/vfio_fsl_mc.c
drivers/vfio/iommufd.c
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
drivers/vfio/pci/mlx5/main.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/platform/vfio_amba.c
drivers/vfio/platform/vfio_platform.c
drivers/vfio/vfio_main.c
include/linux/vfio.h

index 68abc08..363e12c 100644 (file)
@@ -279,6 +279,7 @@ similar to a file operations structure::
                                        struct iommufd_ctx *ictx, u32 *out_device_id);
                void    (*unbind_iommufd)(struct vfio_device *vdev);
                int     (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id);
+               void    (*detach_ioas)(struct vfio_device *vdev);
                int     (*open_device)(struct vfio_device *vdev);
                void    (*close_device)(struct vfio_device *vdev);
                ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
@@ -315,9 +316,10 @@ container_of().
        - The [un]bind_iommufd callbacks are issued when the device is bound to
          and unbound from iommufd.
 
-       - The attach_ioas callback is issued when the device is attached to an
-         IOAS managed by the bound iommufd. The attached IOAS is automatically
-         detached when the device is unbound from iommufd.
+       - The [de]attach_ioas callback is issued when the device is attached to
+         and detached from an IOAS managed by the bound iommufd. However, the
+         attached IOAS can also be automatically detached when the device is
+         unbound from iommufd.
 
        - The read/write/mmap callbacks implement the device region access defined
          by the device's own VFIO_DEVICE_GET_REGION_INFO ioctl.
index f2140e9..116358a 100644 (file)
@@ -593,6 +593,7 @@ static const struct vfio_device_ops vfio_fsl_mc_ops = {
        .bind_iommufd   = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas    = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas    = vfio_iommufd_physical_detach_ioas,
 };
 
 static struct fsl_mc_driver vfio_fsl_mc_driver = {
index 4fc674c..86df541 100644 (file)
@@ -140,6 +140,14 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
 {
        int rc;
 
+       lockdep_assert_held(&vdev->dev_set->lock);
+
+       if (WARN_ON(!vdev->iommufd_device))
+               return -EINVAL;
+
+       if (vdev->iommufd_attached)
+               return -EBUSY;
+
        rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
        if (rc)
                return rc;
@@ -148,6 +156,18 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
 
+void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
+{
+       lockdep_assert_held(&vdev->dev_set->lock);
+
+       if (WARN_ON(!vdev->iommufd_device) || !vdev->iommufd_attached)
+               return;
+
+       iommufd_device_detach(vdev->iommufd_device);
+       vdev->iommufd_attached = false;
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);
+
 /*
  * The emulated standard ops mean that vfio_device is going to use the
  * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
index a117eaf..b2f9778 100644 (file)
@@ -1373,6 +1373,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_migrn_ops = {
        .bind_iommufd = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas = vfio_iommufd_physical_detach_ioas,
 };
 
 static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
@@ -1391,6 +1392,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
        .bind_iommufd = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas = vfio_iommufd_physical_detach_ioas,
 };
 
 static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
index d95fd38..42ec574 100644 (file)
@@ -1320,6 +1320,7 @@ static const struct vfio_device_ops mlx5vf_pci_ops = {
        .bind_iommufd = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas = vfio_iommufd_physical_detach_ioas,
 };
 
 static int mlx5vf_pci_probe(struct pci_dev *pdev,
index 29091ee..cb5b7f8 100644 (file)
@@ -141,6 +141,7 @@ static const struct vfio_device_ops vfio_pci_ops = {
        .bind_iommufd   = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas    = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas    = vfio_iommufd_physical_detach_ioas,
 };
 
 static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
index 83fe540..6464b39 100644 (file)
@@ -119,6 +119,7 @@ static const struct vfio_device_ops vfio_amba_ops = {
        .bind_iommufd   = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas    = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas    = vfio_iommufd_physical_detach_ioas,
 };
 
 static const struct amba_id pl330_ids[] = {
index 22a1efc..8cf22fa 100644 (file)
@@ -108,6 +108,7 @@ static const struct vfio_device_ops vfio_platform_ops = {
        .bind_iommufd   = vfio_iommufd_physical_bind,
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas    = vfio_iommufd_physical_attach_ioas,
+       .detach_ioas    = vfio_iommufd_physical_detach_ioas,
 };
 
 static struct platform_driver vfio_platform_driver = {
index 3a4b7eb..c71c0d1 100644 (file)
@@ -273,7 +273,8 @@ static int __vfio_register_dev(struct vfio_device *device,
        if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) &&
                    (!device->ops->bind_iommufd ||
                     !device->ops->unbind_iommufd ||
-                    !device->ops->attach_ioas)))
+                    !device->ops->attach_ioas ||
+                    !device->ops->detach_ioas)))
                return -EINVAL;
 
        /*
index 06a5221..f2f0227 100644 (file)
@@ -73,7 +73,9 @@ struct vfio_device {
  * @bind_iommufd: Called when binding the device to an iommufd
  * @unbind_iommufd: Opposite of bind_iommufd
  * @attach_ioas: Called when attaching device to an IOAS/HWPT managed by the
- *              bound iommufd. Undo in unbind_iommufd.
+ *              bound iommufd. Undo in unbind_iommufd if @detach_ioas is not
+ *              called.
+ * @detach_ioas: Opposite of attach_ioas
  * @open_device: Called when the first file descriptor is opened for this device
  * @close_device: Opposite of open_device
  * @read: Perform read(2) on device file descriptor
@@ -97,6 +99,7 @@ struct vfio_device_ops {
                                struct iommufd_ctx *ictx, u32 *out_device_id);
        void    (*unbind_iommufd)(struct vfio_device *vdev);
        int     (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id);
+       void    (*detach_ioas)(struct vfio_device *vdev);
        int     (*open_device)(struct vfio_device *vdev);
        void    (*close_device)(struct vfio_device *vdev);
        ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
@@ -120,6 +123,7 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
                               struct iommufd_ctx *ictx, u32 *out_device_id);
 void vfio_iommufd_physical_unbind(struct vfio_device *vdev);
 int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id);
+void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev);
 int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
                               struct iommufd_ctx *ictx, u32 *out_device_id);
 void vfio_iommufd_emulated_unbind(struct vfio_device *vdev);
@@ -144,6 +148,8 @@ vfio_iommufd_get_dev_id(struct vfio_device *vdev, struct iommufd_ctx *ictx)
        ((void (*)(struct vfio_device *vdev)) NULL)
 #define vfio_iommufd_physical_attach_ioas \
        ((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL)
+#define vfio_iommufd_physical_detach_ioas \
+       ((void (*)(struct vfio_device *vdev)) NULL)
 #define vfio_iommufd_emulated_bind                                      \
        ((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx,   \
                  u32 *out_device_id)) NULL)