diff --git a/vfio-Force-nested-if-iommu-requires-it.patch b/vfio-Force-nested-if-iommu-requires-it.patch new file mode 100644 index 0000000..6a6b9da --- /dev/null +++ b/vfio-Force-nested-if-iommu-requires-it.patch @@ -0,0 +1,100 @@ +From e4122a95a30cd58e1cd6e1742928e68aa94fd7ee Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Tue, 28 Aug 2018 16:16:20 +0200 +Subject: [PATCH] vfio: Force nested if iommu requires it + +In case we detect the address space is translated by +a virtual IOMMU which requires HW nested paging to +integrate with VFIO, let's set up the container with +the VFIO_TYPE1_NESTING_IOMMU iommu_type. + +Signed-off-by: Eric Auger +Signed-off-by: Kunkun Jiang +--- + hw/vfio/common.c | 36 ++++++++++++++++++++++++++++-------- + 1 file changed, 28 insertions(+), 8 deletions(-) + +diff --git a/hw/vfio/common.c b/hw/vfio/common.c +index fefa2ccfdf..c78b58d365 100644 +--- a/hw/vfio/common.c ++++ b/hw/vfio/common.c +@@ -1683,27 +1683,38 @@ static void vfio_put_address_space(VFIOAddressSpace *space) + * vfio_get_iommu_type - selects the richest iommu_type (v2 first) + */ + static int vfio_get_iommu_type(VFIOContainer *container, ++ bool want_nested, + Error **errp) + { +- int iommu_types[] = { VFIO_TYPE1v2_IOMMU, VFIO_TYPE1_IOMMU, ++ int iommu_types[] = { VFIO_TYPE1_NESTING_IOMMU, ++ VFIO_TYPE1v2_IOMMU, VFIO_TYPE1_IOMMU, + VFIO_SPAPR_TCE_v2_IOMMU, VFIO_SPAPR_TCE_IOMMU }; +- int i; ++ int i, ret = -EINVAL; + + for (i = 0; i < ARRAY_SIZE(iommu_types); i++) { + if (ioctl(container->fd, VFIO_CHECK_EXTENSION, iommu_types[i])) { +- return iommu_types[i]; ++ if (iommu_types[i] == VFIO_TYPE1_NESTING_IOMMU && !want_nested) { ++ continue; ++ } ++ ret = iommu_types[i]; ++ break; + } + } +- error_setg(errp, "No available IOMMU models"); +- return -EINVAL; ++ if (ret < 0) { ++ error_setg(errp, "No available IOMMU models"); ++ } else if (want_nested && ret != VFIO_TYPE1_NESTING_IOMMU) { ++ error_setg(errp, "Nested mode requested but not supported"); ++ ret = -EINVAL; ++ } ++ return ret; + } + + static int vfio_init_container(VFIOContainer *container, int group_fd, +- Error **errp) ++ bool want_nested, Error **errp) + { + int iommu_type, dirty_log_manual_clear, ret; + +- iommu_type = vfio_get_iommu_type(container, errp); ++ iommu_type = vfio_get_iommu_type(container, want_nested, errp); + if (iommu_type < 0) { + return iommu_type; + } +@@ -1815,6 +1826,14 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + VFIOContainer *container; + int ret, fd; + VFIOAddressSpace *space; ++ IOMMUMemoryRegion *iommu_mr; ++ bool nested = false; ++ ++ if (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 *)&nested); ++ } + + space = vfio_get_address_space(as); + +@@ -1879,13 +1898,14 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + QLIST_INIT(&container->hostwin_list); + QLIST_INIT(&container->dma_list); + +- ret = vfio_init_container(container, group->fd, errp); ++ ret = vfio_init_container(container, group->fd, nested, errp); + if (ret) { + goto free_container_exit; + } + trace_vfio_connect_new_container(group->groupid, container->fd); + + switch (container->iommu_type) { ++ case VFIO_TYPE1_NESTING_IOMMU: + case VFIO_TYPE1v2_IOMMU: + case VFIO_TYPE1_IOMMU: + { +-- +2.27.0 +