Skip to content

drm/asahi: lock only the VM reservation for VM queries and VA updates - #521

Merged
RyanTheTide merged 2 commits into
aurora-silicon:integration/aurorafrom
jgoyvaerts:m4pro/asahi-vm-resv-lock
Oct 31, 2026
Merged

RyanTheTide merged 2 commits into
aurora-silicon:integration/aurorafrom
jgoyvaerts:m4pro/asahi-vm-resv-lock

Conversation

@jgoyvaerts

Copy link
Copy Markdown
Contributor

The asahi VM takes GpuVm::exec_lock() (drm_gpuvm_exec_lock()) for read-only VM queries and for every map and unmap. That locks the VM reservation plus the reservation of every external object, so each call costs O(external objects).

Under virtio-gpu (muvm/libkrun) every guest BO is external, because blobs are mapped through dma-buf export. With a game holding ~15k BOs, each submit spent 12-20 ms in drm_gpuvm_prepare_objects() validating its ranges, and each bind about a millisecond more. CS2 under FEX/muvm was capped at single-digit fps by that alone.

This VM is IMMEDIATE_MODE and DRM_GPUVM_RESV_PROTECTED. VA updates need the VM reservation (extobj list, VM data) and each object's gpuva lock (which the link and unlink paths take). The driver never validates, adds fences through GPUVM, or calls drm_gpuvm_bo_evict(), the paths that need an object's own reservation.

  1. Read-only queries (covers_range*, translate_offset, vm_context_mask, new_execution_context, capacity) take GpuVm::lock_inner(), the VM reservation alone. Every page-table and mapping change holds it, so readers see a consistent snapshot.
  2. VA updates (map_in_range_with_mode, map_at, bind_object, map_io, unmap_range_commit, drop_mappings_now, the user bind batch) take the new GpuVm::exec_lock_vm(). It is the drm_exec_until_all_locked() loop of drm_gpuvm_exec_lock() without drm_gpuvm_prepare_objects(): the VM reservation, plus obj if it is external. Backing is pinned and its segments copied before any reservation is taken. The low-memory unmap path already ran under the VM reservation alone.

Residency restoration and the other lock_vm() users keep the full lock.

Testing

J616s (T6040, 25G83). Both commits have been in our daily kernel since 2026-10-26, on integration 9cbdd0734d9 and then 5ca226e3c40 (patch-identical; this branch is on e3a9c0a58):

  • CS2 under FEX/muvm: submits no longer stall in drm_gpuvm_prepare_objects(). Without these commits the game was capped in single digits; with them the menu is GPU-bound (~22 fps at 1440p, the GPU queue busy 97% of the time).
  • Desktop compositor, GL and Vulkan clients; glmark2 60 s and the vk-default 1/2000 slice (769 pass / 0 fail), with 0 firmware recoveries.
  • Each commit builds on its own; asahi KUnit 163/163 on each. No new warnings.

Not tested with lockdep enabled.

Assisted-by: LLM

Submit validation (covers_ranges_batch and friends), translate_offset,
vm_context_mask, new_execution_context and capacity only read VmInner,
but took the full GPUVM exec lock: the VM reservation plus every
external BO's reservation. Each submit therefore cost O(external BOs).
Under virtio-gpu every guest BO is external (libkrun maps blobs through
dma-buf export), so a game with ~15k BOs spent 12-20 ms per submit in
drm_gpuvm_prepare_objects and was capped at single-digit fps.

Every page-table and mapping change already holds the VM reservation,
so readers need only that lock; use GpuVm::lock_inner() for them.

Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com>
Assisted-by: LLM
Every map and unmap (user VM_BIND, kernel mappings such as each G17
submission's completion record, object teardown) took GpuVm::exec_lock(),
i.e. drm_gpuvm_exec_lock(): the VM reservation plus the reservation of
every external object. Under virtio-gpu every guest BO is external, so
with ~15k BOs each bind and each submit spent around a millisecond in
drm_gpuvm_prepare_objects().

This VM is IMMEDIATE_MODE and RESV_PROTECTED: VA updates need the VM
reservation and each object's gpuva lock, which the link and unlink paths
take themselves. Backing is pinned and its segments copied before any
reservation is taken, no caller adds fences, and the driver already
unmaps under the VM reservation alone on its low-memory path.

Add GpuVm::exec_lock_vm(), which runs the drm_exec loop over the VM
reservation (and an external obj, if given) without
drm_gpuvm_prepare_objects(), and use it for all VA updates.

Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com>
Assisted-by: LLM
@RyanTheTide
RyanTheTide merged commit 902745c into aurora-silicon:integration/aurora Oct 31, 2026
@RyanTheTide

Copy link
Copy Markdown
Contributor

Merged into integration/aurora. Hardware: passed on the M2, M1 Pro and Neo in the integration candidate (integration/aurora with this, #556 and the ISP recovery series), GPU compute and readback plus glmark2 clean and no new err-level lines. J616s on aurora-wip with the same three: 4 glmark2 runs around 7000 with a second client submitting a hanging dispatch alongside, no GPU faults, journalctl -k -p 3 empty, no WARN or DART faults. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants