thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone
ed5979
From ed90f91b61844abd2dff2eb970f721a6cf072235 Mon Sep 17 00:00:00 2001
ed5979
From: Matthew Rosato <mjrosato@linux.ibm.com>
ed5979
Date: Fri, 28 Oct 2022 15:47:57 -0400
ed5979
Subject: [PATCH 6/9] s390x/pci: coalesce unmap operations
ed5979
MIME-Version: 1.0
ed5979
Content-Type: text/plain; charset=UTF-8
ed5979
Content-Transfer-Encoding: 8bit
ed5979
ed5979
RH-Author: Cédric Le Goater <clg@redhat.com>
ed5979
RH-MergeRequest: 141: s390x/pci: reset ISM passthrough devices on shutdown and system reset
ed5979
RH-Bugzilla: 2163701
ed5979
RH-Acked-by: Thomas Huth <thuth@redhat.com>
ed5979
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
ed5979
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
ed5979
RH-Commit: [1/3] 80c3a2c1d720057ae2a80b338ea06c9c6c804532 (clegoate/qemu-kvm-c9s)
ed5979
ed5979
Currently, each unmapped page is handled as an individual iommu
ed5979
region notification.  Attempt to group contiguous unmap operations
ed5979
into fewer notifications to reduce overhead.
ed5979
ed5979
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
ed5979
Message-Id: <20221028194758.204007-3-mjrosato@linux.ibm.com>
ed5979
Reviewed-by: Eric Farman <farman@linux.ibm.com>
ed5979
Signed-off-by: Thomas Huth <thuth@redhat.com>
ed5979
(cherry picked from commit ef536007c3301bbd6a787e4c2210ea289adaa6f0)
ed5979
Signed-off-by: Cédric Le Goater <clg@redhat.com>
ed5979
---
ed5979
 hw/s390x/s390-pci-inst.c | 51 ++++++++++++++++++++++++++++++++++++++++
ed5979
 1 file changed, 51 insertions(+)
ed5979
ed5979
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
ed5979
index 7cc4bcf850..66e764f901 100644
ed5979
--- a/hw/s390x/s390-pci-inst.c
ed5979
+++ b/hw/s390x/s390-pci-inst.c
ed5979
@@ -640,6 +640,8 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
ed5979
         }
ed5979
         g_hash_table_remove(iommu->iotlb, &entry->iova);
ed5979
         inc_dma_avail(iommu);
ed5979
+        /* Don't notify the iommu yet, maybe we can bundle contiguous unmaps */
ed5979
+        goto out;
ed5979
     } else {
ed5979
         if (cache) {
ed5979
             if (cache->perm == entry->perm &&
ed5979
@@ -663,15 +665,44 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
ed5979
         dec_dma_avail(iommu);
ed5979
     }
ed5979
 
ed5979
+    /*
ed5979
+     * All associated iotlb entries have already been cleared, trigger the
ed5979
+     * unmaps.
ed5979
+     */
ed5979
     memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
ed5979
 
ed5979
 out:
ed5979
     return iommu->dma_limit ? iommu->dma_limit->avail : 1;
ed5979
 }
ed5979
 
ed5979
+static void s390_pci_batch_unmap(S390PCIIOMMU *iommu, uint64_t iova,
ed5979
+                                 uint64_t len)
ed5979
+{
ed5979
+    uint64_t remain = len, start = iova, end = start + len - 1, mask, size;
ed5979
+    IOMMUTLBEvent event = {
ed5979
+        .type = IOMMU_NOTIFIER_UNMAP,
ed5979
+        .entry = {
ed5979
+            .target_as = &address_space_memory,
ed5979
+            .translated_addr = 0,
ed5979
+            .perm = IOMMU_NONE,
ed5979
+        },
ed5979
+    };
ed5979
+
ed5979
+    while (remain >= TARGET_PAGE_SIZE) {
ed5979
+        mask = dma_aligned_pow2_mask(start, end, 64);
ed5979
+        size = mask + 1;
ed5979
+        event.entry.iova = start;
ed5979
+        event.entry.addr_mask = mask;
ed5979
+        memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
ed5979
+        start += size;
ed5979
+        remain -= size;
ed5979
+    }
ed5979
+}
ed5979
+
ed5979
 int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
ed5979
 {
ed5979
     CPUS390XState *env = &cpu->env;
ed5979
+    uint64_t iova, coalesce = 0;
ed5979
     uint32_t fh;
ed5979
     uint16_t error = 0;
ed5979
     S390PCIBusDevice *pbdev;
ed5979
@@ -742,6 +773,21 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
ed5979
             break;
ed5979
         }
ed5979
 
ed5979
+        /*
ed5979
+         * If this is an unmap of a PTE, let's try to coalesce multiple unmaps
ed5979
+         * into as few notifier events as possible.
ed5979
+         */
ed5979
+        if (entry.perm == IOMMU_NONE && entry.len == TARGET_PAGE_SIZE) {
ed5979
+            if (coalesce == 0) {
ed5979
+                iova = entry.iova;
ed5979
+            }
ed5979
+            coalesce += entry.len;
ed5979
+        } else if (coalesce > 0) {
ed5979
+            /* Unleash the coalesced unmap before processing a new map */
ed5979
+            s390_pci_batch_unmap(iommu, iova, coalesce);
ed5979
+            coalesce = 0;
ed5979
+        }
ed5979
+
ed5979
         start += entry.len;
ed5979
         while (entry.iova < start && entry.iova < end) {
ed5979
             if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
ed5979
@@ -759,6 +805,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
ed5979
             }
ed5979
         }
ed5979
     }
ed5979
+    if (coalesce) {
ed5979
+            /* Unleash the coalesced unmap before finishing rpcit */
ed5979
+            s390_pci_batch_unmap(iommu, iova, coalesce);
ed5979
+            coalesce = 0;
ed5979
+    }
ed5979
     if (again && dma_avail > 0)
ed5979
         goto retry;
ed5979
 err:
ed5979
-- 
ed5979
2.31.1
ed5979