Re: [PATCH] KVM: pfncache: track HVA invalidations for HVA-based caches

From: David Woodhouse

Date: Mon Aug 03 2026 - 11:43:07 EST


(Spent the day prodding at AI on this while I'm in meetings; I've let
it draft the below for me which isn't entirely my voice but I'm mostly
OK with it...)

On Mon, 2026-07-27 at 10:25 -0700, Sean Christopherson wrote:
> Can you provide the reproducer? That would be super helpful for reviewing and
> iterating on this fix, and probably as a regression test for future changes as
> well.

There's one at https://david.woodhou.se/xen_shinfo_race.c now — no
memslots, just five processes racing
KVM_XEN_HVM_SET_ATTR(SHARED_INFO_HVA) against MAP_FIXED shmem remaps
over the cached HVA. It fires the syzbot splat within five seconds in
a QEMU guest running an unfixed kernel. Tracing confirms the
diagnosis: complete invalidations (start *and* end) land entirely
within the window where hva_to_pfn_retry() has dropped gpc->lock for
the GUP, so by the time it re-checks, mn_active_invalidate_count is
back to zero and mmu_invalidate_seq never moved because nothing
overlapped a memslot. (Note syzbot also found its own reproducer last
week¹.)

The same bug is also reachable through the vcpu_info cache, where the
stale mapping is then dereferenced by kvm_setup_guest_pvclock() on the
next KVM_RUN — which is syzbot+fb7c2dd166d3ea63df2a, the one Heitor
posted a sibling-GPC workaround for². Reproducer for that variant:
https://david.woodhou.se/vcpu_info_race.c

Since you said you'd want to land the sequence fix together with the
range-based optimization: I've taken a shot at that. The branch at

https://git.infradead.org/?p=users/dwmw2/linux.git;a=shortlog;h=refs/heads/pfncache-fixes

has your gpc_invalidate_seq patch (with the sampling side in
hva_to_pfn_retry() also switched over, and both syzbot tags; Cc:
stable and deliberately minimal for backporting) followed by your Oct
2024 patches³ rebased on top, with the range check's second arm now
checking gpc_invalidate_seq so it catches invalidations which complete
within the refresh window without touching a memslot. I've dropped the
sleep-based wait for now.

David Woodhouse (2):
KVM: pfncache: use a dedicated invalidation sequence for cache refresh
KVM: pfncache: Implement range-based invalidation check for hva_to_pfn_retry()

Sean Christopherson (3):
KVM: pfncache: Snapshot invalidation sequence immediately before hva_to_pfn()
KVM: pfncache: Wait for in-progress invalidations to complete during refresh
KVM: pfncache: Add lockless checking of cache invalidation events

include/linux/kvm_host.h | 4 ++
virt/kvm/kvm_main.c | 17 +++++-
virt/kvm/pfncache.c | 144 +++++++++++++++++++++++++++++++----------------
3 files changed, 114 insertions(+), 51 deletions(-)

Both reproducers fire in seconds on the unfixed base and survive
ten-minute soaks under KASAN+lockdep with the first patch alone and
with the full series.

On the RT concern with taking mn_invalidate_lock across the GPC walk:
I don't think the "sleeping while atomic" problem exists once the GPC
locks are no longer irqsave, which v2 of the rwlock_t series⁴ already
does.

¹ https://lore.kernel.org/all/6a6f68af.13bfb6d0.1ecdd5.0271.GAE@xxxxxxxxxx/
² https://lore.kernel.org/all/20260723-kvm_guest_pvclock-v1-1-bba3ea77419b@xxxxxxxxxx/
³ https://lore.kernel.org/all/Zw8DINUkJJKDByXE@xxxxxxxxxx/
https://lore.kernel.org/all/20260529165114.748639-6-seanjc@xxxxxxxxxx/

Attachment: smime.p7s
Description: S/MIME cryptographic signature