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>
This commit is contained in:
Nicolin Chen 2023-03-27 02:33:47 -07:00 committed by Jason Gunthorpe
parent 325de95029
commit 54b47585db
4 changed files with 53 additions and 31 deletions

View File

@ -412,15 +412,17 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
struct iommufd_access *access = struct iommufd_access *access =
container_of(obj, struct iommufd_access, obj); container_of(obj, struct iommufd_access, obj);
iopt_remove_access(&access->ioas->iopt, access); if (access->ioas) {
iopt_remove_access(&access->ioas->iopt, access);
refcount_dec(&access->ioas->obj.users);
access->ioas = NULL;
}
iommufd_ctx_put(access->ictx); iommufd_ctx_put(access->ictx);
refcount_dec(&access->ioas->obj.users);
} }
/** /**
* iommufd_access_create - Create an iommufd_access * iommufd_access_create - Create an iommufd_access
* @ictx: iommufd file descriptor * @ictx: iommufd file descriptor
* @ioas_id: ID for a IOMMUFD_OBJ_IOAS
* @ops: Driver's ops to associate with the access * @ops: Driver's ops to associate with the access
* @data: Opaque data to pass into ops functions * @data: Opaque data to pass into ops functions
* *
@ -431,12 +433,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
* The provided ops are required to use iommufd_access_pin_pages(). * The provided ops are required to use iommufd_access_pin_pages().
*/ */
struct iommufd_access * struct iommufd_access *
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id, iommufd_access_create(struct iommufd_ctx *ictx,
const struct iommufd_access_ops *ops, void *data) const struct iommufd_access_ops *ops, void *data)
{ {
struct iommufd_access *access; struct iommufd_access *access;
struct iommufd_object *obj;
int rc;
/* /*
* There is no uAPI for the access object, but to keep things symmetric * There is no uAPI for the access object, but to keep things symmetric
@ -449,21 +449,10 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
access->data = data; access->data = data;
access->ops = ops; access->ops = ops;
obj = iommufd_get_object(ictx, ioas_id, IOMMUFD_OBJ_IOAS);
if (IS_ERR(obj)) {
rc = PTR_ERR(obj);
goto out_abort;
}
access->ioas = container_of(obj, struct iommufd_ioas, obj);
iommufd_ref_to_users(obj);
if (ops->needs_pin_pages) if (ops->needs_pin_pages)
access->iova_alignment = PAGE_SIZE; access->iova_alignment = PAGE_SIZE;
else else
access->iova_alignment = 1; access->iova_alignment = 1;
rc = iopt_add_access(&access->ioas->iopt, access);
if (rc)
goto out_put_ioas;
/* The calling driver is a user until iommufd_access_destroy() */ /* The calling driver is a user until iommufd_access_destroy() */
refcount_inc(&access->obj.users); refcount_inc(&access->obj.users);
@ -471,11 +460,6 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
iommufd_ctx_get(ictx); iommufd_ctx_get(ictx);
iommufd_object_finalize(ictx, &access->obj); iommufd_object_finalize(ictx, &access->obj);
return access; return access;
out_put_ioas:
refcount_dec(&access->ioas->obj.users);
out_abort:
iommufd_object_abort(ictx, &access->obj);
return ERR_PTR(rc);
} }
EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD); EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
@ -494,6 +478,30 @@ void iommufd_access_destroy(struct iommufd_access *access)
} }
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD); EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
{
struct iommufd_ioas *new_ioas;
int rc = 0;
if (access->ioas)
return -EINVAL;
new_ioas = iommufd_get_ioas(access->ictx, ioas_id);
if (IS_ERR(new_ioas))
return PTR_ERR(new_ioas);
rc = iopt_add_access(&new_ioas->iopt, access);
if (rc) {
iommufd_put_object(&new_ioas->obj);
return rc;
}
iommufd_ref_to_users(&new_ioas->obj);
access->ioas = new_ioas;
return 0;
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
/** /**
* iommufd_access_notify_unmap - Notify users of an iopt to stop using it * iommufd_access_notify_unmap - Notify users of an iopt to stop using it
* @iopt: iopt to work on * @iopt: iopt to work on

View File

@ -571,7 +571,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
} }
access = iommufd_access_create( access = iommufd_access_create(
ucmd->ictx, ioas_id, ucmd->ictx,
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ? (flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
&selftest_access_ops_pin : &selftest_access_ops_pin :
&selftest_access_ops, &selftest_access_ops,
@ -580,6 +580,9 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
rc = PTR_ERR(access); rc = PTR_ERR(access);
goto out_put_fdno; goto out_put_fdno;
} }
rc = iommufd_access_attach(access, ioas_id);
if (rc)
goto out_destroy;
cmd->create_access.out_access_fd = fdno; cmd->create_access.out_access_fd = fdno;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
if (rc) if (rc)

View File

@ -138,10 +138,18 @@ static const struct iommufd_access_ops vfio_user_ops = {
int vfio_iommufd_emulated_bind(struct vfio_device *vdev, int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id) struct iommufd_ctx *ictx, u32 *out_device_id)
{ {
struct iommufd_access *user;
lockdep_assert_held(&vdev->dev_set->lock); lockdep_assert_held(&vdev->dev_set->lock);
vdev->iommufd_ictx = ictx;
iommufd_ctx_get(ictx); iommufd_ctx_get(ictx);
user = iommufd_access_create(ictx, &vfio_user_ops, vdev);
if (IS_ERR(user)) {
iommufd_ctx_put(ictx);
return PTR_ERR(user);
}
vdev->iommufd_access = user;
vdev->iommufd_ictx = ictx;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind); EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
@ -152,6 +160,7 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
if (vdev->iommufd_access) { if (vdev->iommufd_access) {
iommufd_access_destroy(vdev->iommufd_access); iommufd_access_destroy(vdev->iommufd_access);
vdev->iommufd_attached = false;
vdev->iommufd_access = NULL; vdev->iommufd_access = NULL;
} }
iommufd_ctx_put(vdev->iommufd_ictx); iommufd_ctx_put(vdev->iommufd_ictx);
@ -161,15 +170,16 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id) int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
{ {
struct iommufd_access *user; int rc;
lockdep_assert_held(&vdev->dev_set->lock); lockdep_assert_held(&vdev->dev_set->lock);
user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops, if (vdev->iommufd_attached)
vdev); return -EBUSY;
if (IS_ERR(user)) rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
return PTR_ERR(user); if (rc)
vdev->iommufd_access = user; return rc;
vdev->iommufd_attached = true;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas); EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);

View File

@ -40,9 +40,10 @@ enum {
}; };
struct iommufd_access * struct iommufd_access *
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id, iommufd_access_create(struct iommufd_ctx *ictx,
const struct iommufd_access_ops *ops, void *data); const struct iommufd_access_ops *ops, void *data);
void iommufd_access_destroy(struct iommufd_access *access); void iommufd_access_destroy(struct iommufd_access *access);
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
void iommufd_ctx_get(struct iommufd_ctx *ictx); void iommufd_ctx_get(struct iommufd_ctx *ictx);