Commit 54b47585 authored by Nicolin Chen's avatar Nicolin Chen Committed by Jason Gunthorpe
Browse files

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: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Tested-by: default avatarTerrence Xu <terrence.xu@intel.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Signed-off-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Signed-off-by: default avatarYi Liu <yi.l.liu@intel.com>
Acked-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 325de950
Loading
Loading
Loading
Loading
+30 −22
Original line number Diff line number Diff line
@@ -412,15 +412,17 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
	struct iommufd_access *access =
		container_of(obj, struct iommufd_access, obj);

	if (access->ioas) {
		iopt_remove_access(&access->ioas->iopt, access);
	iommufd_ctx_put(access->ictx);
		refcount_dec(&access->ioas->obj.users);
		access->ioas = NULL;
	}
	iommufd_ctx_put(access->ictx);
}

/**
 * iommufd_access_create - Create an iommufd_access
 * @ictx: iommufd file descriptor
 * @ioas_id: ID for a IOMMUFD_OBJ_IOAS
 * @ops: Driver's ops to associate with the access
 * @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().
 */
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
@@ -449,21 +449,10 @@ 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);
@@ -471,11 +460,6 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
	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);

@@ -494,6 +478,30 @@ 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;
	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
 * @iopt: iopt to work on
+4 −1
Original line number Diff line number Diff line
@@ -571,7 +571,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,
@@ -580,6 +580,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)
+17 −7
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -161,15 +170,16 @@ 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_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);
+2 −1
Original line number Diff line number Diff line
@@ -40,9 +40,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);