From: Alex Williamson <alex@shazbot.org>
To: Samuel Crossley <samuelcrossley@gmail.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, alex@shazbot.org
Subject: Re: [PATCH v2] vfio/type1: avoid walking reserved-only mappings while unpinning
Date: Fri, 25 Sep 2026 14:49:32 -0600 [thread overview]
Message-ID: <20260925144932.485c2dec@shazbot.org> (raw)
In-Reply-To: <20260919-vfio-v2-1-68e7ed355972@gmail.com>
On Sat, 19 Sep 2026 15:13:03 -0700
Samuel Crossley <samuelcrossley@gmail.com> wrote:
> 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>
> ---
> This is the reserved-only fast path you suggested on v1, tested on
> the affected hosts. There is indeed no evidence that the non-reserved
> VFIO path needs chunking, and agree any such change to
> unpin_user_page_range_dirty_lock() would belong in mm, so not
> including it in this patch.
> ---
> Changes in v2:
> - Replace v1's cond_resched() chunking with the reserved-only fast path.
> - Tested on an affected host; reserved-only mappings up to 128 GiB now
> complete in microseconds instead of walking ~33.6M pfns.
> - Link to v1: https://patch.msgid.link/20260723-vfio-v1-1-3b59579916c6@gmail.com
> ---
> drivers/vfio/vfio_iommu_type1.c | 12 ++++++++----
> 1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index c8151ba54de3..f7addfbe1aab 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -94,6 +94,7 @@ struct vfio_dma {
> bool lock_cap; /* capable(CAP_IPC_LOCK) */
> bool vaddr_invalid;
> bool has_rsvd; /* has 1 or more rsvd pfns */
> + bool has_non_rsvd; /* has 1 or more !rsvd pfns */
> struct task_struct *task;
> struct rb_root pfn_list; /* Ex-user pinned pfn list */
> unsigned long *bitmap;
> @@ -791,6 +792,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
>
> out:
> dma->has_rsvd |= rsvd;
> + dma->has_non_rsvd |= !rsvd;
> ret = vfio_lock_acct(dma, lock_acct, false);
>
> unpin_out:
> @@ -821,11 +823,13 @@ static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
> long unlocked = 0, locked = vpfn_pages(dma, iova, npage);
>
> if (dma->has_rsvd) {
> - unsigned long i;
> + if (dma->has_non_rsvd) {
> + unsigned long i;
>
> - for (i = 0; i < npage; i++)
> - if (put_pfn(pfn++, dma->prot))
> - unlocked++;
> + for (i = 0; i < npage; i++)
> + if (put_pfn(pfn++, dma->prot))
> + unlocked++;
> + }
> } else {
> put_valid_unreserved_pfns(pfn, npage, dma->prot);
> unlocked = npage;
>
> ---
> base-commit: 4e3c1fc8abcb8eff062150b4340fa4569696d645
> change-id: 20260723-vfio-decd86bf3cf6
>
> Best regards,
> --
> Samuel Crossley <samuelcrossley@gmail.com>
>
Applied to vfio next for v7.4. Thanks,
Alex
prev parent reply other threads:[~2026-09-25 20:51 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 22:13 [PATCH v2] vfio/type1: avoid walking reserved-only mappings while unpinning Samuel Crossley
2026-09-25 20:49 ` Alex Williamson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925144932.485c2dec@shazbot.org \
--to=alex@shazbot.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=samuelcrossley@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.