Commit ad744ed5 authored by Yi Liu's avatar Yi Liu Committed by Jason Gunthorpe
Browse files

vfio: VFIO_DEVICE_[AT|DE]TACH_IOMMUFD_PT support pasid

This extends the VFIO_DEVICE_[AT|DE]TACH_IOMMUFD_PT ioctls to attach/detach
a given pasid of a vfio device to/from an IOAS/HWPT.

Link: https://patch.msgid.link/r/20250321180143.8468-4-yi.l.liu@intel.com


Reviewed-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Signed-off-by: default avatarYi Liu <yi.l.liu@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 29064134
Loading
Loading
Loading
Loading
+52 −8
Original line number Diff line number Diff line
@@ -162,9 +162,9 @@ void vfio_df_unbind_iommufd(struct vfio_device_file *df)
int vfio_df_ioctl_attach_pt(struct vfio_device_file *df,
			    struct vfio_device_attach_iommufd_pt __user *arg)
{
	struct vfio_device *device = df->device;
	struct vfio_device_attach_iommufd_pt attach;
	unsigned long minsz;
	struct vfio_device *device = df->device;
	unsigned long minsz, xend = 0;
	int ret;

	minsz = offsetofend(struct vfio_device_attach_iommufd_pt, pt_id);
@@ -172,10 +172,33 @@ int vfio_df_ioctl_attach_pt(struct vfio_device_file *df,
	if (copy_from_user(&attach, arg, minsz))
		return -EFAULT;

	if (attach.argsz < minsz || attach.flags)
	if (attach.argsz < minsz)
		return -EINVAL;

	if (attach.flags & ~VFIO_DEVICE_ATTACH_PASID)
		return -EINVAL;

	if (attach.flags & VFIO_DEVICE_ATTACH_PASID) {
		if (!device->ops->pasid_attach_ioas)
			return -EOPNOTSUPP;
		xend = offsetofend(struct vfio_device_attach_iommufd_pt, pasid);
	}

	if (xend) {
		if (attach.argsz < xend)
			return -EINVAL;

		if (copy_from_user((void *)&attach + minsz,
				   (void __user *)arg + minsz, xend - minsz))
			return -EFAULT;
	}

	mutex_lock(&device->dev_set->lock);
	if (attach.flags & VFIO_DEVICE_ATTACH_PASID)
		ret = device->ops->pasid_attach_ioas(device,
						     attach.pasid,
						     &attach.pt_id);
	else
		ret = device->ops->attach_ioas(device, &attach.pt_id);
	if (ret)
		goto out_unlock;
@@ -198,19 +221,40 @@ int vfio_df_ioctl_attach_pt(struct vfio_device_file *df,
int vfio_df_ioctl_detach_pt(struct vfio_device_file *df,
			    struct vfio_device_detach_iommufd_pt __user *arg)
{
	struct vfio_device *device = df->device;
	struct vfio_device_detach_iommufd_pt detach;
	unsigned long minsz;
	struct vfio_device *device = df->device;
	unsigned long minsz, xend = 0;

	minsz = offsetofend(struct vfio_device_detach_iommufd_pt, flags);

	if (copy_from_user(&detach, arg, minsz))
		return -EFAULT;

	if (detach.argsz < minsz || detach.flags)
	if (detach.argsz < minsz)
		return -EINVAL;

	if (detach.flags & ~VFIO_DEVICE_DETACH_PASID)
		return -EINVAL;

	if (detach.flags & VFIO_DEVICE_DETACH_PASID) {
		if (!device->ops->pasid_detach_ioas)
			return -EOPNOTSUPP;
		xend = offsetofend(struct vfio_device_detach_iommufd_pt, pasid);
	}

	if (xend) {
		if (detach.argsz < xend)
			return -EINVAL;

		if (copy_from_user((void *)&detach + minsz,
				   (void __user *)arg + minsz, xend - minsz))
			return -EFAULT;
	}

	mutex_lock(&device->dev_set->lock);
	if (detach.flags & VFIO_DEVICE_DETACH_PASID)
		device->ops->pasid_detach_ioas(device, detach.pasid);
	else
		device->ops->detach_ioas(device);
	mutex_unlock(&device->dev_set->lock);

+19 −10
Original line number Diff line number Diff line
@@ -931,29 +931,34 @@ struct vfio_device_bind_iommufd {
 * VFIO_DEVICE_ATTACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 19,
 *					struct vfio_device_attach_iommufd_pt)
 * @argsz:	User filled size of this data.
 * @flags:	Must be 0.
 * @flags:	Flags for attach.
 * @pt_id:	Input the target id which can represent an ioas or a hwpt
 *		allocated via iommufd subsystem.
 *		Output the input ioas id or the attached hwpt id which could
 *		be the specified hwpt itself or a hwpt automatically created
 *		for the specified ioas by kernel during the attachment.
 * @pasid:	The pasid to be attached, only meaningful when
 *		VFIO_DEVICE_ATTACH_PASID is set in @flags
 *
 * Associate the device with an address space within the bound iommufd.
 * Undo by VFIO_DEVICE_DETACH_IOMMUFD_PT or device fd close.  This is only
 * allowed on cdev fds.
 *
 * If a vfio device is currently attached to a valid hw_pagetable, without doing
 * a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl
 * passing in another hw_pagetable (hwpt) id is allowed. This action, also known
 * as a hw_pagetable replacement, will replace the device's currently attached
 * hw_pagetable with a new hw_pagetable corresponding to the given pt_id.
 * If a vfio device or a pasid of this device is currently attached to a valid
 * hw_pagetable (hwpt), without doing a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second
 * VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl passing in another hwpt id is allowed.
 * This action, also known as a hw_pagetable replacement, will replace the
 * currently attached hwpt of the device or the pasid of this device with a new
 * hwpt corresponding to the given pt_id.
 *
 * Return: 0 on success, -errno on failure.
 */
struct vfio_device_attach_iommufd_pt {
	__u32	argsz;
	__u32	flags;
#define VFIO_DEVICE_ATTACH_PASID	(1 << 0)
	__u32	pt_id;
	__u32	pasid;
};

#define VFIO_DEVICE_ATTACH_IOMMUFD_PT		_IO(VFIO_TYPE, VFIO_BASE + 19)
@@ -962,17 +967,21 @@ struct vfio_device_attach_iommufd_pt {
 * VFIO_DEVICE_DETACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 20,
 *					struct vfio_device_detach_iommufd_pt)
 * @argsz:	User filled size of this data.
 * @flags:	Must be 0.
 * @flags:	Flags for detach.
 * @pasid:	The pasid to be detached, only meaningful when
 *		VFIO_DEVICE_DETACH_PASID is set in @flags
 *
 * Remove the association of the device and its current associated address
 * space.  After it, the device should be in a blocking DMA state.  This is only
 * allowed on cdev fds.
 * Remove the association of the device or a pasid of the device and its current
 * associated address space.  After it, the device or the pasid should be in a
 * blocking DMA state.  This is only allowed on cdev fds.
 *
 * Return: 0 on success, -errno on failure.
 */
struct vfio_device_detach_iommufd_pt {
	__u32	argsz;
	__u32	flags;
#define VFIO_DEVICE_DETACH_PASID	(1 << 0)
	__u32	pasid;
};

#define VFIO_DEVICE_DETACH_IOMMUFD_PT		_IO(VFIO_TYPE, VFIO_BASE + 20)