Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vfio-iommufd: Support pasid [at|de]tach for physical VFIO devices

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>

authored by

Yi Liu and committed by
Jason Gunthorpe
29064134 7fe6b987

+66
+50
drivers/vfio/iommufd.c
··· 119 119 if (IS_ERR(idev)) 120 120 return PTR_ERR(idev); 121 121 vdev->iommufd_device = idev; 122 + ida_init(&vdev->pasids); 122 123 return 0; 123 124 } 124 125 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind); 125 126 126 127 void vfio_iommufd_physical_unbind(struct vfio_device *vdev) 127 128 { 129 + int pasid; 130 + 128 131 lockdep_assert_held(&vdev->dev_set->lock); 132 + 133 + while ((pasid = ida_find_first(&vdev->pasids)) >= 0) { 134 + iommufd_device_detach(vdev->iommufd_device, pasid); 135 + ida_free(&vdev->pasids, pasid); 136 + } 129 137 130 138 if (vdev->iommufd_attached) { 131 139 iommufd_device_detach(vdev->iommufd_device, IOMMU_NO_PASID); ··· 177 169 vdev->iommufd_attached = false; 178 170 } 179 171 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas); 172 + 173 + int vfio_iommufd_physical_pasid_attach_ioas(struct vfio_device *vdev, 174 + u32 pasid, u32 *pt_id) 175 + { 176 + int rc; 177 + 178 + lockdep_assert_held(&vdev->dev_set->lock); 179 + 180 + if (WARN_ON(!vdev->iommufd_device)) 181 + return -EINVAL; 182 + 183 + if (ida_exists(&vdev->pasids, pasid)) 184 + return iommufd_device_replace(vdev->iommufd_device, 185 + pasid, pt_id); 186 + 187 + rc = ida_alloc_range(&vdev->pasids, pasid, pasid, GFP_KERNEL); 188 + if (rc < 0) 189 + return rc; 190 + 191 + rc = iommufd_device_attach(vdev->iommufd_device, pasid, pt_id); 192 + if (rc) 193 + ida_free(&vdev->pasids, pasid); 194 + 195 + return rc; 196 + } 197 + EXPORT_SYMBOL_GPL(vfio_iommufd_physical_pasid_attach_ioas); 198 + 199 + void vfio_iommufd_physical_pasid_detach_ioas(struct vfio_device *vdev, 200 + u32 pasid) 201 + { 202 + lockdep_assert_held(&vdev->dev_set->lock); 203 + 204 + if (WARN_ON(!vdev->iommufd_device)) 205 + return; 206 + 207 + if (!ida_exists(&vdev->pasids, pasid)) 208 + return; 209 + 210 + iommufd_device_detach(vdev->iommufd_device, pasid); 211 + ida_free(&vdev->pasids, pasid); 212 + } 213 + EXPORT_SYMBOL_GPL(vfio_iommufd_physical_pasid_detach_ioas); 180 214 181 215 /* 182 216 * The emulated standard ops mean that vfio_device is going to use the
+2
drivers/vfio/pci/vfio_pci.c
··· 144 144 .unbind_iommufd = vfio_iommufd_physical_unbind, 145 145 .attach_ioas = vfio_iommufd_physical_attach_ioas, 146 146 .detach_ioas = vfio_iommufd_physical_detach_ioas, 147 + .pasid_attach_ioas = vfio_iommufd_physical_pasid_attach_ioas, 148 + .pasid_detach_ioas = vfio_iommufd_physical_pasid_detach_ioas, 147 149 }; 148 150 149 151 static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+14
include/linux/vfio.h
··· 67 67 struct inode *inode; 68 68 #if IS_ENABLED(CONFIG_IOMMUFD) 69 69 struct iommufd_device *iommufd_device; 70 + struct ida pasids; 70 71 u8 iommufd_attached:1; 71 72 #endif 72 73 u8 cdev_opened:1; ··· 92 91 * bound iommufd. Undo in unbind_iommufd if @detach_ioas is not 93 92 * called. 94 93 * @detach_ioas: Opposite of attach_ioas 94 + * @pasid_attach_ioas: The pasid variation of attach_ioas 95 + * @pasid_detach_ioas: Opposite of pasid_attach_ioas 95 96 * @open_device: Called when the first file descriptor is opened for this device 96 97 * @close_device: Opposite of open_device 97 98 * @read: Perform read(2) on device file descriptor ··· 118 115 void (*unbind_iommufd)(struct vfio_device *vdev); 119 116 int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id); 120 117 void (*detach_ioas)(struct vfio_device *vdev); 118 + int (*pasid_attach_ioas)(struct vfio_device *vdev, u32 pasid, 119 + u32 *pt_id); 120 + void (*pasid_detach_ioas)(struct vfio_device *vdev, u32 pasid); 121 121 int (*open_device)(struct vfio_device *vdev); 122 122 void (*close_device)(struct vfio_device *vdev); 123 123 ssize_t (*read)(struct vfio_device *vdev, char __user *buf, ··· 145 139 void vfio_iommufd_physical_unbind(struct vfio_device *vdev); 146 140 int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id); 147 141 void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev); 142 + int vfio_iommufd_physical_pasid_attach_ioas(struct vfio_device *vdev, 143 + u32 pasid, u32 *pt_id); 144 + void vfio_iommufd_physical_pasid_detach_ioas(struct vfio_device *vdev, 145 + u32 pasid); 148 146 int vfio_iommufd_emulated_bind(struct vfio_device *vdev, 149 147 struct iommufd_ctx *ictx, u32 *out_device_id); 150 148 void vfio_iommufd_emulated_unbind(struct vfio_device *vdev); ··· 176 166 ((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL) 177 167 #define vfio_iommufd_physical_detach_ioas \ 178 168 ((void (*)(struct vfio_device *vdev)) NULL) 169 + #define vfio_iommufd_physical_pasid_attach_ioas \ 170 + ((int (*)(struct vfio_device *vdev, u32 pasid, u32 *pt_id)) NULL) 171 + #define vfio_iommufd_physical_pasid_detach_ioas \ 172 + ((void (*)(struct vfio_device *vdev, u32 pasid)) NULL) 179 173 #define vfio_iommufd_emulated_bind \ 180 174 ((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx, \ 181 175 u32 *out_device_id)) NULL)