All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] KVM: Flush dirty ring resets before handling signals
@ 2026-08-28  9:11 Hao Zhang
  2026-08-28  9:19 ` [PATCH 2/2] KVM: Return dirty ring reset errors if no entries were reset Hao Zhang
  0 siblings, 1 reply; 2+ messages in thread
From: Hao Zhang @ 2026-08-28  9:11 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm

From: Hao Zhang <zhanghao1@kylinos.cn>

KVM bails out of KVM_RESET_DIRTY_RINGS if a signal is pending, but the
dirty ring reset flow can already have consumed harvested entries before
noticing the signal.  In that case, the entries have been marked invalid
and reset_index has been advanced, but the batched GFNs may not yet have
been reprotected by kvm_reset_dirty_gfn().

This breaks the dirty ring state machine: userspace has handed the GFNs
back to KVM, but KVM can leave the corresponding pages writable.  Future
guest writes to those pages may then fail to generate new dirty-ring
entries, causing dirty tracking to miss updates.

Make the signal path break out of the scan loop instead of returning
immediately, so any pending batch is flushed before kvm_dirty_ring_reset()
returns.

Fixes: 49005a2a3d2a ("KVM: Bail from the dirty ring reset flow if a signal is pending")
Signed-off-by: Hao Zhang <zhanghao1@kylinos.cn>
---
 virt/kvm/dirty_ring.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/dirty_ring.c b/virt/kvm/dirty_ring.c
index 572b854edf74..451eee9d8f69 100644
--- a/virt/kvm/dirty_ring.c
+++ b/virt/kvm/dirty_ring.c
@@ -122,6 +122,7 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
 	u64 cur_offset, next_offset;
 	unsigned long mask = 0;
 	struct kvm_dirty_gfn *entry;
+	int r = 0;
 
 	/*
 	 * Ensure concurrent calls to KVM_RESET_DIRTY_RINGS are serialized,
@@ -132,8 +133,10 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
 	lockdep_assert_held(&kvm->slots_lock);
 
 	while (likely((*nr_entries_reset) < INT_MAX)) {
-		if (signal_pending(current))
-			return -EINTR;
+		if (signal_pending(current)) {
+			r = -EINTR;
+			break;
+		}
 
 		entry = &ring->dirty_gfns[ring->reset_index & (ring->size - 1)];
 
@@ -213,7 +216,7 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
 
 	trace_kvm_dirty_ring_reset(ring);
 
-	return 0;
+	return r;
 }
 
 void kvm_dirty_ring_push(struct kvm_vcpu *vcpu, u32 slot, u64 offset)

base-commit: 45c13f3f9e3bb15fd89ff2864c6f627a3b4b4229
-- 
2.15.0


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

end of thread, other threads:[~2026-08-28  9:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28  9:11 [PATCH 1/2] KVM: Flush dirty ring resets before handling signals Hao Zhang
2026-08-28  9:19 ` [PATCH 2/2] KVM: Return dirty ring reset errors if no entries were reset Hao Zhang

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.