Hi Matthew,

On 28/9/26 22:23, Matthew Rosato wrote:
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: [email protected]
Signed-off-by: Matthew Rosato <[email protected]>
---
  hw/s390x/s390-pci-inst.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 652e1712ec..a51543df44 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 = (start & ~(entry.len - 1)) + entry.len;

Could that be QEMU_ALIGN_UP()?

          while (entry.iova < start && entry.iova < end) {
              if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
                  dma_avail = s390_pci_update_iotlb(iommu, &entry);


Reply via email to