]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vfio-iommufd: Support pasid [at|de]tach for physical VFIO devices
authorYi Liu <yi.l.liu@intel.com>
Fri, 21 Mar 2025 18:01:40 +0000 (11:01 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 25 Mar 2025 13:18:31 +0000 (10:18 -0300)
This adds pasid_at|de]tach_ioas ops for attaching hwpt to pasid of a
device and the helpers for it. For now, only vfio-pci supports pasid
attach/detach.

Link: https://patch.msgid.link/r/20250321180143.8468-3-yi.l.liu@intel.com
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/vfio/iommufd.c
drivers/vfio/pci/vfio_pci.c
include/linux/vfio.h

index 37e1efa2c7bfe68a9bb47597833b2fe47db5dbf6..c8c3a2d53f86e197a72f0e4d798c201f3d8e31d4 100644 (file)
@@ -119,14 +119,22 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
        if (IS_ERR(idev))
                return PTR_ERR(idev);
        vdev->iommufd_device = idev;
+       ida_init(&vdev->pasids);
        return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind);
 
 void vfio_iommufd_physical_unbind(struct vfio_device *vdev)
 {
+       int pasid;
+
        lockdep_assert_held(&vdev->dev_set->lock);
 
+       while ((pasid = ida_find_first(&vdev->pasids)) >= 0) {
+               iommufd_device_detach(vdev->iommufd_device, pasid);
+               ida_free(&vdev->pasids, pasid);
+       }
+
        if (vdev->iommufd_attached) {
                iommufd_device_detach(vdev->iommufd_device, IOMMU_NO_PASID);
                vdev->iommufd_attached = false;
@@ -170,6 +178,48 @@ void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);
 
+int vfio_iommufd_physical_pasid_attach_ioas(struct vfio_device *vdev,
+                                           u32 pasid, u32 *pt_id)
+{
+       int rc;
+
+       lockdep_assert_held(&vdev->dev_set->lock);
+
+       if (WARN_ON(!vdev->iommufd_device))
+               return -EINVAL;
+
+       if (ida_exists(&vdev->pasids, pasid))
+               return iommufd_device_replace(vdev->iommufd_device,
+                                             pasid, pt_id);
+
+       rc = ida_alloc_range(&vdev->pasids, pasid, pasid, GFP_KERNEL);
+       if (rc < 0)
+               return rc;
+
+       rc = iommufd_device_attach(vdev->iommufd_device, pasid, pt_id);
+       if (rc)
+               ida_free(&vdev->pasids, pasid);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_physical_pasid_attach_ioas);
+
+void vfio_iommufd_physical_pasid_detach_ioas(struct vfio_device *vdev,
+                                            u32 pasid)
+{
+       lockdep_assert_held(&vdev->dev_set->lock);
+
+       if (WARN_ON(!vdev->iommufd_device))
+               return;
+
+       if (!ida_exists(&vdev->pasids, pasid))
+               return;
+
+       iommufd_device_detach(vdev->iommufd_device, pasid);
+       ida_free(&vdev->pasids, pasid);
+}
+EXPORT_SYMBOL_GPL(vfio_iommufd_physical_pasid_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 e727941f589de5316667ebe451745f5b4b9e6e75..6f7ae7e5b7b07fc0296fb3745f6de2f79f202bf2 100644 (file)
@@ -144,6 +144,8 @@ static const struct vfio_device_ops vfio_pci_ops = {
        .unbind_iommufd = vfio_iommufd_physical_unbind,
        .attach_ioas    = vfio_iommufd_physical_attach_ioas,
        .detach_ioas    = vfio_iommufd_physical_detach_ioas,
+       .pasid_attach_ioas      = vfio_iommufd_physical_pasid_attach_ioas,
+       .pasid_detach_ioas      = vfio_iommufd_physical_pasid_detach_ioas,
 };
 
 static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
index 000a6cab2d318a93cf495a18ae5cc39df38beac5..707b00772ce1ff61097655773ea3cc9a87f920fc 100644 (file)
@@ -67,6 +67,7 @@ struct vfio_device {
        struct inode *inode;
 #if IS_ENABLED(CONFIG_IOMMUFD)
        struct iommufd_device *iommufd_device;
+       struct ida pasids;
        u8 iommufd_attached:1;
 #endif
        u8 cdev_opened:1;
@@ -91,6 +92,8 @@ struct vfio_device {
  *              bound iommufd. Undo in unbind_iommufd if @detach_ioas is not
  *              called.
  * @detach_ioas: Opposite of attach_ioas
+ * @pasid_attach_ioas: The pasid variation of attach_ioas
+ * @pasid_detach_ioas: Opposite of pasid_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
@@ -115,6 +118,9 @@ struct vfio_device_ops {
        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     (*pasid_attach_ioas)(struct vfio_device *vdev, u32 pasid,
+                                    u32 *pt_id);
+       void    (*pasid_detach_ioas)(struct vfio_device *vdev, u32 pasid);
        int     (*open_device)(struct vfio_device *vdev);
        void    (*close_device)(struct vfio_device *vdev);
        ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
@@ -139,6 +145,10 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
 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_physical_pasid_attach_ioas(struct vfio_device *vdev,
+                                           u32 pasid, u32 *pt_id);
+void vfio_iommufd_physical_pasid_detach_ioas(struct vfio_device *vdev,
+                                            u32 pasid);
 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);
@@ -166,6 +176,10 @@ vfio_iommufd_get_dev_id(struct vfio_device *vdev, struct iommufd_ctx *ictx)
        ((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL)
 #define vfio_iommufd_physical_detach_ioas \
        ((void (*)(struct vfio_device *vdev)) NULL)
+#define vfio_iommufd_physical_pasid_attach_ioas \
+       ((int (*)(struct vfio_device *vdev, u32 pasid, u32 *pt_id)) NULL)
+#define vfio_iommufd_physical_pasid_detach_ioas \
+       ((void (*)(struct vfio_device *vdev, u32 pasid)) NULL)
 #define vfio_iommufd_emulated_bind                                      \
        ((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx,   \
                  u32 *out_device_id)) NULL)