In case we detect the address space is translated by a virtual IOMMU which requires nested stages, let's set up the container with the VFIO_TYPE1_NESTING_IOMMU iommu_type.
Signed-off-by: Eric Auger <eric.au...@redhat.com> --- hw/vfio/common.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 39f400b077..53ff7a6b39 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1041,11 +1041,15 @@ static void vfio_put_address_space(VFIOAddressSpace *space) * nested only is selected if requested by @force_nested */ static int vfio_iommu_get_type(VFIOContainer *container, - Error **errp) + bool force_nested, Error **errp) { int fd = container->fd; - if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) { + if (force_nested && + ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_NESTING_IOMMU)) { + /* NESTED implies v2 */ + return VFIO_TYPE1_NESTING_IOMMU; + } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) { return VFIO_TYPE1v2_IOMMU; } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { return VFIO_TYPE1_IOMMU; @@ -1085,9 +1089,16 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, VFIOContainer *container; int ret, fd; VFIOAddressSpace *space; + IOMMUMemoryRegion *iommu_mr; int iommu_type; + bool force_nested = false; bool v2 = false; + if (as != &address_space_memory && memory_region_is_iommu(as->root)) { + iommu_mr = IOMMU_MEMORY_REGION(as->root); + memory_region_iommu_get_attr(iommu_mr, IOMMU_ATTR_VFIO_NESTED, + (void *)&force_nested); + } space = vfio_get_address_space(as); @@ -1148,12 +1159,18 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, QLIST_INIT(&container->giommu_list); QLIST_INIT(&container->hostwin_list); - iommu_type = vfio_iommu_get_type(container, errp); + iommu_type = vfio_iommu_get_type(container, force_nested, errp); if (iommu_type < 0) { goto free_container_exit; } + if (force_nested && iommu_type != VFIO_TYPE1_NESTING_IOMMU) { + error_setg(errp, "nested mode requested by the virtual IOMMU " + "but not supported by the vfio iommu"); + } + switch (iommu_type) { + case VFIO_TYPE1_NESTING_IOMMU: case VFIO_TYPE1v2_IOMMU: case VFIO_TYPE1_IOMMU: { -- 2.17.1