riscv_iommu_translate() allocates an IOATC entry before passing it to
riscv_iommu_iot_update(). The update helper normally transfers ownership
to the hash table.

When ioatc-limit is zero, however, the helper returns without inserting or
freeing the entry. Every cacheable non-identity translation therefore leaks
one RISCVIOMMUEntry.

Avoid this by disabling caching at the caller when ioatc-limit is zero,
so riscv_iommu_translate() does not allocate an IOATC entry in the first
place. This avoids special-casing entry freeing in riscv_iommu_iot_update()
and keeps the ownership semantics simpler.

Suggested-by: Daniel Henrique Barboza <[email protected]>
Fixes: 9d085a1c3cb2 ("hw/riscv/riscv-iommu: add Address Translation Cache 
(IOATC)")
Cc: [email protected]
Signed-off-by: Tan Chi <[email protected]>
---
v2:
- Disable caching when ioatc-limit is zero instead of freeing the
  allocated entry in riscv_iommu_iot_update().

 hw/riscv/riscv-iommu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 323a041b4a..866f49cc39 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -2919,7 +2919,8 @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate(
         /* Translation disabled or invalid. */
         iotlb.addr_mask = 0;
         iotlb.perm = IOMMU_NONE;
-    } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb, true)) {
+    } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb,
+                                     as->iommu->iot_limit > 0)) {
         /* Translation disabled or fault reported. */
         iotlb.addr_mask = 0;
         iotlb.perm = IOMMU_NONE;
-- 
2.53.0


Reply via email to