mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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>
This commit is contained in:
parent
7fe6b98716
commit
290641346d
3 changed files with 66 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue