Skip to content

Commit 54b4758

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd: Create access in vfio_iommufd_emulated_bind()
There are needs to created iommufd_access prior to have an IOAS and set IOAS later. Like the vfio device cdev needs to have an iommufd object to represent the bond (iommufd_access) and IOAS replacement. Moves the iommufd_access_create() call into vfio_iommufd_emulated_bind(), making it symmetric with the __vfio_iommufd_access_destroy() call in the vfio_iommufd_emulated_unbind(). This means an access is created/destroyed by the bind()/unbind(), and the vfio_iommufd_emulated_attach_ioas() only updates the access->ioas pointer. Since vfio_iommufd_emulated_bind() does not provide ioas_id, drop it from the argument list of iommufd_access_create(). Instead, add a new access API iommufd_access_attach() to set the access->ioas pointer. Also, set vdev->iommufd_attached accordingly, similar to the physical pathway. Link: https://lore.kernel.org/r/20230327093351.44505-3-yi.l.liu@intel.com Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Tested-by: Terrence Xu <terrence.xu@intel.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Yi Liu <yi.l.liu@intel.com> Acked-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 325de95 commit 54b4758

4 files changed

Lines changed: 53 additions & 31 deletions

File tree

drivers/iommu/iommufd/device.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -412,15 +412,17 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
412412
struct iommufd_access *access =
413413
container_of(obj, struct iommufd_access, obj);
414414

415-
iopt_remove_access(&access->ioas->iopt, access);
415+
if (access->ioas) {
416+
iopt_remove_access(&access->ioas->iopt, access);
417+
refcount_dec(&access->ioas->obj.users);
418+
access->ioas = NULL;
419+
}
416420
iommufd_ctx_put(access->ictx);
417-
refcount_dec(&access->ioas->obj.users);
418421
}
419422

420423
/**
421424
* iommufd_access_create - Create an iommufd_access
422425
* @ictx: iommufd file descriptor
423-
* @ioas_id: ID for a IOMMUFD_OBJ_IOAS
424426
* @ops: Driver's ops to associate with the access
425427
* @data: Opaque data to pass into ops functions
426428
*
@@ -431,12 +433,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
431433
* The provided ops are required to use iommufd_access_pin_pages().
432434
*/
433435
struct iommufd_access *
434-
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
436+
iommufd_access_create(struct iommufd_ctx *ictx,
435437
const struct iommufd_access_ops *ops, void *data)
436438
{
437439
struct iommufd_access *access;
438-
struct iommufd_object *obj;
439-
int rc;
440440

441441
/*
442442
* There is no uAPI for the access object, but to keep things symmetric
@@ -449,33 +449,17 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
449449
access->data = data;
450450
access->ops = ops;
451451

452-
obj = iommufd_get_object(ictx, ioas_id, IOMMUFD_OBJ_IOAS);
453-
if (IS_ERR(obj)) {
454-
rc = PTR_ERR(obj);
455-
goto out_abort;
456-
}
457-
access->ioas = container_of(obj, struct iommufd_ioas, obj);
458-
iommufd_ref_to_users(obj);
459-
460452
if (ops->needs_pin_pages)
461453
access->iova_alignment = PAGE_SIZE;
462454
else
463455
access->iova_alignment = 1;
464-
rc = iopt_add_access(&access->ioas->iopt, access);
465-
if (rc)
466-
goto out_put_ioas;
467456

468457
/* The calling driver is a user until iommufd_access_destroy() */
469458
refcount_inc(&access->obj.users);
470459
access->ictx = ictx;
471460
iommufd_ctx_get(ictx);
472461
iommufd_object_finalize(ictx, &access->obj);
473462
return access;
474-
out_put_ioas:
475-
refcount_dec(&access->ioas->obj.users);
476-
out_abort:
477-
iommufd_object_abort(ictx, &access->obj);
478-
return ERR_PTR(rc);
479463
}
480464
EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
481465

@@ -494,6 +478,30 @@ void iommufd_access_destroy(struct iommufd_access *access)
494478
}
495479
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
496480

481+
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
482+
{
483+
struct iommufd_ioas *new_ioas;
484+
int rc = 0;
485+
486+
if (access->ioas)
487+
return -EINVAL;
488+
489+
new_ioas = iommufd_get_ioas(access->ictx, ioas_id);
490+
if (IS_ERR(new_ioas))
491+
return PTR_ERR(new_ioas);
492+
493+
rc = iopt_add_access(&new_ioas->iopt, access);
494+
if (rc) {
495+
iommufd_put_object(&new_ioas->obj);
496+
return rc;
497+
}
498+
iommufd_ref_to_users(&new_ioas->obj);
499+
500+
access->ioas = new_ioas;
501+
return 0;
502+
}
503+
EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
504+
497505
/**
498506
* iommufd_access_notify_unmap - Notify users of an iopt to stop using it
499507
* @iopt: iopt to work on

drivers/iommu/iommufd/selftest.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
571571
}
572572

573573
access = iommufd_access_create(
574-
ucmd->ictx, ioas_id,
574+
ucmd->ictx,
575575
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
576576
&selftest_access_ops_pin :
577577
&selftest_access_ops,
@@ -580,6 +580,9 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
580580
rc = PTR_ERR(access);
581581
goto out_put_fdno;
582582
}
583+
rc = iommufd_access_attach(access, ioas_id);
584+
if (rc)
585+
goto out_destroy;
583586
cmd->create_access.out_access_fd = fdno;
584587
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
585588
if (rc)

drivers/vfio/iommufd.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,18 @@ static const struct iommufd_access_ops vfio_user_ops = {
138138
int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
139139
struct iommufd_ctx *ictx, u32 *out_device_id)
140140
{
141+
struct iommufd_access *user;
142+
141143
lockdep_assert_held(&vdev->dev_set->lock);
142144

143-
vdev->iommufd_ictx = ictx;
144145
iommufd_ctx_get(ictx);
146+
user = iommufd_access_create(ictx, &vfio_user_ops, vdev);
147+
if (IS_ERR(user)) {
148+
iommufd_ctx_put(ictx);
149+
return PTR_ERR(user);
150+
}
151+
vdev->iommufd_access = user;
152+
vdev->iommufd_ictx = ictx;
145153
return 0;
146154
}
147155
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
@@ -152,6 +160,7 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
152160

153161
if (vdev->iommufd_access) {
154162
iommufd_access_destroy(vdev->iommufd_access);
163+
vdev->iommufd_attached = false;
155164
vdev->iommufd_access = NULL;
156165
}
157166
iommufd_ctx_put(vdev->iommufd_ictx);
@@ -161,15 +170,16 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
161170

162171
int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
163172
{
164-
struct iommufd_access *user;
173+
int rc;
165174

166175
lockdep_assert_held(&vdev->dev_set->lock);
167176

168-
user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops,
169-
vdev);
170-
if (IS_ERR(user))
171-
return PTR_ERR(user);
172-
vdev->iommufd_access = user;
177+
if (vdev->iommufd_attached)
178+
return -EBUSY;
179+
rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
180+
if (rc)
181+
return rc;
182+
vdev->iommufd_attached = true;
173183
return 0;
174184
}
175185
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);

include/linux/iommufd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ enum {
4040
};
4141

4242
struct iommufd_access *
43-
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
43+
iommufd_access_create(struct iommufd_ctx *ictx,
4444
const struct iommufd_access_ops *ops, void *data);
4545
void iommufd_access_destroy(struct iommufd_access *access);
46+
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
4647

4748
void iommufd_ctx_get(struct iommufd_ctx *ictx);
4849

0 commit comments

Comments
 (0)