Skip to content

Commit e46ad85

Browse files
committed
KVM: Use mask of harvested dirty ring entries to coalesce dirty ring resets
Use "mask" instead of a dedicated boolean to track whether or not there is at least one to-be-reset entry for the current slot+offset. In the body of the loop, mask is zero only on the first iteration, i.e. !mask is equivalent to first_round. Opportunistically combine the adjacent "if (mask)" statements into a single if-statement. No functional change intended. Cc: Peter Xu <peterx@redhat.com> Cc: Yan Zhao <yan.y.zhao@intel.com> Cc: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com> Reviewed-by: James Houghton <jthoughton@google.com> Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> Reviewed-by: Yan Zhao <yan.y.zhao@intel.com> Reviewed-by: Peter Xu <peterx@redhat.com> Link: https://lore.kernel.org/r/20250516213540.2546077-6-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent ee188de commit e46ad85

1 file changed

Lines changed: 31 additions & 33 deletions

File tree

virt/kvm/dirty_ring.c

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
121121
u64 cur_offset, next_offset;
122122
unsigned long mask = 0;
123123
struct kvm_dirty_gfn *entry;
124-
bool first_round = true;
125124

126125
while (likely((*nr_entries_reset) < INT_MAX)) {
127126
if (signal_pending(current))
@@ -141,42 +140,42 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
141140
ring->reset_index++;
142141
(*nr_entries_reset)++;
143142

144-
/*
145-
* While the size of each ring is fixed, it's possible for the
146-
* ring to be constantly re-dirtied/harvested while the reset
147-
* is in-progress (the hard limit exists only to guard against
148-
* wrapping the count into negative space).
149-
*/
150-
if (!first_round)
143+
if (mask) {
144+
/*
145+
* While the size of each ring is fixed, it's possible
146+
* for the ring to be constantly re-dirtied/harvested
147+
* while the reset is in-progress (the hard limit exists
148+
* only to guard against the count becoming negative).
149+
*/
151150
cond_resched();
152151

153-
/*
154-
* Try to coalesce the reset operations when the guest is
155-
* scanning pages in the same slot.
156-
*/
157-
if (!first_round && next_slot == cur_slot) {
158-
s64 delta = next_offset - cur_offset;
159-
160-
if (delta >= 0 && delta < BITS_PER_LONG) {
161-
mask |= 1ull << delta;
162-
continue;
152+
/*
153+
* Try to coalesce the reset operations when the guest
154+
* is scanning pages in the same slot.
155+
*/
156+
if (next_slot == cur_slot) {
157+
s64 delta = next_offset - cur_offset;
158+
159+
if (delta >= 0 && delta < BITS_PER_LONG) {
160+
mask |= 1ull << delta;
161+
continue;
162+
}
163+
164+
/* Backwards visit, careful about overflows! */
165+
if (delta > -BITS_PER_LONG && delta < 0 &&
166+
(mask << -delta >> -delta) == mask) {
167+
cur_offset = next_offset;
168+
mask = (mask << -delta) | 1;
169+
continue;
170+
}
163171
}
164172

165-
/* Backwards visit, careful about overflows! */
166-
if (delta > -BITS_PER_LONG && delta < 0 &&
167-
(mask << -delta >> -delta) == mask) {
168-
cur_offset = next_offset;
169-
mask = (mask << -delta) | 1;
170-
continue;
171-
}
172-
}
173-
174-
/*
175-
* Reset the slot for all the harvested entries that have been
176-
* gathered, but not yet fully processed.
177-
*/
178-
if (mask)
173+
/*
174+
* Reset the slot for all the harvested entries that
175+
* have been gathered, but not yet fully processed.
176+
*/
179177
kvm_reset_dirty_gfn(kvm, cur_slot, cur_offset, mask);
178+
}
180179

181180
/*
182181
* The current slot was reset or this is the first harvested
@@ -185,7 +184,6 @@ int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring,
185184
cur_slot = next_slot;
186185
cur_offset = next_offset;
187186
mask = 1;
188-
first_round = false;
189187
}
190188

191189
/*

0 commit comments

Comments
 (0)