[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[qemu-s390x] [PATCH v1 2/3] vfio/pci: Get real IOMMU information from co
From: |
Pierre Morel |
Subject: |
[qemu-s390x] [PATCH v1 2/3] vfio/pci: Get real IOMMU information from container |
Date: |
Wed, 9 Jan 2019 13:41:19 +0100 |
When the vfio_iommu_type1 supports the VFIO_IOMMU_INFO_CAPABILITIES
and the capability ID VFIO_IOMMU_INFO_CAP_DMA we can use an ioctl
to retrieve this information from the real IOMMU device.
Let's use this information to add the host window associated with
the container.
Signed-off-by: Pierre Morel <address@hidden>
---
hw/vfio/common.c | 73 +++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 56 insertions(+), 17 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 7c185e5a..fd7e991 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1036,6 +1036,61 @@ static void vfio_put_address_space(VFIOAddressSpace
*space)
}
}
+static void vfio_iommu_type1_get_info(int fd, VFIOContainer *container)
+{
+ struct vfio_iommu_type1_info *info;
+ size_t argsz = sizeof(*info);
+ struct vfio_info_cap_header *hdr;
+ struct vfio_iommu_cap_dma *dma_info;
+ int ret = 0;
+
+ info = g_malloc0(argsz);
+
+retry:
+ info->argsz = argsz;
+ info->flags = VFIO_IOMMU_INFO_CAPABILITIES;
+
+ ret = ioctl(fd, VFIO_IOMMU_GET_INFO, info);
+ /* Ignore errors */
+ if (ret) {
+ goto out;
+ }
+ if (!(info->flags & VFIO_IOMMU_INFO_PGSIZES)) {
+ info->iova_pgsizes = 4096;
+ }
+
+ if (info->argsz > argsz) {
+ argsz = info->argsz;
+ info = g_realloc(info, argsz);
+
+ goto retry;
+ }
+ if (info->argsz != argsz) {
+ goto out;
+ }
+ /* Now we have the capabilities */
+ hdr = (struct vfio_info_cap_header *)((unsigned char *)info +
+ sizeof(struct vfio_iommu_type1_info)
+
+ info->cap_offset);
+ do {
+ dma_info = (struct vfio_iommu_cap_dma *) (hdr);
+ if (hdr->id == VFIO_IOMMU_INFO_CAP_DMA) {
+ vfio_host_win_add(container, 0,
+ dma_info->dma_end - dma_info->dma_start,
+ info->iova_pgsizes);
+ container->pgsizes = info->iova_pgsizes;
+ return;
+ }
+ hdr = (struct vfio_info_cap_header *)((unsigned char *) dma_info +
+ hdr->next);
+ } while (hdr->next);
+out:
+ /* Assume 4k IOVA page size */
+ vfio_host_win_add(container, 0, (hwaddr)-1, 4096);
+ container->pgsizes = 4096;
+ return;
+}
+
static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
Error **errp)
{
@@ -1104,7 +1159,6 @@ static int vfio_connect_container(VFIOGroup *group,
AddressSpace *as,
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);
- struct vfio_iommu_type1_info info;
ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
if (ret) {
@@ -1121,22 +1175,7 @@ static int vfio_connect_container(VFIOGroup *group,
AddressSpace *as,
goto free_container_exit;
}
- /*
- * FIXME: This assumes that a Type1 IOMMU can map any 64-bit
- * IOVA whatsoever. That's not actually true, but the current
- * kernel interface doesn't tell us what it can map, and the
- * existing Type1 IOMMUs generally support any IOVA we're
- * going to actually try in practice.
- */
- info.argsz = sizeof(info);
- ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info);
- /* Ignore errors */
- if (ret || !(info.flags & VFIO_IOMMU_INFO_PGSIZES)) {
- /* Assume 4k IOVA page size */
- info.iova_pgsizes = 4096;
- }
- vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes);
- container->pgsizes = info.iova_pgsizes;
+ vfio_iommu_type1_get_info(fd, container);
} else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU) ||
ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU)) {
struct vfio_iommu_spapr_tce_info info;
--
2.7.4