diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 5f0adb0b4a..f7bf36cec8 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -84,6 +84,7 @@ S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, cnt->users = 1; cnt->avail = avail; QTAILQ_INSERT_TAIL(&s->zpci_dma_limit, cnt, link); + pbdev->iommu->max_dma_limit = avail; return cnt; } @@ -103,6 +104,7 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev, struct vfio_info_cap_header *hdr; struct vfio_device_info_cap_zpci_base *cap; VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + uint64_t vfio_size; hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE); @@ -122,6 +124,15 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev, /* The following values remain 0 until we support other FMB formats */ pbdev->zpci_fn.fmbl = 0; pbdev->zpci_fn.pft = 0; + + /* + * If appropriate, reduce the size of the supported DMA aperture reported + * to the guest based upon the vfio DMA limit. + */ + vfio_size = pbdev->iommu->max_dma_limit << TARGET_PAGE_BITS; + if (vfio_size < (cap->end_dma - cap->start_dma + 1)) { + pbdev->zpci_fn.edma = cap->start_dma + vfio_size - 1; + } } static bool get_host_fh(S390PCIBusDevice *pbdev, struct vfio_device_info *info, diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index 0605fcea24..1c46e3a269 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -278,6 +278,7 @@ struct S390PCIIOMMU { uint64_t g_iota; uint64_t pba; uint64_t pal; + uint64_t max_dma_limit; GHashTable *iotlb; S390PCIDMACount *dma_limit; };