]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommufd: Pass @pasid through the device attach/replace path
authorYi Liu <yi.l.liu@intel.com>
Fri, 21 Mar 2025 17:19:25 +0000 (10:19 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 25 Mar 2025 13:18:30 +0000 (10:18 -0300)
Most of the core logic before conducting the actual device attach/
replace operation can be shared with pasid attach/replace. So pass
@pasid through the device attach/replace helpers to prepare adding
pasid attach/replace.

So far the @pasid should only be IOMMU_NO_PASID. No functional change.

Link: https://patch.msgid.link/r/20250321171940.7213-4-yi.l.liu@intel.com
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/iommufd/device.c
drivers/iommu/iommufd/hw_pagetable.c
drivers/iommu/iommufd/iommufd_private.h

index d18ea9a61522e0312b1f3a19ed4f8b002a45f581..7051feda2fab0885e2787590496a3293a202951a 100644 (file)
@@ -368,7 +368,8 @@ static bool iommufd_device_is_attached(struct iommufd_device *idev)
 }
 
 static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
-                                     struct iommufd_device *idev)
+                                     struct iommufd_device *idev,
+                                     ioasid_t pasid)
 {
        struct iommufd_attach_handle *handle;
        int rc;
@@ -386,6 +387,7 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
        }
 
        handle->idev = idev;
+       WARN_ON(pasid != IOMMU_NO_PASID);
        rc = iommu_attach_group_handle(hwpt->domain, idev->igroup->group,
                                       &handle->handle);
        if (rc)
@@ -402,25 +404,28 @@ out_free_handle:
 }
 
 static struct iommufd_attach_handle *
-iommufd_device_get_attach_handle(struct iommufd_device *idev)
+iommufd_device_get_attach_handle(struct iommufd_device *idev, ioasid_t pasid)
 {
        struct iommu_attach_handle *handle;
 
        lockdep_assert_held(&idev->igroup->lock);
 
        handle =
-               iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0);
+               iommu_attach_handle_get(idev->igroup->group, pasid, 0);
        if (IS_ERR(handle))
                return NULL;
        return to_iommufd_handle(handle);
 }
 
 static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
-                                      struct iommufd_device *idev)
+                                      struct iommufd_device *idev,
+                                      ioasid_t pasid)
 {
        struct iommufd_attach_handle *handle;
 
-       handle = iommufd_device_get_attach_handle(idev);
+       WARN_ON(pasid != IOMMU_NO_PASID);
+
+       handle = iommufd_device_get_attach_handle(idev, pasid);
        iommu_detach_group_handle(hwpt->domain, idev->igroup->group);
        if (hwpt->fault) {
                iommufd_auto_response_faults(hwpt, handle);
@@ -430,13 +435,17 @@ static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
 }
 
 static int iommufd_hwpt_replace_device(struct iommufd_device *idev,
+                                      ioasid_t pasid,
                                       struct iommufd_hw_pagetable *hwpt,
                                       struct iommufd_hw_pagetable *old)
 {
-       struct iommufd_attach_handle *handle, *old_handle =
-               iommufd_device_get_attach_handle(idev);
+       struct iommufd_attach_handle *handle, *old_handle;
        int rc;
 
+       WARN_ON(pasid != IOMMU_NO_PASID);
+
+       old_handle = iommufd_device_get_attach_handle(idev, pasid);
+
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle)
                return -ENOMEM;
@@ -471,7 +480,7 @@ out_free_handle:
 }
 
 int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
-                               struct iommufd_device *idev)
+                               struct iommufd_device *idev, ioasid_t pasid)
 {
        struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
        int rc;
@@ -497,7 +506,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
         * attachment.
         */
        if (list_empty(&idev->igroup->device_list)) {
-               rc = iommufd_hwpt_attach_device(hwpt, idev);
+               rc = iommufd_hwpt_attach_device(hwpt, idev, pasid);
                if (rc)
                        goto err_unresv;
                idev->igroup->hwpt = hwpt;
@@ -515,7 +524,7 @@ err_unlock:
 }
 
 struct iommufd_hw_pagetable *
-iommufd_hw_pagetable_detach(struct iommufd_device *idev)
+iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid)
 {
        struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt;
        struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
@@ -523,7 +532,7 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev)
        mutex_lock(&idev->igroup->lock);
        list_del(&idev->group_item);
        if (list_empty(&idev->igroup->device_list)) {
-               iommufd_hwpt_detach_device(hwpt, idev);
+               iommufd_hwpt_detach_device(hwpt, idev, pasid);
                idev->igroup->hwpt = NULL;
        }
        if (hwpt_paging)
@@ -535,12 +544,12 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev)
 }
 
 static struct iommufd_hw_pagetable *
