Print a warning if IOMMU address space width is smaller than the physical address width. In this case, PCI peer-to-peer transactions on BARs are not supported and failures of device MMIO regions are to be expected.
This can occur with the 39-bit IOMMU address space width as found on consumer grade processors or when using a vIOMMU device with default settings. Signed-off-by: Cédric Le Goater <c...@redhat.com> --- hw/vfio/common.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 561be7f57cf903e6e2bcbbb708be9e4d4ee8941c..d0104976e9d99c3f64ec716accd3adb4a70d9afe 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -44,6 +44,8 @@ #include "migration/qemu-file.h" #include "system/tpm.h" +#include "hw/core/cpu.h" + VFIODeviceList vfio_device_list = QLIST_HEAD_INITIALIZER(vfio_device_list); static QLIST_HEAD(, VFIOAddressSpace) vfio_address_spaces = @@ -1561,12 +1563,28 @@ retry: return info; } +static bool vfio_device_check_address_space(VFIODevice *vbasedev, Error **errp) +{ + uint32_t cpu_aw_bits = cpu_get_phys_bits(first_cpu); + uint32_t iommu_aw_bits = vfio_device_get_aw_bits(vbasedev); + + if (cpu_aw_bits && cpu_aw_bits > iommu_aw_bits) { + error_setg(errp, "Host physical address space (%u) is larger than " + "the host IOMMU address space (%u).", cpu_aw_bits, + iommu_aw_bits); + vfio_container_p2p_error_append(vbasedev->bcontainer, errp); + return false; + } + return true; +} + bool vfio_attach_device(char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp) { const VFIOIOMMUClass *ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_LEGACY)); HostIOMMUDevice *hiod = NULL; + Error *local_err = NULL; if (vbasedev->iommufd) { ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD)); @@ -1586,6 +1604,9 @@ bool vfio_attach_device(char *name, VFIODevice *vbasedev, return false; } + if (!vfio_device_check_address_space(vbasedev, &local_err)) { + warn_report_err(local_err); + } return true; } -- 2.48.1