On Sun, Nov 26, 2023 at 10:34:23PM -0800, Yi Liu wrote: > @@ -534,7 +537,17 @@ iommufd_device_do_replace(struct iommufd_device *idev, > static struct iommufd_hw_pagetable *do_attach(struct iommufd_device *idev, > struct iommufd_hw_pagetable *hwpt, struct attach_data *data) > { > - return data->attach_fn(idev, hwpt); > + if (data->pasid == IOMMU_PASID_INVALID) { > + BUG_ON((data->attach_fn != iommufd_device_do_attach) && > + (data->attach_fn != iommufd_device_do_replace)); > + return data->attach_fn(idev, hwpt); > + } else { > + BUG_ON((data->pasid_attach_fn != > + iommufd_device_pasid_do_attach) && > + (data->pasid_attach_fn != > + iommufd_device_pasid_do_replace)); > + return data->pasid_attach_fn(idev, data->pasid, hwpt); > + } Seems like the BUG_ON's are pointless > +/** > + * iommufd_device_pasid_detach - Disconnect a {device, pasid} to an iommu_domain > + * @idev: device to detach > + * @pasid: pasid to detach > + * > + * Undo iommufd_device_pasid_attach(). This disconnects the idev/pasid from > + * the previously attached pt_id. > + */ > +void iommufd_device_pasid_detach(struct iommufd_device *idev, u32 pasid) > +{ > + struct iommufd_hw_pagetable *hwpt; > + > + hwpt = xa_load(&idev->pasid_hwpts, pasid); > + if (!hwpt) > + return; > + xa_erase(&idev->pasid_hwpts, pasid); > + iommu_detach_device_pasid(hwpt->domain, idev->dev, pasid); > + iommufd_hw_pagetable_put(idev->ictx, hwpt); > +} None of this xarray stuff looks locked properly Jason