Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH v3 0/7] KVM: x86/xen: Fix Xen/GPC/PREEMPT_RT issues with rwlock_t
@ 2026-08-05 19:55 Woodhouse, David
  2026-08-05 19:55 ` [PATCH v3 1/7] KVM: pfncache: use a dedicated invalidation sequence for cache refresh Woodhouse, David
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Woodhouse, David @ 2026-08-05 19:55 UTC (permalink / raw)
  To: seanjc@google.com, pbonzini@redhat.com, akpm@linux-foundation.org
  Cc: bigeasy@linutronix.de, peterz@infradead.org, mingo@redhat.com,
	will@kernel.org, longman@redhat.com, boqun@kernel.org,
	tglx@kernel.org, paul@xen.org, Stollmaier, Carsten,
	dwmw2@infradead.org, Woodhouse, David, daniel.vetter@ffwll.ch,
	mhocko@suse.com, jgg@nvidia.com, christian.koenig@amd.com,
	jglisse@redhat.com, david@kernel.org, ljs@kernel.org,
	liam@infradead.org, vbabka@kernel.org, rppt@kernel.org,
	surenb@google.com, bp@alien8.de, dave.hansen@linux.intel.com,
	hpa@zytor.com, x86@kernel.org, kvm@vger.kernel.org,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org


[-- Attachment #1.1: Type: text/plain, Size: 7222 bytes --]

The gfn_to_pfn_cache read side is currently protected by a per-GPC
rwlock_t. That is a problem on PREEMPT_RT, which turns rwlock_t into a
sleeping lock, when the GPC is read from hardirq context (the Xen timer
callback and kvm_arch_set_irq_inatomic()) and from the scheduler path
(kvm_xen_runstate_set_preempted() via kvm_sched_out()).

v1 and v2 worked around that with read_trylock() and a pile of related
cleanups: dropping the now-unnecessary IRQ disabling, and adding CLASS()
constructs to make the lock-and-check dance less error-prone. That series
stalled, partly on the observation that a trylock which callers must be
prepared to fail is an awkward contract to build on.

This version takes the locking away instead. Readers run under
rcu_read_lock() alone, which is legal in every context a GPC is read
from, never fails, and never spins. Mutators clear gpc->valid, wait for
a grace period, and only then touch anything a reader might be looking
at — exactly the pattern of a TLB shootdown, and for the same reason.
That deletes the trylock contortions, the double-lock dance with its
lockdep subclass hack in the runstate update, and the CLASS() machinery
along with them: 15 of the 20 patches in v2 simply become unnecessary
once there is no lock object left to manage.

The only complexity is that the OOM reaper path currently calls
non_block_start(), which is a little overzealous and makes the RCU
grace period sad too. So we rip that out in patch 2.

Patch 1 is the standalone fix for two syzbot reports, already posted
separately¹ and verified by syzbot against the published branch. It
is Cc: stable and stands alone; the rest of the series is cleanup and
consolidation on top.

Patch 2 removes the non_block_start()/end() annotation from the
!blockable mmu_notifier walk. This is a prerequisite, because the
invalidation path now waits for an RCU grace period. That wait is safe
even for the OOM reaper: the actual requirement, per the commit which
added non_block_start() in the first place, is that the caller must not
"have an indirect dependency upon the page allocator and hence close the
loop with the oom reaper", and a grace period has no such dependency —
GPC readers never allocate, never take mmap_lock and never sleep. The
annotation is coarser than the requirement, though, and forbids *any*
voluntary schedule, so it would splat regardless. It is already known to
fire spuriously on PREEMPT_RT, where a plain spinlock becomes sleepable;
all of this was gone over at some length on v2². Cc'ing everyone
involved in the original code.

Patches 4-6 are Sean's from v2, unchanged in substance. Patch 7 is
Carsten's steal-time conversion, which Sean explicitly did not want to
take in v2 without more confidence that it would not regress setups
running NUMA autobalancing and KSM, on the grounds that steal time is
updated on every vCPU load rather than rarely like KVM_REQ_CLOCK_UPDATE.
That concern was well founded, and measuring it turned up a real problem
(now fixed) in this series — see below.

Numbers
=======

Booting a Xen HVM guest (QEMU -accel kvm,xen-version=0x4000a, 4 vCPUs)
on a KASAN + PROVE_LOCKING kernel, timed to the login prompt:

  rwlock (patch 1 only, pre-RCU)  45.562 s
  RCU, this series               45.551 s
  RCU, without the fast path     51.73  s   (1400+ grace periods, 5.9 s)

The middle row is the point: the RCU conversion is performance-neutral
against the code it replaces. Getting there required keeping the
optimisation the rwlock version already had — a refresh which resolves
to the same uHVA, in the same memslot, for the same gPA does not need to
invalidate anything, because the gPA => uHVA translation has not changed
and gpc->valid already asserts the uHVA => PFN mapping is good.

Testing
=======

 - syzbot's C reproducer for the shared_info UAF: fires on the first run
   without patch 1; clean over 12 runs with the series. syzbot has also
   tested patch 1 directly and issued a Tested-by.
 - Targeted reproducers for both syzbot reports (xen_shinfo_race,
   vcpu_info_race) and one for the steal-time cache, soaked 10 minutes
   each under KASAN: clean. Instrumentation showed vcpu_info_race only
   refreshing the cache 16 times over the whole soak, so treat that one
   as weak evidence; the other two drove 4.2M and 147k refreshes
   respectively.
 - xen_shinfo_test, steal_time: pass.
 - The reproducers cover both sides of the fast path: syzbot's alternates
   between two HVAs, so the fast path correctly declines 2506/2506 times
   and takes a grace period each time; a single-HVA reproducer takes it
   4.07M times out of 4.2M refreshes.

Not addressed
=============

Range-based invalidation, and the needs_invalidation flag from earlier
drafts, are both still absent. With the fast path in place the
motivation largely evaporates: a cache which is invalidated but whose
page returns at the same address costs nothing to "refresh", so making
the invalidation itself more precise buys little. I would rather not add
that complexity without a workload which demonstrates it is needed.

  ¹ https://lore.kernel.org/all/6a734239.d1b4d54b.5552d.001c.GAE@google.com/
  ² https://lore.kernel.org/all/20260601134008.rllwJtn-@linutronix.de/

v3:
 - Use RCU for the read side instead of read_trylock(), dropping the
   CLASS() APIs, the irqsave removal patches and the locking/rt patch
   (15 of v2's 20 patches) as no longer applicable.
 - Remove non_block_start()/end() from the !blockable notifier walk.
 - Keep the same-uHVA refresh shortcut, without which the conversion
   costs a grace period per mmu_notifier invalidation.
 - Restore the KVM_REQ_STEAL_UPDATE early-out on the MSR disable path,
   which v2's steal time patch had inadvertently made unconditional.
 - Rebase onto kvm-x86/next, where the MSR handling has moved to msrs.c.

v2: https://lore.kernel.org/all/20260529165114.748639-1-seanjc@google.com
 - Add the CLASS() APIs.
 - Move the steal time change to the very end.
 - "Fix" a dirty logging inconsistency with the Xen vCPU info page.

v1: https://lore.kernel.org/all/20260508181717.3230988-1-dwmw2@infradead.org


Carsten Stollmaier (1):
      KVM: x86: Use gfn_to_pfn_cache for steal time / preempted status

David Woodhouse (3):
      KVM: pfncache: use a dedicated invalidation sequence for cache refresh
      mm/mmu_notifier: Remove non_block_start/end() from notifier invocation
      KVM: pfncache: Use RCU for readers instead of a rwlock

Sean Christopherson (3):
      KVM: x86/xen: Extract delivery of event to vCPU into a separate helper
      KVM: x86/xen: Explicitly tag "shared info" page as never being dirty tracked
      KVM: x86/xen: Don't dirty track "vCPU info" page

 arch/x86/include/asm/kvm_host.h |   2 +-
 arch/x86/kvm/msrs.c             |   7 +-
 arch/x86/kvm/x86.c              | 128 +++++++++---------
 arch/x86/kvm/xen.c              | 200 ++++++++++++++--------------
 include/linux/kvm_host.h        |  28 ++--
 include/linux/kvm_types.h       |   2 +-
 mm/mmu_notifier.c               |  11 +-
 virt/kvm/kvm_main.c             |  10 ++
 virt/kvm/pfncache.c             | 282 +++++++++++++++++++++++++---------------
 9 files changed, 369 insertions(+), 301 deletions(-)


[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 15938 bytes --]

[-- Attachment #2.1: Type: text/plain, Size: 215 bytes --]




Amazon Development Centre (London) Ltd. Registered in England and Wales with registration number 04543232 with its registered office at 1 Principal Place, Worship Street, London EC2A 2FA, United Kingdom.



[-- Attachment #2.2: Type: text/html, Size: 228 bytes --]

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

end of thread, other threads:[~2026-08-06 22:03 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-05 19:55 [PATCH v3 0/7] KVM: x86/xen: Fix Xen/GPC/PREEMPT_RT issues with rwlock_t Woodhouse, David
2026-08-05 19:55 ` [PATCH v3 1/7] KVM: pfncache: use a dedicated invalidation sequence for cache refresh Woodhouse, David
2026-08-05 19:55 ` [PATCH v3 2/7] mm/mmu_notifier: Remove non_block_start/end() from notifier invocation Woodhouse, David
2026-08-05 19:55 ` [PATCH v3 3/7] KVM: pfncache: Use RCU for readers instead of a rwlock Woodhouse, David
2026-08-05 20:36   ` sashiko-bot
2026-08-06 16:53     ` Sean Christopherson
2026-08-06 17:58       ` Woodhouse, David
2026-08-06 18:11         ` Sean Christopherson
2026-08-06 18:23           ` Woodhouse, David
2026-08-06 20:38         ` David Woodhouse
2026-08-06 21:52           ` Paul E. McKenney
2026-08-06 22:02             ` David Woodhouse
2026-08-05 19:55 ` [PATCH v3 4/7] KVM: x86/xen: Extract delivery of event to vCPU into a separate helper Woodhouse, David
2026-08-05 20:47   ` sashiko-bot
2026-08-05 22:35     ` David Woodhouse
2026-08-06 10:00       ` David Woodhouse
2026-08-06 14:32         ` David Woodhouse
2026-08-05 19:56 ` [PATCH v3 5/7] KVM: x86/xen: Explicitly tag "shared info" page as never being dirty tracked Woodhouse, David
2026-08-05 19:56 ` [PATCH v3 6/7] KVM: x86/xen: Don't dirty track "vCPU info" page Woodhouse, David
2026-08-05 19:56 ` [PATCH v3 7/7] KVM: x86: Use gfn_to_pfn_cache for steal time / preempted status Woodhouse, David
2026-08-05 21:15   ` sashiko-bot

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