Add qemu support for the newly introduced VFIO No-IOMMU driver. We need to add special handling for: - Group character device is /dev/vfio/noiommu-$GROUP. - No-IOMMU does not rely on a memory listener. - No IOMMU will be set for its group, so no need to call vfio_kvm_device_add_group. Signed-off-by: Xiao Feng Ren <renxiaof@xxxxxxxxxxxxxxxxxx> --- hw/vfio/common.c | 66 ++++++++++++++++++++++++++++++++++--------- include/hw/vfio/vfio-common.h | 2 ++ 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index f27db36..656c303 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -789,6 +789,33 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) container = g_malloc0(sizeof(*container)); container->space = space; container->fd = fd; + container->noiommu = group->noiommu; + + if (container->noiommu) { + ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); + if (ret) { + error_report("vfio: failed to set group container: %m"); + ret = -errno; + goto free_container_exit; + } + + ret = ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_NOIOMMU_IOMMU); + if (!ret) { + error_report("vfio: No available IOMMU models"); + ret = -EINVAL; + goto free_container_exit; + } + + ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_NOIOMMU_IOMMU); + if (ret) { + error_report("vfio: failed to set iommu for container: %m"); + ret = -errno; + goto free_container_exit; + } + + goto listener_register; + } + if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) || ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) { bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU); @@ -878,14 +905,16 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) goto free_container_exit; } - container->listener = vfio_memory_listener; - - memory_listener_register(&container->listener, container->space->as); - - if (container->error) { - ret = container->error; - error_report("vfio: memory listener initialization failed for container"); - goto listener_release_exit; +listener_register: + if (!container->noiommu) { + container->listener = vfio_memory_listener; + memory_listener_register(&container->listener, container->space->as); + if (container->error) { + ret = container->error; + error_report("vfio: memory listener initialization failed for " + "container"); + goto listener_release_exit; + } } container->initialized = true; @@ -898,7 +927,9 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) return 0; listener_release_exit: - vfio_listener_release(container); + if (!container->noiommu) { + vfio_listener_release(container); + } free_container_exit: g_free(container); @@ -928,7 +959,9 @@ static void vfio_disconnect_container(VFIOGroup *group) VFIOAddressSpace *space = container->space; VFIOGuestIOMMU *giommu, *tmp; - vfio_listener_release(container); + if (!container->noiommu) { + vfio_listener_release(container); + } QLIST_REMOVE(container, next); QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) { @@ -969,8 +1002,13 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); group->fd = qemu_open(path, O_RDWR); if (group->fd < 0) { - error_report("vfio: error opening %s: %m", path); - goto free_group_exit; + snprintf(path, sizeof(path), "/dev/vfio/noiommu-%d", groupid); + group->fd = qemu_open(path, O_RDWR); + if (group->fd < 0) { + error_report("vfio: error opening %s: %m", path); + goto free_group_exit; + } + group->noiommu = 1; } if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { @@ -999,7 +1037,9 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) QLIST_INSERT_HEAD(&vfio_group_list, group, next); - vfio_kvm_device_add_group(group); + if (!group->noiommu) { + vfio_kvm_device_add_group(group); + } return group; diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index eb0e1b0..85c2a74 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -72,6 +72,7 @@ struct VFIOGroup; typedef struct VFIOContainer { VFIOAddressSpace *space; int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + bool noiommu; MemoryListener listener; int error; bool initialized; @@ -121,6 +122,7 @@ struct VFIODeviceOps { typedef struct VFIOGroup { int fd; int groupid; + bool noiommu; VFIOContainer *container; QLIST_HEAD(, VFIODevice) device_list; QLIST_ENTRY(VFIOGroup) next; -- 2.6.6 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html