bf143f
From b972c5a2763a91024725c147cf1691ed8e180c7c Mon Sep 17 00:00:00 2001
bf143f
From: Matthew Rosato <mjrosato@linux.ibm.com>
bf143f
Date: Fri, 28 Oct 2022 15:47:57 -0400
bf143f
Subject: [PATCH 09/11] s390x/pci: coalesce unmap operations
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: [2/4] 7b5ee38eca565f5a7cbede4b9883ba3a508fb46c
bf143f
bf143f
Currently, each unmapped page is handled as an individual iommu
bf143f
region notification.  Attempt to group contiguous unmap operations
bf143f
into fewer notifications to reduce overhead.
bf143f
bf143f
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
bf143f
Message-Id: <20221028194758.204007-3-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 ef536007c3301bbd6a787e4c2210ea289adaa6f0)
bf143f
Signed-off-by: Cédric Le Goater <clg@redhat.com>
bf143f
---
bf143f
 hw/s390x/s390-pci-inst.c | 51 ++++++++++++++++++++++++++++++++++++++++
bf143f
 1 file changed, 51 insertions(+)
bf143f
bf143f
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
bf143f
index 7cc4bcf850..66e764f901 100644
bf143f
--- a/hw/s390x/s390-pci-inst.c
bf143f
+++ b/hw/s390x/s390-pci-inst.c
bf143f
@@ -640,6 +640,8 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
bf143f
         }
bf143f
         g_hash_table_remove(iommu->iotlb, &entry->iova);
bf143f
         inc_dma_avail(iommu);
bf143f
+        /* Don't notify the iommu yet, maybe we can bundle contiguous unmaps */
bf143f
+        goto out;
bf143f
     } else {
bf143f
         if (cache) {
bf143f
             if (cache->perm == entry->perm &&
bf143f
@@ -663,15 +665,44 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
bf143f
         dec_dma_avail(iommu);
bf143f
     }
bf143f
 
bf143f
+    /*
bf143f
+     * All associated iotlb entries have already been cleared, trigger the
bf143f
+     * unmaps.
bf143f
+     */
bf143f
     memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
bf143f
 
bf143f
 out:
bf143f
     return iommu->dma_limit ? iommu->dma_limit->avail : 1;
bf143f
 }
bf143f
 
bf143f
+static void s390_pci_batch_unmap(S390PCIIOMMU *iommu, uint64_t iova,
bf143f
+                                 uint64_t len)
bf143f
+{
bf143f
+    uint64_t remain = len, start = iova, end = start + len - 1, mask, size;
bf143f
+    IOMMUTLBEvent event = {
bf143f
+        .type = IOMMU_NOTIFIER_UNMAP,
bf143f
+        .entry = {
bf143f
+            .target_as = &address_space_memory,
bf143f
+            .translated_addr = 0,
bf143f
+            .perm = IOMMU_NONE,
bf143f
+        },
bf143f
+    };
bf143f
+
bf143f
+    while (remain >= TARGET_PAGE_SIZE) {
bf143f
+        mask = dma_aligned_pow2_mask(start, end, 64);
bf143f
+        size = mask + 1;
bf143f
+        event.entry.iova = start;
bf143f
+        event.entry.addr_mask = mask;
bf143f
+        memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
bf143f
+        start += size;
bf143f
+        remain -= size;
bf143f
+    }
bf143f
+}
bf143f
+
bf143f
 int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
 {
bf143f
     CPUS390XState *env = &cpu->env;
bf143f
+    uint64_t iova, coalesce = 0;
bf143f
     uint32_t fh;
bf143f
     uint16_t error = 0;
bf143f
     S390PCIBusDevice *pbdev;
bf143f
@@ -742,6 +773,21 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
             break;
bf143f
         }
bf143f
 
bf143f
+        /*
bf143f
+         * If this is an unmap of a PTE, let's try to coalesce multiple unmaps
bf143f
+         * into as few notifier events as possible.
bf143f
+         */
bf143f
+        if (entry.perm == IOMMU_NONE && entry.len == TARGET_PAGE_SIZE) {
bf143f
+            if (coalesce == 0) {
bf143f
+                iova = entry.iova;
bf143f
+            }
bf143f
+            coalesce += entry.len;
bf143f
+        } else if (coalesce > 0) {
bf143f
+            /* Unleash the coalesced unmap before processing a new map */
bf143f
+            s390_pci_batch_unmap(iommu, iova, coalesce);
bf143f
+            coalesce = 0;
bf143f
+        }
bf143f
+
bf143f
         start += entry.len;
bf143f
         while (entry.iova < start && entry.iova < end) {
bf143f
             if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
bf143f
@@ -759,6 +805,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
bf143f
             }
bf143f
         }
bf143f
     }
bf143f
+    if (coalesce) {
bf143f
+            /* Unleash the coalesced unmap before finishing rpcit */
bf143f
+            s390_pci_batch_unmap(iommu, iova, coalesce);
bf143f
+            coalesce = 0;
bf143f
+    }
bf143f
     if (again && dma_avail > 0)
bf143f
         goto retry;
bf143f
 err:
bf143f
-- 
bf143f
2.37.3
bf143f