KVM: Pass MMU notifier range flags to kvm_unmap_hva_range()
authorWill Deacon <will@kernel.org>
Tue, 11 Aug 2020 10:27:24 +0000 (11:27 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Aug 2020 08:31:07 +0000 (10:31 +0200)
commit fdfe7cbd58806522e799e2a50a15aee7f2cbb7b6 upstream.

The 'flags' field of 'struct mmu_notifier_range' is used to indicate
whether invalidate_range_{start,end}() are permitted to block. In the
case of kvm_mmu_notifier_invalidate_range_start(), this field is not
forwarded on to the architecture-specific implementation of
kvm_unmap_hva_range() and therefore the backend cannot sensibly decide
whether or not to block.

Add an extra 'flags' parameter to kvm_unmap_hva_range() so that
architectures are aware as to whether or not they are permitted to block.

Cc: <stable@vger.kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
Message-Id: <20200811102725.7121-2-will@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[will: Backport to 4.19; use 'blockable' instead of non-existent range flags]
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_host.h
arch/mips/include/asm/kvm_host.h
arch/mips/kvm/mmu.c
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/e500_mmu_host.c
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu.c
virt/kvm/arm/mmu.c
virt/kvm/kvm_main.c

index c9128bb187f9ad051dfe448b7d6f0d35b0d7c1e3..471859cbfe0bbe5462db401f621f4c7f71288877 100644 (file)
@@ -234,7 +234,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-                       unsigned long start, unsigned long end);
+                       unsigned long start, unsigned long end, bool blockable);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
index e9afdfcb8403cf5d5f45011e5b5cc7f228111d59..5e720742d647959fb1bf47e160bd08607b5af5ff 100644 (file)
@@ -370,7 +370,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-                       unsigned long start, unsigned long end);
+                       unsigned long start, unsigned long end, bool blockable);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
index 2b3fdfc9e0e77dffdc1503063e34035bde857579..c254761cb8ad91bb1d9861c48cb23d88ea5e613e 100644 (file)
@@ -936,7 +936,7 @@ enum kvm_mips_fault_result kvm_trap_emul_gva_fault(struct kvm_vcpu *vcpu,
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-                       unsigned long start, unsigned long end);
+                       unsigned long start, unsigned long end, bool blockable);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
index d8dcdb350405900928b83e7afa2112ecf3122518..098a7afd4d384cc4cac9cba8f67bedb6fecc9700 100644 (file)
@@ -512,7 +512,8 @@ static int kvm_unmap_hva_handler(struct kvm *kvm, gfn_t gfn, gfn_t gfn_end,
        return 1;
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+                       bool blockable)
 {
        handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL);
 
index 2f95e38f05491a6dcb60a1adda6ff850ce39c1b9..7b54d8412367e36b62dc6f381e72362ac0dd8d3a 100644 (file)
@@ -68,7 +68,8 @@
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 
 extern int kvm_unmap_hva_range(struct kvm *kvm,
-                              unsigned long start, unsigned long end);
+                              unsigned long start, unsigned long end,
+                              bool blockable);
 extern int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
index cc05f346e04219d0c737948c463d890f55bf6deb..bc9d1321dc730770c4c1093b0e115f323cfb6c61 100644 (file)
@@ -812,7 +812,8 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm,
        kvm->arch.kvm_ops->commit_memory_region(kvm, mem, old, new);
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+                       bool blockable)
 {
        return kvm->arch.kvm_ops->unmap_hva_range(kvm, start, end);
 }
index 8f2985e46f6f193d975e2d26ca92c2df60742649..bbb02195dc53076717d19ed9cc633687e8ca8014 100644 (file)
@@ -737,7 +737,8 @@ static int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
        return 0;
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+                       bool blockable)
 {
        /* kvm_unmap_hva flushes everything anyways */
        kvm_unmap_hva(kvm, start);
index ce7b3b22ae86bc959f8a3f2bc5acb9b4645ccef3..4876411a072a7d1da0dc65b3f96e918575404610 100644 (file)
@@ -1465,7 +1465,8 @@ asmlinkage void __noreturn kvm_spurious_fault(void);
        ____kvm_handle_fault_on_reboot(insn, "")
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end);
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+                       bool blockable);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
index 92ff656e18101f6dd029aeacc5294917af97e295..a2ff5c214738a0a08c9b4823e243086d17396acc 100644 (file)
@@ -1956,7 +1956,8 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
        return kvm_handle_hva_range(kvm, hva, hva + 1, data, handler);
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+                       bool blockable)
 {
        return kvm_handle_hva_range(kvm, start, end, 0, kvm_unmap_rmapp);
 }
index a5bc10d30618f2023427874564a8160c0dacf5c9..3957ff0ecda57b95ada86ee1d21756b4b6f3f10b 100644 (file)
@@ -1825,7 +1825,7 @@ static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *dat
 }
 
 int kvm_unmap_hva_range(struct kvm *kvm,
-                       unsigned long start, unsigned long end)
+                       unsigned long start, unsigned long end, bool blockable)
 {
        if (!kvm->arch.pgd)
                return 0;
index 1218ea663c6d26ecdfe114dc611bba11db21dd6c..2155b52b17ecaff6abe13b862f46713af96eca3a 100644 (file)
@@ -410,7 +410,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
         * count is also read inside the mmu_lock critical section.
         */
        kvm->mmu_notifier_count++;
-       need_tlb_flush = kvm_unmap_hva_range(kvm, start, end);
+       need_tlb_flush = kvm_unmap_hva_range(kvm, start, end, blockable);
        need_tlb_flush |= kvm->tlbs_dirty;
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)