Adds a lock around memslots changes. Currently this lock does not have any effect on the syncronization model, but it will be used in a future commit to facilitate lazy rmap allocation. Signed-off-by: Ben Gardon <bgardon@xxxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 5 +++++ arch/x86/kvm/x86.c | 11 +++++++++++ include/linux/kvm_host.h | 2 ++ virt/kvm/kvm_main.c | 9 ++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 3900dcf2439e..bce7fa152473 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1124,6 +1124,11 @@ struct kvm_arch { #endif /* CONFIG_X86_64 */ bool shadow_mmu_active; + + /* + * Protects kvm->memslots. + */ + struct mutex memslot_assignment_lock; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fc32a7dbe4c4..30234fe96f48 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10649,6 +10649,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) raw_spin_lock_init(&kvm->arch.tsc_write_lock); mutex_init(&kvm->arch.apic_map_lock); spin_lock_init(&kvm->arch.pvclock_gtod_sync_lock); + mutex_init(&kvm->arch.memslot_assignment_lock); kvm->arch.kvmclock_offset = -get_kvmclock_base_ns(); pvclock_update_vm_gtod_copy(kvm); @@ -10868,6 +10869,16 @@ static int alloc_memslot_rmap(struct kvm_memory_slot *slot, return -ENOMEM; } + +void kvm_arch_assign_memslots(struct kvm *kvm, int as_id, + struct kvm_memslots *slots) +{ + mutex_lock(&kvm->arch.memslot_assignment_lock); + rcu_assign_pointer(kvm->memslots[as_id], slots); + mutex_unlock(&kvm->arch.memslot_assignment_lock); +} + + static int kvm_alloc_memslot_metadata(struct kvm_memory_slot *slot, unsigned long npages) { diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 8895b95b6a22..146bb839c754 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -720,6 +720,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, struct kvm_memory_slot *memslot, const struct kvm_userspace_memory_region *mem, enum kvm_mr_change change); +void kvm_arch_assign_memslots(struct kvm *kvm, int as_id, + struct kvm_memslots *slots); void kvm_arch_commit_memory_region(struct kvm *kvm, const struct kvm_userspace_memory_region *mem, struct kvm_memory_slot *old, diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2799c6660cce..e62a37bc5b90 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1270,6 +1270,12 @@ static int check_memory_region_flags(const struct kvm_userspace_memory_region *m return 0; } +__weak void kvm_arch_assign_memslots(struct kvm *kvm, int as_id, + struct kvm_memslots *slots) +{ + rcu_assign_pointer(kvm->memslots[as_id], slots); +} + static struct kvm_memslots *install_new_memslots(struct kvm *kvm, int as_id, struct kvm_memslots *slots) { @@ -1279,7 +1285,8 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm, WARN_ON(gen & KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS); slots->generation = gen | KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS; - rcu_assign_pointer(kvm->memslots[as_id], slots); + kvm_arch_assign_memslots(kvm, as_id, slots); + synchronize_srcu_expedited(&kvm->srcu); /* -- 2.31.1.498.g6c1eba8ee3d-goog