In order to support direct mapping (which is only bound by the aperture size of the underlying host EDMA reported via vfio) QEMU reports the host-provided EDMA to the guest. However, when using translation mode QEMU only supports up to 4 TiB currently (the size of a single RT table).
Reject attempts by a guest to register a translation aperture that would exceed what QEMU can support by giving an operand exception on the MPCIFC instruction that requested the large aperture. This restriction can be removed in the future if/when support for additional IOAT regions is added. Cc: [email protected] Signed-off-by: Matthew Rosato <[email protected]> --- hw/s390x/s390-pci-inst.c | 15 +++++++++++++++ include/hw/s390x/s390-pci-bus.h | 1 + 2 files changed, 16 insertions(+) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index c6da3b4c07..c7658e7eca 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -1055,6 +1055,21 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, return -EINVAL; } + /* + * We report an EDMA that may exceed what QEMU can handle in support + * of direct-mapping. If the guest attempts to register an IOAT that + * is too large, reject it with an informative message. Only direct + * mapping can be used for guests of this size until support is added + * to QEMU for additional IOAT regions. + */ + if (t && pal >= ZPCI_TABLE_SIZE_RT) { + qemu_log_mask(LOG_GUEST_ERROR, + "ioat pal 0x%"PRIx64" exceeds max translatable address", + pal); + s390_program_interrupt(env, PGM_OPERAND, ra); + return -EINVAL; + } + iommu->pba = pba; iommu->pal = pal; iommu->g_iota = g_iota; diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index 9228523ce8..f182bab246 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -140,6 +140,7 @@ enum ZpciIoatDtype { #define ZPCI_PT_BITS 8 #define ZPCI_ST_SHIFT (ZPCI_PT_BITS + TARGET_PAGE_BITS) #define ZPCI_RT_SHIFT (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS) +#define ZPCI_TABLE_SIZE_RT (1ULL << (ZPCI_RT_SHIFT + ZPCI_TABLE_BITS)) #define ZPCI_RTE_FLAG_MASK 0x3fffULL #define ZPCI_RTE_ADDR_MASK (~ZPCI_RTE_FLAG_MASK) -- 2.55.0
