Skip to content

Commit 9fa336e

Browse files
Paul Durrantsean-jc
authored andcommitted
KVM: pfncache: check the need for invalidation under read lock first
When processing mmu_notifier invalidations for gpc caches, pre-check for overlap with the invalidation event while holding gpc->lock for read, and only take gpc->lock for write if the cache needs to be invalidated. Doing a pre-check without taking gpc->lock for write avoids unnecessarily contending the lock for unrelated invalidations, which is very beneficial for caches that are heavily used (but rarely subjected to mmu_notifier invalidations). Signed-off-by: Paul Durrant <pdurrant@amazon.com> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Link: https://lore.kernel.org/r/20240215152916.1158-20-paul@xen.org Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 615451d commit 9fa336e

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

virt/kvm/pfncache.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,30 @@ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
2929

3030
spin_lock(&kvm->gpc_lock);
3131
list_for_each_entry(gpc, &kvm->gpc_list, list) {
32-
write_lock_irq(&gpc->lock);
32+
read_lock_irq(&gpc->lock);
3333

3434
/* Only a single page so no need to care about length */
3535
if (gpc->valid && !is_error_noslot_pfn(gpc->pfn) &&
3636
gpc->uhva >= start && gpc->uhva < end) {
37-
gpc->valid = false;
37+
read_unlock_irq(&gpc->lock);
38+
39+
/*
40+
* There is a small window here where the cache could
41+
* be modified, and invalidation would no longer be
42+
* necessary. Hence check again whether invalidation
43+
* is still necessary once the write lock has been
44+
* acquired.
45+
*/
46+
47+
write_lock_irq(&gpc->lock);
48+
if (gpc->valid && !is_error_noslot_pfn(gpc->pfn) &&
49+
gpc->uhva >= start && gpc->uhva < end)
50+
gpc->valid = false;
51+
write_unlock_irq(&gpc->lock);
52+
continue;
3853
}
39-
write_unlock_irq(&gpc->lock);
54+
55+
read_unlock_irq(&gpc->lock);
4056
}
4157
spin_unlock(&kvm->gpc_lock);
4258
}

0 commit comments

Comments
 (0)