Merge tag 'kvmarm-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm...
[platform/kernel/linux-starfive.git] / virt / kvm / kvm_main.c
index c2723cc..c5e4f0a 100644 (file)
@@ -686,6 +686,24 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
 
        return __kvm_handle_hva_range(kvm, &range);
 }
+
+static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+       /*
+        * Skipping invalid memslots is correct if and only change_pte() is
+        * surrounded by invalidate_range_{start,end}(), which is currently
+        * guaranteed by the primary MMU.  If that ever changes, KVM needs to
+        * unmap the memslot instead of skipping the memslot to ensure that KVM
+        * doesn't hold references to the old PFN.
+        */
+       WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
+
+       if (range->slot->flags & KVM_MEMSLOT_INVALID)
+               return false;
+
+       return kvm_set_spte_gfn(kvm, range);
+}
+
 static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
                                        struct mm_struct *mm,
                                        unsigned long address,
@@ -707,7 +725,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
        if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
                return;
 
-       kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn);
+       kvm_handle_hva_range(mn, address, address + 1, pte, kvm_change_spte_gfn);
 }
 
 void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start,