]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
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 68abc089d6ddd173013b115ff65df1e84b292706..363e12c90b87d59e36888b4c06ecc74c8f103931 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 f2140e94d41efbac306caabac83762e28ad795b4..116358a8f1cfa969fcbf759829879bfcd6f7c896 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 4fc674c01a0524b492a20ba82423cbe844686705..86df5415759a2a5ba5b0b43fe162ade3e2f1ec3c 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 a117eaf21c14fb1b447ad66b9b2687b044344cc4..b2f9778c8366ea8944f1c59be51f41d69570da19 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 d95fd382814c8f28ba4db8d78170e97441992cc9..42ec574a86221074b2b201d4546e116adfd79179 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 29091ee2e9849bafc044a70559b7db1f2f260116..cb5b7f865d5856f803bcb54a0342980c97a5127e 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 83fe5401559585d241146258b9630d1670ed8600..6464b3939ebcfb5304511d42aedc9bb5d9a3393a 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 22a1efca32a8a86ae24ae683d2035d7cece8e016..8cf22fa65baa229404fc133cad75240e113f81b8 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 3a4b7eb128dfcc592da8b2c375f0dfdf1fd8f18b..c71c0d1a079fd67ce7206c25deb28e39e3f13a11 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 06a5221949c5ba0f0458ac22d5fae6c37a1ae0bf..f2f02273ece196fe7961ba30cd6ddec227aeeba9 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)