[PATCH 27/31] KVM: let kvm_arch_post_set_memory_attributes drop mmu_lock

From: Paolo Bonzini

Date: Fri Sep 18 2026 - 10:11:18 EST


Ensure that mmu_invalidate_in_progress is not cleared until
kvm_arch_post_set_memory_attributes() returns.

kvm_arch_post_set_memory_attributes() runs with the MMU lock taken
exclusively, so a concurrent page fault would be blocked anyway, and
delaying the clearing makes it possible to use cond_resched() within
kvm_arch_post_set_memory_attributes().

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
virt/kvm/kvm_main.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2045252bd9c9..eb4a661cd0f7 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2516,7 +2516,7 @@ static bool kvm_range_memory_attributes_need_sync(struct kvm *kvm,
return kvm_range_has_any_memory_attributes(kvm, start, end, mask);
}

-static __always_inline void kvm_handle_gfn_range(struct kvm *kvm,
+static __always_inline bool kvm_handle_gfn_range(struct kvm *kvm,
struct kvm_mmu_notifier_range *range)
{
struct kvm_gfn_range gfn_range;
@@ -2566,6 +2566,8 @@ static __always_inline void kvm_handle_gfn_range(struct kvm *kvm,

if (found_memslot)
KVM_MMU_UNLOCK(kvm);
+
+ return found_memslot;
}

static bool kvm_pre_set_memory_attributes(struct kvm *kvm,
@@ -2603,10 +2605,11 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
.end = end,
.arg.attributes = attributes,
.handler = kvm_arch_post_set_memory_attributes,
- .on_lock = kvm_mmu_invalidate_end,
+ .on_lock = (void *)kvm_null_fn,
.may_block = true,
};
bool sync = false;
+ bool found_memslot;
unsigned long i;
void *entry;
int r = 0;
@@ -2637,7 +2640,7 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
cond_resched();
}

- kvm_handle_gfn_range(kvm, &pre_set_range);
+ found_memslot = kvm_handle_gfn_range(kvm, &pre_set_range);

for (i = start; i < end; i++) {
r = xa_err(xa_store(&kvm->mem_attrs.array, i, entry,
@@ -2650,7 +2653,12 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
smp_store_release(&kvm->mem_attrs.generation,
kvm->mem_attrs.generation + 1);

- kvm_handle_gfn_range(kvm, &post_set_range);
+ if (found_memslot) {
+ kvm_handle_gfn_range(kvm, &post_set_range);
+ KVM_MMU_LOCK(kvm);
+ kvm_mmu_invalidate_end(kvm);
+ KVM_MMU_UNLOCK(kvm);
+ }

out_unlock:
mutex_unlock(&kvm->slots_lock);
--
2.52.0