Skip to content

Commit

Permalink
iommufd: Create access in vfio_iommufd_emulated_bind()
Browse files Browse the repository at this point in the history
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.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
  • Loading branch information
nicolinc committed Mar 15, 2023
1 parent a5d8ac4 commit 34fba75
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
50 changes: 29 additions & 21 deletions drivers/iommu/iommufd/device.c
Expand Up @@ -625,9 +625,12 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
struct iommufd_access *access =
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);
refcount_dec(&access->ioas->obj.users);
}

/**
Expand All @@ -644,12 +647,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
* The provided ops are required to use iommufd_access_pin_pages().
*/
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)
{
struct iommufd_access *access;
struct iommufd_object *obj;
int rc;

/*
* There is no uAPI for the access object, but to keep things symmetric
Expand All @@ -662,33 +663,17 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
access->data = data;
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)
access->iova_alignment = PAGE_SIZE;
else
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() */
refcount_inc(&access->obj.users);
access->ictx = ictx;
iommufd_ctx_get(ictx);
iommufd_object_finalize(ictx, &access->obj);
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);

Expand All @@ -707,6 +692,29 @@ void iommufd_access_destroy(struct iommufd_access *access)
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);

int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
{
struct iommufd_ioas *new_ioas;
struct iommufd_object *obj;
int rc = 0;

obj = iommufd_get_object(access->ictx, ioas_id, IOMMUFD_OBJ_IOAS);
if (IS_ERR(obj))
return PTR_ERR(obj);
new_ioas = container_of(obj, struct iommufd_ioas, obj);

rc = iopt_add_access(&new_ioas->iopt, access);
if (rc) {
iommufd_put_object(obj);
return rc;
}
iommufd_ref_to_users(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
* @iopt: iopt to work on
Expand Down
5 changes: 4 additions & 1 deletion drivers/iommu/iommufd/selftest.c
Expand Up @@ -754,7 +754,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
}

access = iommufd_access_create(
ucmd->ictx, ioas_id,
ucmd->ictx,
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
&selftest_access_ops_pin :
&selftest_access_ops,
Expand All @@ -763,6 +763,9 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
rc = PTR_ERR(access);
goto out_put_fdno;
}
rc = iommufd_access_attach(access, ioas_id);
if (rc)
goto out_destroy;
cmd->create_access.out_access_fd = fdno;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
if (rc)
Expand Down
28 changes: 21 additions & 7 deletions drivers/vfio/iommufd.c
Expand Up @@ -138,10 +138,18 @@ static const struct iommufd_access_ops vfio_user_ops = {
int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id)
{
struct iommufd_access *user;

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

vdev->iommufd_ictx = 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;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
Expand All @@ -152,6 +160,7 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)

if (vdev->iommufd_access) {
iommufd_access_destroy(vdev->iommufd_access);
vdev->iommufd_attached = false;
vdev->iommufd_access = NULL;
}
iommufd_ctx_put(vdev->iommufd_ictx);
Expand All @@ -161,15 +170,20 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);

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);

user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops,
vdev);
if (IS_ERR(user))
return PTR_ERR(user);
vdev->iommufd_access = user;
if (!vdev->iommufd_ictx)
return -EINVAL;
if (!vdev->iommufd_access)
return -ENOENT;
if (vdev->iommufd_attached)
return -EBUSY;
rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
if (rc)
return rc;
vdev->iommufd_attached = true;
return 0;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);
3 changes: 2 additions & 1 deletion include/linux/iommufd.h
Expand Up @@ -41,9 +41,10 @@ enum {
};

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);
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);

Expand Down

0 comments on commit 34fba75

Please sign in to comment.