-iommufd_device_do_attach(struct iommufd_device *idev,
+iommufd_device_do_attach(struct iommufd_device *idev, ioasid_t pasid,
                         struct iommufd_hw_pagetable *hwpt)
 {
        int rc;
 
-       rc = iommufd_hw_pagetable_attach(hwpt, idev);
+       rc = iommufd_hw_pagetable_attach(hwpt, idev, pasid);
        if (rc)
                return ERR_PTR(rc);
        return NULL;
@@ -589,7 +598,7 @@ err_unresv:
 }
 
 static struct iommufd_hw_pagetable *
-iommufd_device_do_replace(struct iommufd_device *idev,
+iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
                          struct iommufd_hw_pagetable *hwpt)
 {
        struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
@@ -623,7 +632,7 @@ iommufd_device_do_replace(struct iommufd_device *idev,
                        goto err_unlock;
        }
 
-       rc = iommufd_hwpt_replace_device(idev, hwpt, old_hwpt);
+       rc = iommufd_hwpt_replace_device(idev, pasid, hwpt, old_hwpt);
        if (rc)
                goto err_unresv;
 
@@ -656,7 +665,8 @@ err_unlock:
 }
 
 typedef struct iommufd_hw_pagetable *(*attach_fn)(
-       struct iommufd_device *idev, struct iommufd_hw_pagetable *hwpt);
+       struct iommufd_device *idev, ioasid_t pasid,
+       struct iommufd_hw_pagetable *hwpt);
 
 /*
  * When automatically managing the domains we search for a compatible domain in
@@ -664,7 +674,7 @@ typedef struct iommufd_hw_pagetable *(*attach_fn)(
  * Automatic domain selection will never pick a manually created domain.
  */
 static struct iommufd_hw_pagetable *
