Message ID | 20221028194758.204007-3-mjrosato@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x/pci: rpcit fixes and enhancements | expand |
On Fri, 2022-10-28 at 15:47 -0400, Matthew Rosato wrote: > Currently, each unmapped page is handled as an individual iommu > region notification. Attempt to group contiguous unmap operations > into fewer notifications to reduce overhead. > > Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> > --- > hw/s390x/s390-pci-inst.c | 51 > ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 51 insertions(+) > > diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c > index 7cc4bcf850..66e764f901 100644 > --- a/hw/s390x/s390-pci-inst.c > +++ b/hw/s390x/s390-pci-inst.c > @@ -640,6 +640,8 @@ static uint32_t > s390_pci_update_iotlb(S390PCIIOMMU *iommu, > } > g_hash_table_remove(iommu->iotlb, &entry->iova); > inc_dma_avail(iommu); > + /* Don't notify the iommu yet, maybe we can bundle > contiguous unmaps */ > + goto out; > } else { > if (cache) { > if (cache->perm == entry->perm && > @@ -663,15 +665,44 @@ static uint32_t > s390_pci_update_iotlb(S390PCIIOMMU *iommu, > dec_dma_avail(iommu); > } > > + /* > + * All associated iotlb entries have already been cleared, > trigger the > + * unmaps. > + */ > memory_region_notify_iommu(&iommu->iommu_mr, 0, event); > > out: > return iommu->dma_limit ? iommu->dma_limit->avail : 1; > } > > +static void s390_pci_batch_unmap(S390PCIIOMMU *iommu, uint64_t iova, > + uint64_t len) > +{ > + uint64_t remain = len, start = iova, end = start + len - 1, > mask, size; > + IOMMUTLBEvent event = { > + .type = IOMMU_NOTIFIER_UNMAP, > + .entry = { > + .target_as = &address_space_memory, > + .translated_addr = 0, > + .perm = IOMMU_NONE, > + }, > + }; > + > + while (remain >= TARGET_PAGE_SIZE) { > + mask = dma_aligned_pow2_mask(start, end, 64); > + size = mask + 1; > + event.entry.iova = start; > + event.entry.addr_mask = mask; > + memory_region_notify_iommu(&iommu->iommu_mr, 0, event); > + start += size; > + remain -= size; > + } > +} > + > int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, > uintptr_t ra) > { > CPUS390XState *env = &cpu->env; > + uint64_t iova, coalesce = 0; > uint32_t fh; > uint16_t error = 0; > S390PCIBusDevice *pbdev; > @@ -742,6 +773,21 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, > uint8_t r2, uintptr_t ra) > break; > } > > + /* > + * If this is an unmap of a PTE, let's try to coalesce > multiple unmaps > + * into as few notifier events as possible. > + */ > + if (entry.perm == IOMMU_NONE && entry.len == > TARGET_PAGE_SIZE) { > + if (coalesce == 0) { > + iova = entry.iova; > + } > + coalesce += entry.len; > + } else if (coalesce > 0) { > + /* Unleash the coalesced unmap before processing a new > map */ > + s390_pci_batch_unmap(iommu, iova, coalesce); > + coalesce = 0; > + } > + > start += entry.len; > while (entry.iova < start && entry.iova < end) { > if (dma_avail > 0 || entry.perm == IOMMU_NONE) { > @@ -759,6 +805,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, > uint8_t r2, uintptr_t ra) > } > } > } > + if (coalesce) { I'd guess this should be "coalesce > 0" as above. Regardless, Reviewed-by: Eric Farman <farman@linux.ibm.com> > + /* Unleash the coalesced unmap before finishing rpcit */ > + s390_pci_batch_unmap(iommu, iova, coalesce); > + coalesce = 0; > + } > if (again && dma_avail > 0) > goto retry; > err:
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 7cc4bcf850..66e764f901 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -640,6 +640,8 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, } g_hash_table_remove(iommu->iotlb, &entry->iova); inc_dma_avail(iommu); + /* Don't notify the iommu yet, maybe we can bundle contiguous unmaps */ + goto out; } else { if (cache) { if (cache->perm == entry->perm && @@ -663,15 +665,44 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, dec_dma_avail(iommu); } + /* + * All associated iotlb entries have already been cleared, trigger the + * unmaps. + */ memory_region_notify_iommu(&iommu->iommu_mr, 0, event); out: return iommu->dma_limit ? iommu->dma_limit->avail : 1; } +static void s390_pci_batch_unmap(S390PCIIOMMU *iommu, uint64_t iova, + uint64_t len) +{ + uint64_t remain = len, start = iova, end = start + len - 1, mask, size; + IOMMUTLBEvent event = { + .type = IOMMU_NOTIFIER_UNMAP, + .entry = { + .target_as = &address_space_memory, + .translated_addr = 0, + .perm = IOMMU_NONE, + }, + }; + + while (remain >= TARGET_PAGE_SIZE) { + mask = dma_aligned_pow2_mask(start, end, 64); + size = mask + 1; + event.entry.iova = start; + event.entry.addr_mask = mask; + memory_region_notify_iommu(&iommu->iommu_mr, 0, event); + start += size; + remain -= size; + } +} + int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) { CPUS390XState *env = &cpu->env; + uint64_t iova, coalesce = 0; uint32_t fh; uint16_t error = 0; S390PCIBusDevice *pbdev; @@ -742,6 +773,21 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) break; } + /* + * If this is an unmap of a PTE, let's try to coalesce multiple unmaps + * into as few notifier events as possible. + */ + if (entry.perm == IOMMU_NONE && entry.len == TARGET_PAGE_SIZE) { + if (coalesce == 0) { + iova = entry.iova; + } + coalesce += entry.len; + } else if (coalesce > 0) { + /* Unleash the coalesced unmap before processing a new map */ + s390_pci_batch_unmap(iommu, iova, coalesce); + coalesce = 0; + } + start += entry.len; while (entry.iova < start && entry.iova < end) { if (dma_avail > 0 || entry.perm == IOMMU_NONE) { @@ -759,6 +805,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) } } } + if (coalesce) { + /* Unleash the coalesced unmap before finishing rpcit */ + s390_pci_batch_unmap(iommu, iova, coalesce); + coalesce = 0; + } if (again && dma_avail > 0) goto retry; err:
Currently, each unmapped page is handled as an individual iommu region notification. Attempt to group contiguous unmap operations into fewer notifications to reduce overhead. Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> --- hw/s390x/s390-pci-inst.c | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)