Skip to content
Permalink
Browse files
vfio: VFIO_IOMMU_SET_PASID_TABLE
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: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Liu, Yi L <yi.l.liu@linux.intel.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
  • Loading branch information
Liu, Yi L authored and intel-lab-lkp committed Apr 11, 2021
1 parent e49d033 commit 0af9db19db29eb2a707b9e1ca4ff9e1a08a1c511
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
@@ -2834,6 +2834,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)
{
@@ -3002,6 +3035,29 @@ static int vfio_iommu_type1_unmap_dma(struct vfio_iommu *iommu,
-EFAULT : 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 int vfio_iommu_type1_dirty_pages(struct vfio_iommu *iommu,
unsigned long arg)
{
@@ -3122,6 +3178,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
return vfio_iommu_type1_unmap_dma(iommu, arg);
case VFIO_IOMMU_DIRTY_PAGES:
return vfio_iommu_type1_dirty_pages(iommu, arg);
case VFIO_IOMMU_SET_PASID_TABLE:
return vfio_iommu_type1_set_pasid_table(iommu, arg);
default:
return -ENOTTY;
}
@@ -14,6 +14,7 @@

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

#define VFIO_API_VERSION 0

@@ -1208,6 +1209,25 @@ struct vfio_iommu_type1_dirty_bitmap_get {

#define VFIO_IOMMU_DIRTY_PAGES _IO(VFIO_TYPE, VFIO_BASE + 17)

/*
* 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 -------- */

/*

0 comments on commit 0af9db1

Please sign in to comment.