summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2014-06-10 15:39:24 +1000
committerAlexander Graf <agraf@suse.de>2014-06-27 13:48:23 +0200
commit591812634c84471fc68feb259ebebb82d0d5513a (patch)
tree10d380b2c2ef9dcdb4fe03f60d3aaf486d4c2a47
parent9fc34ada7e80a7c561f64eb124b2b814a8feca68 (diff)
downloadqemu-591812634c84471fc68feb259ebebb82d0d5513a.tar.gz
qemu-591812634c84471fc68feb259ebebb82d0d5513a.tar.bz2
qemu-591812634c84471fc68feb259ebebb82d0d5513a.zip
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 <aik@ozlabs.ru> Acked-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--hw/misc/vfio.c36
1 files changed, 36 insertions, 0 deletions
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);