-iommufd_device_auto_get_domain(struct iommufd_device *idev,
+iommufd_device_auto_get_domain(struct iommufd_device *idev, ioasid_t pasid,
                               struct iommufd_ioas *ioas, u32 *pt_id,
                               attach_fn do_attach)
 {
@@ -693,7 +703,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
                hwpt = &hwpt_paging->common;
                if (!iommufd_lock_obj(&hwpt->obj))
                        continue;
-               destroy_hwpt = (*do_attach)(idev, hwpt);
+               destroy_hwpt = (*do_attach)(idev, pasid, hwpt);
                if (IS_ERR(destroy_hwpt)) {
                        iommufd_put_object(idev->ictx, &hwpt->obj);
                        /*
@@ -711,8 +721,8 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
                goto out_unlock;
        }
 
-       hwpt_paging = iommufd_hwpt_paging_alloc(idev->ictx, ioas, idev, 0,
-                                               immediate_attach, NULL);
+       hwpt_paging = iommufd_hwpt_paging_alloc(idev->ictx, ioas, idev, pasid,
+                                               0, immediate_attach, NULL);
        if (IS_ERR(hwpt_paging)) {
                destroy_hwpt = ERR_CAST(hwpt_paging);
                goto out_unlock;
@@ -720,7 +730,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
        hwpt = &hwpt_paging->common;
 
        if (!immediate_attach) {
-               destroy_hwpt = (*do_attach)(idev, hwpt);
+               destroy_hwpt = (*do_attach)(idev, pasid, hwpt);
                if (IS_ERR(destroy_hwpt))
                        goto out_abort;
        } else {
@@ -741,8 +751,9 @@ out_unlock:
        return destroy_hwpt;
 }
 
-static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id,
-                                   attach_fn do_attach)
+static int iommufd_device_change_pt(struct iommufd_device *idev,
+                                   ioasid_t pasid,
+                                   u32 *pt_id, attach_fn do_attach)
 {
        struct iommufd_hw_pagetable *destroy_hwpt;
        struct iommufd_object *pt_obj;
@@ -757,7 +768,7 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id,
                struct iommufd_hw_pagetable *hwpt =
                        container_of(pt_obj, struct iommufd_hw_pagetable, obj);
 
-               destroy_hwpt = (*do_attach)(idev, hwpt);
+               destroy_hwpt = (*do_attach)(idev, pasid, hwpt);
                if (IS_ERR(destroy_hwpt))
                        goto out_put_pt_obj;
                break;
@@ -766,8 +777,8 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id,
                struct iommufd_ioas *ioas =
                        container_of(pt_obj, struct iommufd_ioas, obj);
 
-               destroy_hwpt = iommufd_device_auto_get_domain(idev, ioas, pt_id,
-                                                             do_attach);
+               destroy_hwpt = iommufd_device_auto_get_domain(idev, pasid, ioas,
+                                                             pt_id, do_attach);
                if (IS_ERR(destroy_hwpt))
                        goto out_put_pt_obj;
                break;
@@ -804,7 +815,8 @@ int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id)
 {
        int rc;
 
-       rc = iommufd_device_change_pt(idev, pt_id, &iommufd_device_do_attach);
+       rc = iommufd_device_change_pt(idev, IOMMU_NO_PASID, pt_id,
+                                     &iommufd_device_do_attach);
        if (rc)
                return rc;
 
@@ -834,7 +846,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, "IOMMUFD");
  */
 int iommufd_device_replace(struct iommufd_device *idev, u32 *pt_id)
 {
-       return iommufd_device_change_pt(idev, pt_id,
+       return iommufd_device_change_pt(idev, IOMMU_NO_PASID, pt_id,
                                        &iommufd_device_do_replace);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_device_replace, "IOMMUFD");
@@ -850,7 +862,7 @@ void iommufd_device_detach(struct iommufd_device *idev)
 {
        struct iommufd_hw_pagetable *hwpt;
 
-       hwpt = iommufd_hw_pagetable_detach(idev);
+       hwpt = iommufd_hw_pagetable_detach(idev, IOMMU_NO_PASID);
        iommufd_hw_pagetable_put(idev->ictx, hwpt);
        refcount_dec(&idev->obj.users);
 }
index 8e87ae71e1284a5a76825999a48f039333c5f53a..bd9dd26a52950a72f25cda987156f35230945ac5 100644 (file)
@@ -90,6 +90,7 @@ iommufd_hwpt_paging_enforce_cc(struct iommufd_hwpt_paging *hwpt_paging)
  * @ictx: iommufd context
  * @ioas: IOAS to associate the domain with
  * @idev: Device to get an iommu_domain for
+ * @pasid: PASID to get an iommu_domain for
  * @flags: Flags from userspace
  * @immediate_attach: True if idev should be attached to the hwpt
  * @user_data: The user provided driver specific data describing the domain to
@@ -105,8 +106,8 @@ iommufd_hwpt_paging_enforce_cc(struct iommufd_hwpt_paging *hwpt_paging)
  */
 struct iommufd_hwpt_paging *
 iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
-                         struct iommufd_device *idev, u32 flags,
-                         bool immediate_attach,
+                         struct iommufd_device *idev, ioasid_t pasid,
+                         u32 flags, bool immediate_attach,
                          const struct iommu_user_data *user_data)
 {
        const u32 valid_flags = IOMMU_HWPT_ALLOC_NEST_PARENT |
@@ -189,7 +190,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
         * sequence. Once those drivers are fixed this should be removed.
         */
        if (immediate_attach) {
-               rc = iommufd_hw_pagetable_attach(hwpt, idev);
+               rc = iommufd_hw_pagetable_attach(hwpt, idev, pasid);
                if (rc)
                        goto out_abort;
        }
@@ -202,7 +203,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
 
 out_detach:
        if (immediate_attach)
-               iommufd_hw_pagetable_detach(idev);
+               iommufd_hw_pagetable_detach(idev, pasid);
 out_abort:
        iommufd_object_abort_and_destroy(ictx, &hwpt->obj);
        return ERR_PTR(rc);
@@ -364,8 +365,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
                ioas = container_of(pt_obj, struct iommufd_ioas, obj);
                mutex_lock(&ioas->mutex);
                hwpt_paging = iommufd_hwpt_paging_alloc(
-                       ucmd->ictx, ioas, idev, cmd->flags, false,
-                       user_data.len ? &user_data : NULL);
+                       ucmd->ictx, ioas, idev, IOMMU_NO_PASID, cmd->flags,
+                       false, user_data.len ? &user_data : NULL);
                if (IS_ERR(hwpt_paging)) {
                        rc = PTR_ERR(hwpt_paging);
                        goto out_unlock;
index 8c49ca16919a247b09d068886f5603ccac10bc36..891800948d1a67cab75c25e4f34e5ba880f1f990 100644 (file)
@@ -369,13 +369,13 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd);
 
 struct iommufd_hwpt_paging *
 iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
-                         struct iommufd_device *idev, u32 flags,
-                         bool immediate_attach,
+                         struct iommufd_device *idev, ioasid_t pasid,
+                         u32 flags, bool immediate_attach,
                          const struct iommu_user_data *user_data);
 int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
-                               struct iommufd_device *idev);
+                               struct iommufd_device *idev, ioasid_t pasid);
 struct iommufd_hw_pagetable *
-iommufd_hw_pagetable_detach(struct iommufd_device *idev);
+iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid);
 void iommufd_hwpt_paging_destroy(struct iommufd_object *obj);
 void iommufd_hwpt_paging_abort(struct iommufd_object *obj);
 void iommufd_hwpt_nested_destroy(struct iommufd_object *obj);