From 6d8be4c3434783a59ae29f7ea6a792b56c812349 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 10 Jun 2014 15:39:22 +1000 Subject: vfio: Add vfio_container_ioctl() While most operations with VFIO IOMMU driver are generic and used inside vfio.c, there are still some operations which only specific VFIO IOMMU drivers implement. The first example of it will be reading a DMA window start from the host. This adds a helper which passes an ioctl request to the container's fd. The helper will check if @req is known. For this, stub is added. This return -1 on any requests for now. Signed-off-by: Alexey Kardashevskiy Acked-by: Alex Williamson Acked-by: Alex Williamson Signed-off-by: Alexander Graf --- hw/misc/vfio.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'hw/misc/vfio.c') diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 7437c2e3c3..bdd6e3386e 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -39,6 +39,7 @@ #include "qemu/range.h" #include "sysemu/kvm.h" #include "sysemu/sysemu.h" +#include "hw/misc/vfio.h" /* #define DEBUG_VFIO */ #ifdef DEBUG_VFIO @@ -4318,3 +4319,44 @@ static void register_vfio_pci_dev_type(void) } type_init(register_vfio_pci_dev_type) + +static int vfio_container_do_ioctl(AddressSpace *as, int32_t groupid, + int req, void *param) +{ + VFIOGroup *group; + VFIOContainer *container; + int ret = -1; + + group = vfio_get_group(groupid, as); + if (!group) { + error_report("vfio: group %d not registered", groupid); + return ret; + } + + container = group->container; + if (group->container) { + ret = ioctl(container->fd, req, param); + if (ret < 0) { + error_report("vfio: failed to ioctl container: ret=%d, %s", + ret, strerror(errno)); + } + } + + vfio_put_group(group); + + return ret; +} + +int vfio_container_ioctl(AddressSpace *as, int32_t groupid, + int req, void *param) +{ + /* We allow only certain ioctls to the container */ + switch (req) { + default: + /* Return an error on unknown requests */ + error_report("vfio: unsupported ioctl %X", req); + return -1; + } + + return vfio_container_do_ioctl(as, groupid, req, param); +} -- cgit 1.4.1 From 591812634c84471fc68feb259ebebb82d0d5513a Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 10 Jun 2014 15:39:24 +1000 Subject: vfio: Enable for SPAPR This turns the sPAPR support on and enables VFIO container use in the kernel. This extends vfio_connect_container to support VFIO_SPAPR_TCE_IOMMU type in the host kernel. This registers a memory listener which sPAPR IOMMU will notify when executing H_PUT_TCE/etc DMA calls. The listener then will notify the host kernel about DMA map/unmap operation via VFIO_IOMMU_MAP_DMA/ VFIO_IOMMU_UNMAP_DMA ioctls. This executes VFIO_IOMMU_ENABLE ioctl to make sure that the IOMMU is free of mappings and can be exclusively given to the user. At the moment SPAPR is the only platform requiring this call to be implemented. Note that the host kernel function implementing VFIO_IOMMU_DISABLE is called automatically when container's fd is closed so there is no need to call it explicitly from QEMU. We may need to call VFIO_IOMMU_DISABLE explicitly in the future for some sort of dynamic reconfiguration (PCI hotplug or dynamic IOMMU group management). Signed-off-by: Alexey Kardashevskiy Acked-by: Alex Williamson Signed-off-by: Alexander Graf --- hw/misc/vfio.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'hw/misc/vfio.c') diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index bdd6e3386e..7b279c4f05 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -3650,6 +3650,39 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) container->iommu_data.type1.initialized = true; + } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU)) { + 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_SET_IOMMU, VFIO_SPAPR_TCE_IOMMU); + if (ret) { + error_report("vfio: failed to set iommu for container: %m"); + ret = -errno; + goto free_container_exit; + } + + /* + * The host kernel code implementing VFIO_IOMMU_DISABLE is called + * when container fd is closed so we do not call it explicitly + * in this file. + */ + ret = ioctl(fd, VFIO_IOMMU_ENABLE); + if (ret) { + error_report("vfio: failed to enable container: %m"); + ret = -errno; + goto free_container_exit; + } + + container->iommu_data.type1.listener = vfio_memory_listener; + container->iommu_data.release = vfio_listener_release; + + memory_listener_register(&container->iommu_data.type1.listener, + container->space->as); + } else { error_report("vfio: No available IOMMU models"); ret = -EINVAL; @@ -4352,6 +4385,9 @@ int vfio_container_ioctl(AddressSpace *as, int32_t groupid, { /* We allow only certain ioctls to the container */ switch (req) { + case VFIO_CHECK_EXTENSION: + case VFIO_IOMMU_SPAPR_TCE_GET_INFO: + break; default: /* Return an error on unknown requests */ error_report("vfio: unsupported ioctl %X", req); -- cgit 1.4.1