Commit 4b042357 authored by Liu, Yi L's avatar Liu, Yi L Committed by Zheng Zengkai
Browse files

vfio: VFIO_IOMMU_SET_PASID_TABLE

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I401IF


CVE: NA

------------------------------

This patch adds an VFIO_IOMMU_SET_PASID_TABLE ioctl
which aims to pass the virtual iommu guest configuration
to the host. This latter takes the form of the so-called
PASID table.

Signed-off-by: default avatarJacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: default avatarLiu, Yi L <yi.l.liu@linux.intel.com>
Signed-off-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarKunkun <Jiang&lt;jiangkunkun@huawei.com>
Reviewed-by: default avatarKeqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 7733f2e7
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -3018,6 +3018,39 @@ static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
	return ret;
}

static void
vfio_detach_pasid_table(struct vfio_iommu *iommu)
{
	struct vfio_domain *d;

	mutex_lock(&iommu->lock);
	list_for_each_entry(d, &iommu->domain_list, next)
		iommu_detach_pasid_table(d->domain);

	mutex_unlock(&iommu->lock);
}

static int
vfio_attach_pasid_table(struct vfio_iommu *iommu, unsigned long arg)
{
	struct vfio_domain *d;
	int ret = 0;

	mutex_lock(&iommu->lock);

	list_for_each_entry(d, &iommu->domain_list, next) {
		ret = iommu_uapi_attach_pasid_table(d->domain, (void __user *)arg);
		if (ret) {
			list_for_each_entry_continue_reverse(d, &iommu->domain_list, next)
				iommu_detach_pasid_table(d->domain);
			break;
		}
	}

	mutex_unlock(&iommu->lock);
	return ret;
}

static int vfio_iommu_migration_build_caps(struct vfio_iommu *iommu,
					   struct vfio_info_cap *caps)
{
@@ -3456,6 +3489,29 @@ static long vfio_iommu_type1_unbind(struct vfio_iommu *iommu, unsigned long arg)
	return 0;
}

static int vfio_iommu_type1_set_pasid_table(struct vfio_iommu *iommu,
					    unsigned long arg)
{
	struct vfio_iommu_type1_set_pasid_table spt;
	unsigned long minsz;

	minsz = offsetofend(struct vfio_iommu_type1_set_pasid_table, flags);

	if (copy_from_user(&spt, (void __user *)arg, minsz))
		return -EFAULT;

	if (spt.argsz < minsz)
		return -EINVAL;

	if (spt.flags == VFIO_PASID_TABLE_FLAG_SET) {
		return vfio_attach_pasid_table(iommu, arg + minsz);
	} else if (spt.flags == VFIO_PASID_TABLE_FLAG_UNSET) {
		vfio_detach_pasid_table(iommu);
		return 0;
	}
	return -EINVAL;
}

static long vfio_iommu_type1_ioctl(void *iommu_data,
				   unsigned int cmd, unsigned long arg)
{
@@ -3476,6 +3532,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
		return vfio_iommu_type1_bind(iommu, arg);
	case VFIO_IOMMU_UNBIND:
		return vfio_iommu_type1_unbind(iommu, arg);
	case VFIO_IOMMU_SET_PASID_TABLE:
		return vfio_iommu_type1_set_pasid_table(iommu, arg);
	default:
		return -ENOTTY;
	}
+20 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/iommu.h>

#define VFIO_API_VERSION	0

@@ -1290,6 +1291,25 @@ struct vfio_iommu_type1_bind {
 */
#define VFIO_IOMMU_UNBIND	_IO(VFIO_TYPE, VFIO_BASE + 23)

/*
 * VFIO_IOMMU_SET_PASID_TABLE - _IOWR(VFIO_TYPE, VFIO_BASE + 18,
 *			struct vfio_iommu_type1_set_pasid_table)
 *
 * The SET operation passes a PASID table to the host while the
 * UNSET operation detaches the one currently programmed. It is
 * allowed to "SET" the table several times without unsetting as
 * long as the table config does not stay IOMMU_PASID_CONFIG_TRANSLATE.
 */
struct vfio_iommu_type1_set_pasid_table {
	__u32	argsz;
	__u32	flags;
#define VFIO_PASID_TABLE_FLAG_SET	(1 << 0)
#define VFIO_PASID_TABLE_FLAG_UNSET	(1 << 1)
	struct iommu_pasid_table_config config; /* used on SET */
};

#define VFIO_IOMMU_SET_PASID_TABLE	_IO(VFIO_TYPE, VFIO_BASE + 18)

/* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */

/*