Commit f5c9eceb authored by Will Deacon's avatar Will Deacon Committed by Alex Williamson

vfio/iommu_type1: add new VFIO_TYPE1_NESTING_IOMMU IOMMU type

VFIO allows devices to be safely handed off to userspace by putting
them behind an IOMMU configured to ensure DMA and interrupt isolation.
This enables userspace KVM clients, such as kvmtool and qemu, to further
map the device into a virtual machine.

With IOMMUs such as the ARM SMMU, it is then possible to provide SMMU
translation services to the guest operating system, which are nested
with the existing translation installed by VFIO. However, enabling this
feature means that the IOMMU driver must be informed that the VFIO domain
is being created for the purposes of nested translation.

This patch adds a new IOMMU type (VFIO_TYPE1_NESTING_IOMMU) to the VFIO
type-1 driver. The new IOMMU type acts identically to the
VFIO_TYPE1v2_IOMMU type, but additionally sets the DOMAIN_ATTR_NESTING
attribute on its IOMMU domains.

Cc: Joerg Roedel <joro@8bytes.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent c02607aa
...@@ -57,7 +57,8 @@ struct vfio_iommu { ...@@ -57,7 +57,8 @@ struct vfio_iommu {
struct list_head domain_list; struct list_head domain_list;
struct mutex lock; struct mutex lock;
struct rb_root dma_list; struct rb_root dma_list;
bool v2; bool v2;
bool nesting;
}; };
struct vfio_domain { struct vfio_domain {
...@@ -705,6 +706,15 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, ...@@ -705,6 +706,15 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
goto out_free; goto out_free;
} }
if (iommu->nesting) {
int attr = 1;
ret = iommu_domain_set_attr(domain->domain, DOMAIN_ATTR_NESTING,
&attr);
if (ret)
goto out_domain;
}
ret = iommu_attach_group(domain->domain, iommu_group); ret = iommu_attach_group(domain->domain, iommu_group);
if (ret) if (ret)
goto out_domain; goto out_domain;
...@@ -819,17 +829,26 @@ static void *vfio_iommu_type1_open(unsigned long arg) ...@@ -819,17 +829,26 @@ static void *vfio_iommu_type1_open(unsigned long arg)
{ {
struct vfio_iommu *iommu; struct vfio_iommu *iommu;
if (arg != VFIO_TYPE1_IOMMU && arg != VFIO_TYPE1v2_IOMMU)
return ERR_PTR(-EINVAL);
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
if (!iommu) if (!iommu)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
switch (arg) {
case VFIO_TYPE1_IOMMU:
break;
case VFIO_TYPE1_NESTING_IOMMU:
iommu->nesting = true;
case VFIO_TYPE1v2_IOMMU:
iommu->v2 = true;
break;
default:
kfree(iommu);
return ERR_PTR(-EINVAL);
}
INIT_LIST_HEAD(&iommu->domain_list); INIT_LIST_HEAD(&iommu->domain_list);
iommu->dma_list = RB_ROOT; iommu->dma_list = RB_ROOT;
mutex_init(&iommu->lock); mutex_init(&iommu->lock);
iommu->v2 = (arg == VFIO_TYPE1v2_IOMMU);
return iommu; return iommu;
} }
...@@ -885,6 +904,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, ...@@ -885,6 +904,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
switch (arg) { switch (arg) {
case VFIO_TYPE1_IOMMU: case VFIO_TYPE1_IOMMU:
case VFIO_TYPE1v2_IOMMU: case VFIO_TYPE1v2_IOMMU:
case VFIO_TYPE1_NESTING_IOMMU:
return 1; return 1;
case VFIO_DMA_CC_IOMMU: case VFIO_DMA_CC_IOMMU:
if (!iommu) if (!iommu)
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
/* Check if EEH is supported */ /* Check if EEH is supported */
#define VFIO_EEH 5 #define VFIO_EEH 5
/* Two-stage IOMMU */
#define VFIO_TYPE1_NESTING_IOMMU 6 /* Implies v2 */
/* /*
* The IOCTL interface is designed for extensibility by embedding the * The IOCTL interface is designed for extensibility by embedding the
* structure length (argsz) and flags into structures passed between * structure length (argsz) and flags into structures passed between
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment