mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/6] iommu/virtio: batch the mapping replay
@ 2026-10-04 12:59 Anlai Lu
  2026-10-04 13:01 ` [PATCH v2 1/6] iommu/virtio: publish the endpoint before replaying it Anlai Lu
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Anlai Lu @ 2026-10-04 12:59 UTC (permalink / raw)
  To: Jean-Philippe Brucker, Joerg Roedel, Will Deacon
  Cc: Robin Murphy, virtualization, iommu, linux-kernel, Anlai Lu

The virtio-iommu device frees a domain together with its last endpoint, so
the first endpoint attaching to a domain that already has mappings must
rebuild it: viommu_replay_mappings() re-sends every mapping the driver
holds. That walk sent one synchronous request per mapping with
mappings_lock held - and with it interrupts disabled. The IRQ-off window
therefore grew with the number of mappings: 233 ms for 8192 4K mappings,
about 29 s for a million, long enough to add scheduling latency to
everything else running on the CPU.

The same code had two long-standing defects, fixed by the first patches:

 - nr_endpoints was bumped only after the replay, without the lock, while
   viommu_map_pages() read the same counter, also without the lock, to
   decide whether to send a MAP itself or leave it to the replay. A map
   racing the first attach could be sent by nobody and never reach the
   device.

 - viommu_unmap_pages() removed whole mappings from its tree but queued a
   single UNMAP built from the range the caller asked for, after dropping
   the lock: the device could keep translating memory the driver had
   released, and a concurrent map could be sent ahead of the UNMAP. That
   queueing also allocated on the unmap path, which iommu_unmap_nofail()
   does not allow.

The series:

 - 1/6 publishes the endpoint before the replay, tracks an unfinished
   replay with replay_pending, and puts the endpoint back on the old
   domain when the ATTACH or the replay fails - with a replay pending for
   it if the device dropped its mappings - so a failed attach cannot leave
   the endpoint count short, the endpoint unattached (bypassed), or the
   endpoint recorded on a domain the core does not reference;
 - 2/6 queues one UNMAP per contiguous run of removed mappings, in the
   section that removes them, covering the mappings' own ranges;
 - 3/6 allocates the UNMAP request together with the mapping, on the map
   path, so the unmap path never allocates;
 - 4/6 stops queueing and draining once the device is removed;
 - 5/6 reads the endpoint count under the lock in the iotlb paths;
 - 6/6 queues the replayed mappings, one per lock section, and waits once.

Measured with QEMU/KVM and iommufd, N=8192 4K mappings: max IRQ-off window
233.7 ms -> 1.4-2.5 ms, flat from N=64 to 32768; attach ioctl 218.9/249.0
-> 50.3/48.8 ms (48-67 ms across runs); viommu_send_req_sync() calls 8193
-> 1; the device receives exactly the same MAPs. With large pages the
same 256 MB attach is about 4 ms (197 device requests); the remaining cost
is the device processing one MAP per mapping, which the protocol
requires. The concurrent map-vs-first-attach test loses mappings on the
unpatched driver in several runs and none with the series; lockdep and
KCSAN report nothing. Allocation-failure and device-rejection paths were
exercised with test-only fault injection in QEMU.

Patches 1-4 carry Fixes: tags for the original driver commit. Behaviour
that predates this work - in particular, how a MAP the device rejects on
the map path - is deliberately left unchanged. Based on v7.3-rc5
(ce1e0223d8ad).

Changes since v1:
 - 1/6's comments now say why a failed ATTACH is reported without
   replaying (the endpoint did not move, so the old domain still holds it
   and its mappings), and why a failed replay leaves the old domain's
   mappings to its next attach, and viommu_restore_endpoint()'s kernel-doc
   covers both of its call sites;
 - 4/6 detaches the requests left on the request queue and frees them
   after the device is reset and before the queues are deleted, instead
   of leaking them (pointed out in review).

Anlai Lu (6):
  iommu/virtio: publish the endpoint before replaying it
  iommu/virtio: queue an UNMAP for every removed mapping
  iommu/virtio: allocate the UNMAP request with the mapping
  iommu/virtio: stop queueing and draining once the device is removed
  iommu/virtio: read the endpoint count under the lock in the iotlb
    paths
  iommu/virtio: batch the mapping replay on domain attach

 drivers/iommu/virtio-iommu.c | 673 +++++++++++++++++++++++++++++------
 1 file changed, 569 insertions(+), 104 deletions(-)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-04 13:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-04 12:59 [PATCH v2 0/6] iommu/virtio: batch the mapping replay Anlai Lu
2026-10-04 13:01 ` [PATCH v2 1/6] iommu/virtio: publish the endpoint before replaying it Anlai Lu
2026-10-04 13:01 ` [PATCH v2 2/6] iommu/virtio: queue an UNMAP for every removed mapping Anlai Lu
2026-10-04 13:01 ` [PATCH v2 3/6] iommu/virtio: allocate the UNMAP request with the mapping Anlai Lu
2026-10-04 13:01 ` [PATCH v2 4/6] iommu/virtio: stop queueing and draining once the device is removed Anlai Lu
2026-10-04 13:01 ` [PATCH v2 5/6] iommu/virtio: read the endpoint count under the lock in the iotlb paths Anlai Lu
2026-10-04 13:01 ` [PATCH v2 6/6] iommu/virtio: batch the mapping replay on domain attach Anlai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®