Blame SOURCES/kvm-s390x-pci-RPCIT-second-pass-when-mappings-exhausted.patch

bf143f
From 2f0febd6813c4ad7f52e43afb3ecce7aef3557e6 Mon Sep 17 00:00:00 2001
bf143f
From: Matthew Rosato <mjrosato@linux.ibm.com>
bf143f
Date: Fri, 28 Oct 2022 15:47:56 -0400
bf143f
Subject: [PATCH 08/11] s390x/pci: RPCIT second pass when mappings exhausted
bf143f
MIME-Version: 1.0
bf143f
Content-Type: text/plain; charset=UTF-8
bf143f
Content-Transfer-Encoding: 8bit
bf143f
bf143f
RH-Author: Cédric Le Goater <clg@redhat.com>
bf143f
RH-MergeRequest: 250: s390x/pci: reset ISM passthrough devices on shutdown and system reset
bf143f
RH-Bugzilla: 2163713
bf143f
RH-Acked-by: Thomas Huth <thuth@redhat.com>
bf143f
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
bf143f
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
bf143f
RH-Commit: [1/4] 0b4500b9247725b1ef0b290bb85392300a618cac
bf143f
bf143f
If we encounter a new mapping while the number of available DMA entries
bf143f
in vfio is 0, we are currently skipping that mapping which is a problem
bf143f
if we manage to free up DMA space after that within the same RPCIT --
bf143f
we will return to the guest with CC0 and have not mapped everything
bf143f
within the specified range.  This issue was uncovered while testing
bf143f
changes to the s390 linux kernel iommu/dma code, where a different
bf143f
usage pattern was employed (new mappings start at the end of the
bf143f
aperture and work back towards the front, making us far more likely
bf143f
to encounter new mappings before invalidated mappings during a
bf143f
global refresh).
bf143f
bf143f
Fix this by tracking whether any mappings were skipped due to vfio
bf143f
DMA limit hitting 0; when this occurs, we still continue the range
bf143f
and unmap/map anything we can - then we must re-run the range again
bf143f
to pickup anything that was missed.  This must occur in a loop until
bf143f
all requests are satisfied (success) or we detect that we are still
bf143f
unable to complete all mappings (return ZPCI_RPCIT_ST_INSUFF_RES).
bf143f
bf143f
Link: https://lore.kernel.org/linux-s390/20221019144435.369902-1-schnelle@linux.ibm.com/
bf143f
Fixes: 37fa32de70 ("s390x/pci: Honor DMA limits set by vfio")
bf143f
Reported-by: Niklas Schnelle <schnelle@linux.ibm.com>
bf143f
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
bf143f
Message-Id: <20221028194758.204007-2-mjrosato@linux.ibm.com>
bf143f
Reviewed-by: Eric Farman <farman@linux.ibm.com>
bf143f
Signed-off-by: Thomas Huth <thuth@redhat.com>
bf143f
(cherry picked from commit 4a8d21ba50fc8625c3bd51dab903872952f95718)
bf143f
Signed-off-by: Cédric Le Goater <clg@redhat.com>
bf143f
---
bf143f
 hw/s390x/s390-pci-inst.c | 29 ++++++++++++++++++++++-------
bf143f
 1 file changed, 22 insertions(+), 7 deletions(-)
bf143f
bf143f
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
bf143f
index 20a9bcc7af..7cc4bcf850 100644
bf143f
--- a/hw/s390x/s390-pci-inst.c
bf143f
+++ b/hw/s390x/s390-pci-inst.c
bf143f
@@ -677,8 +677,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
     S390PCIBusDevice *pbdev;
bf143f
     S390PCIIOMMU *iommu;
bf143f
     S390IOTLBEntry entry;
bf143f
-    hwaddr start, end;
bf143f
+    hwaddr start, end, sstart;
bf143f
     uint32_t dma_avail;
bf143f
+    bool again;
bf143f
 
bf143f
     if (env->psw.mask & PSW_MASK_PSTATE) {
bf143f
         s390_program_interrupt(env, PGM_PRIVILEGED, ra);
bf143f
@@ -691,7 +692,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
     }
bf143f
 
bf143f
     fh = env->regs[r1] >> 32;
bf143f
-    start = env->regs[r2];
bf143f
+    sstart = start = env->regs[r2];
bf143f
     end = start + env->regs[r2 + 1];
bf143f
 
bf143f
     pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
bf143f
@@ -732,6 +733,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
         goto err;
bf143f
     }
bf143f
 
bf143f
+ retry:
bf143f
+    start = sstart;
bf143f
+    again = false;
bf143f
     while (start < end) {
bf143f
         error = s390_guest_io_table_walk(iommu->g_iota, start, &entry);
bf143f
         if (error) {
bf143f
@@ -739,13 +743,24 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
         }
bf143f
 
bf143f
         start += entry.len;
bf143f
-        while (entry.iova < start && entry.iova < end &&
bf143f
-               (dma_avail > 0 || entry.perm == IOMMU_NONE)) {
bf143f
-            dma_avail = s390_pci_update_iotlb(iommu, &entry);
bf143f
-            entry.iova += TARGET_PAGE_SIZE;
bf143f
-            entry.translated_addr += TARGET_PAGE_SIZE;
bf143f
+        while (entry.iova < start && entry.iova < end) {
bf143f
+            if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
bf143f
+                dma_avail = s390_pci_update_iotlb(iommu, &entry);
bf143f
+                entry.iova += TARGET_PAGE_SIZE;
bf143f
+                entry.translated_addr += TARGET_PAGE_SIZE;
bf143f
+            } else {
bf143f
+                /*
bf143f
+                 * We are unable to make a new mapping at this time, continue
bf143f
+                 * on and hopefully free up more space.  Then attempt another
bf143f
+                 * pass.
bf143f
+                 */
bf143f
+                again = true;
bf143f
+                break;
bf143f
+            }
bf143f
         }
bf143f
     }
bf143f
+    if (again && dma_avail > 0)
bf143f
+        goto retry;
bf143f
 err:
bf143f
     if (error) {
bf143f
         pbdev->state = ZPCI_FS_ERROR;
bf143f
-- 
bf143f
2.37.3
bf143f