From: Kevin Tian <kevin.t...@intel.com>

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.

Signed-off-by: Kevin Tian <kevin.t...@intel.com>
Signed-off-by: Yi Liu <yi.l....@intel.com>
---
 drivers/vfio/iommufd.c      | 48 +++++++++++++++++++++++++++++++++++++
 drivers/vfio/pci/vfio_pci.c |  2 ++
 include/linux/vfio.h        | 11 +++++++++
 3 files changed, 61 insertions(+)

diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 82eba6966fa5..43a702b9b4d3 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -119,6 +119,7 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
        if (IS_ERR(idev))
                return PTR_ERR(idev);
        vdev->iommufd_device = idev;
+       xa_init(&vdev->pasid_pts);
        return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind);
@@ -127,6 +128,17 @@ void vfio_iommufd_physical_unbind(struct vfio_device *vdev)
 {
        lockdep_assert_held(&vdev->dev_set->lock);
 
+       if (!xa_empty(&vdev->pasid_pts)) {
+               void *entry;
+               unsigned long index;
+
+               xa_for_each(&vdev->pasid_pts, index, entry) {
+                       xa_erase(&vdev->pasid_pts, index);
+                       iommufd_device_pasid_detach(vdev->iommufd_device, 
index);
+               }
+               xa_destroy(&vdev->pasid_pts);
+       }
+
        if (vdev->iommufd_attached) {
                iommufd_device_detach(vdev->iommufd_device);
                vdev->iommufd_attached = false;
@@ -168,6 +180,42 @@ 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)
+{
+       void *entry;
+       int rc;
+
+       lockdep_assert_held(&vdev->dev_set->lock);
+
+       if (WARN_ON(!vdev->iommufd_device))
+               return -EINVAL;
+
+       entry = xa_load(&vdev->pasid_pts, pasid);
+       if (xa_is_value(entry))
+               rc = iommufd_device_pasid_replace(vdev->iommufd_device, pasid, 
pt_id);
+       else
+               rc = iommufd_device_pasid_attach(vdev->iommufd_device, pasid, 
pt_id);
+       if (rc)
+               return rc;
+       xa_store(&vdev->pasid_pts, pasid, xa_mk_value(*pt_id), GFP_KERNEL);
+       return 0;
+}
+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) ||
+           !xa_is_value(xa_load(&vdev->pasid_pts, pasid)))
+               return;
+
+       iommufd_device_pasid_detach(vdev->iommufd_device, pasid);
+       xa_erase(&vdev->pasid_pts, 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
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index cb5b7f865d58..e0198851ffd2 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -142,6 +142,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)
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 454e9295970c..7b06d1bc7cb3 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -66,6 +66,7 @@ struct vfio_device {
        void (*put_kvm)(struct kvm *kvm);
 #if IS_ENABLED(CONFIG_IOMMUFD)
        struct iommufd_device *iommufd_device;
+       struct xarray pasid_pts;
        u8 iommufd_attached:1;
 #endif
        u8 cdev_opened:1;
@@ -83,6 +84,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
@@ -107,6 +110,8 @@ 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,
@@ -131,6 +136,8 @@ 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);
@@ -158,6 +165,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)
-- 
2.34.1


Reply via email to