diff options
| author | Samuel Crossley <samuelcrossley@gmail.com> | 2026-09-19 15:13:03 -0700 |
|---|---|---|
| committer | Alex Williamson <alex@shazbot.org> | 2026-09-25 13:31:54 -0600 |
| commit | bc78c90728cd74d1c7335fef786fa51968bdebad (patch) | |
| tree | fd5dd88f9e92b286eebebddaf31884c0baaf8855 /tools/perf/scripts/python/stackcollapse.py | |
| parent | e281aa76bc22865052dc7b7250403ff1258856a0 (diff) | |
| download | linux-next-bc78c90728cd74d1c7335fef786fa51968bdebad.tar.gz linux-next-bc78c90728cd74d1c7335fef786fa51968bdebad.zip | |
vfio/type1: avoid walking reserved-only mappings while unpinning
Tearing down a large device-passthrough DMA mapping can process tens of
millions of reserved pfns in a single VFIO_IOMMU_UNMAP_DMA. A 128 GiB
reserved mapping holds about 33.6 million 4KiB pfns, and
vfio_unpin_pages_remote() walks every one of them whenever dma->has_rsvd
is set, because reserved and non-reserved pfns might be mixed. For a
mapping that contains only reserved pfns every put_pfn() is a no-op, but
each one still pays for the pfn_valid()/PageReserved() classification.
Seen on GPU-passthrough hosts running 6.13 with the v6.18 type1 series
backported, where a single VFIO_IOMMU_UNMAP_DMA held a CPU past the
soft-lockup watchdog (host identification, register dump and module list
trimmed):
watchdog: BUG: soft lockup - CPU#261 stuck for 22s! [qemu-system-x86:134503]
RIP: 0010:vfio_unpin_pages_remote+0x139/0x2a0 [vfio_iommu_type1]
Code: 90 4c 89 e1 48 c1 e9 34 75 74 4c 89 e1 48 c1 e9 22 75 6b 48 8b 0d f7 6f c2 e3 48 85 c9 74 5f 4c 89 e2 48 c1 ea 16 48 8b 0c d1 <48> 85 c9 74 4f 41 8b 55 30 4c 89 e6 48 c1 ee 0f 83 e6 7f c1 e6 05
Call Trace:
<IRQ>
? watchdog_timer_fn+0x3d6/0x440
? running_clock+0x10/0x10
? hrtimer_interrupt+0x185/0x580
? __sysvec_apic_timer_interrupt+0x44/0xe0
? sysvec_apic_timer_interrupt+0x6b/0x80
</IRQ>
<TASK>
? asm_sysvec_apic_timer_interrupt+0x16/0x20
? vfio_unpin_pages_remote+0x139/0x2a0 [vfio_iommu_type1]
vfio_sync_unpin+0x96/0xf0 [vfio_iommu_type1]
vfio_unmap_unpin+0x324/0x3d0 [vfio_iommu_type1]
vfio_remove_dma+0x25/0xa0 [vfio_iommu_type1]
vfio_iommu_type1_ioctl+0xcd5/0x1760 [vfio_iommu_type1]
? amd_pmu_v2_enable_all+0xa/0x30
? perf_pmu_sched_task+0xbf/0xf0
x64_sys_call+0x282/0x1ac0
? syscall_trace_enter+0x1e5/0x1f0
do_syscall_64+0x68/0x130
entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP is the mem_section root test in pfn_valid(), inlined into put_pfn()
through is_invalid_reserved_pfn(), so the stall is in the dma->has_rsvd
per-page loop. mem_section[] has no root for that pfn, so pfn_valid()
returns false and put_pfn() does nothing - for every pfn in the mapping.
Track whether the mapping also contains non-reserved pfns and skip the
walk entirely for reserved-only mappings. Mixed mappings keep the
existing per-pfn walk, and ordinary mappings keep the existing batched
unpin path.
Tested on an affected host: reserved-only mappings up to 128 GiB take the
new path and complete in microseconds. The ordinary-page path was
exercised unchanged.
Suggested-by: Alex Williamson <alex@shazbot.org>
Link: https://lore.kernel.org/all/20260803154707.71cc0d6b@shazbot.org/
Signed-off-by: Samuel Crossley <samuelcrossley@gmail.com>
Link: https://lore.kernel.org/r/20260919-vfio-v2-1-68e7ed355972@gmail.com
Signed-off-by: Alex Williamson <alex@shazbot.org>
Diffstat (limited to 'tools/perf/scripts/python/stackcollapse.py')
0 files changed, 0 insertions, 0 deletions
