Commit e57ad36701 for qemu.org
commit e57ad36701886404baaf5216bacfa9a21f98fd6e
Author: Matthew Rosato <mjrosato@linux.ibm.com>
Date: Tue Sep 29 11:30:10 2026 -0400
s390x/pci: Fix frame stepping in rpcit_service_call()
When walking the guest IO address table, an invalid segment or region
entry causes table_translate() to return entry.len equal to the frame
size for that table level (1 MiB for ST, 2 GiB for RT). Adding
entry.len directly to start only advances to the correct next frame
boundary if start is already frame-aligned at that level -- which is
true for a well-behaved Linux guest but not a general requirement.
Add logic to advance start to the next frame boundary rather than
simply adding entry.len. For a frame-aligned start (the typical,
well-behaved case) the result is identical.
Fixes: 0125861eacc3 ("s390x/pci: fixup the code walking IOMMU tables")
Cc: qemu-stable@nongnu.org
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20260929153012.774530-2-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 652e1712ec..bac813fb6a 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -808,7 +808,8 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
coalesce = 0;
}
- start += entry.len;
+ /* Advance to next frame boundary if start was not frame-aligned */
+ start = QEMU_ALIGN_UP(start + 1, entry.len);
while (entry.iova < start && entry.iova < end) {
if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
dma_avail = s390_pci_update_iotlb(iommu, &entry);