mirror of
https://github.com/qemu/qemu.git
synced 2026-09-22 14:34:34 +00:00
s390x/pci: fix DMA slot leak on I/O TLB entry replacement
When s390_pci_update_iotlb() does a mapping update for an IOVA that has
an already-existing TLB entry with different permissions or translated
address, it unmaps then remaps it. However, at the end of the map path,
it unconditionally decrements the available DMA slot counter without a
corresponding increment in the intermediate unmap branch.
This causes the DMA slot count to be decremented on every remapping of
an active IOVA, leading to a permanent DMA slot leak. This remapping
without a prior invalidation and sync is not seen today in well-behaved
guests but is allowed by the architecture. Fix it by only decrementing
available DMA slots when inserting a brand new mapping.
Cc: qemu-stable@nongnu.org
Fixes: 37fa32de70 ("s390x/pci: Honor DMA limits set by vfio")
Signed-off-by: Omar Elghoul <oelghoul@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20260917140431.45343-1-oelghoul@linux.ibm.com
Signed-off-by: Eric Farman <farman@linux.ibm.com>
This commit is contained in:
committed by
Eric Farman
parent
8dc3cf1053
commit
9b64b3cc83
@@ -655,6 +655,7 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
|
||||
goto out;
|
||||
} else {
|
||||
if (cache) {
|
||||
/* valid->valid transitions reuse the DMA slot */
|
||||
if (cache->perm == entry->perm &&
|
||||
cache->translated_addr == entry->translated_addr) {
|
||||
goto out;
|
||||
@@ -665,6 +666,9 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
|
||||
memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
|
||||
event.type = IOMMU_NOTIFIER_MAP;
|
||||
event.entry.perm = entry->perm;
|
||||
} else {
|
||||
/* invalid->valid transitions consume a new DMA slot */
|
||||
dec_dma_avail(iommu);
|
||||
}
|
||||
|
||||
cache = g_new(S390IOTLBEntry, 1);
|
||||
@@ -673,7 +677,6 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu,
|
||||
cache->len = TARGET_PAGE_SIZE;
|
||||
cache->perm = entry->perm;
|
||||
g_hash_table_replace(iommu->iotlb, &cache->iova, cache);
|
||||
dec_dma_avail(iommu);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user