[PATCH v2 5/6] iommu/virtio: read the endpoint count under the lock in the iotlb paths

From: Anlai Lu

Date: Sun Oct 04 2026 - 09:04:04 EST


viommu_iotlb_sync_map() and viommu_flush_iotlb_all() read nr_endpoints
without the lock its writers take: the one place left after the endpoint
helpers were introduced. Order a sync only when the device holds the
domain, and read the count under the same lock as the writers.

Signed-off-by: Anlai Lu <agicy@xxxxxx>
---
drivers/iommu/virtio-iommu.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 7119030dbcb3..8a93d5f0668f 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -131,6 +131,19 @@ static bool viommu_device_live(struct viommu_dev *viommu)
return !viommu->removed;
}

+/* Does the device hold this domain for at least one endpoint? */
+static bool viommu_domain_has_endpoint(struct viommu_domain *vdomain)
+{
+ unsigned long flags;
+ bool has;
+
+ spin_lock_irqsave(&vdomain->mappings_lock, flags);
+ has = vdomain->nr_endpoints != 0;
+ spin_unlock_irqrestore(&vdomain->mappings_lock, flags);
+
+ return has;
+}
+
static int viommu_get_req_errno(void *buf, size_t len)
{
struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
@@ -1287,8 +1300,10 @@ static int viommu_iotlb_sync_map(struct iommu_domain *domain,
* May be called before the viommu is initialized including
* while creating direct mapping
*/
- if (!vdomain->nr_endpoints)
+ if (!viommu_domain_has_endpoint(vdomain))
return 0;
+
+ /* Wait for this batch's MAPs, whose outcome nobody looks at */
return viommu_sync_req(vdomain->viommu);
}

@@ -1300,7 +1315,7 @@ static void viommu_flush_iotlb_all(struct iommu_domain *domain)
* May be called before the viommu is initialized including
* while creating direct mapping
*/
- if (!vdomain->nr_endpoints)
+ if (!viommu_domain_has_endpoint(vdomain))
return;
viommu_sync_req(vdomain->viommu);
}
--
2.55.0