Commit d818e2b0e6 for qemu.org

commit d818e2b0e6317fe5685ce3671bdb566402ff00e9
Author: Matthew Rosato <mjrosato@linux.ibm.com>
Date:   Tue Sep 29 11:30:12 2026 -0400

    s390x/pci: Reject apertures beyond IOAT capacity in translation mode

    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: qemu-stable@nongnu.org
    Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
    Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
    Link: https://lore.kernel.org/qemu-devel/20260929153012.774530-4-mjrosato@linux.ibm.com
    Signed-off-by: Eric Farman <farman@linux.ibm.com>

diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 73417edade..09026360d4 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -1054,6 +1054,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\n",
+                      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)