From: Greg Kroah-Hartman Date: Mon, 24 Aug 2020 16:04:15 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.4.234~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bbcf45452c9bdb758f039c0ff2005c71b8e95b3a;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: kvm-arm64-only-reschedule-if-mmu_notifier_range_blockable-is-not-set.patch kvm-pass-mmu-notifier-range-flags-to-kvm_unmap_hva_range.patch --- diff --git a/queue-5.4/kvm-arm64-only-reschedule-if-mmu_notifier_range_blockable-is-not-set.patch b/queue-5.4/kvm-arm64-only-reschedule-if-mmu_notifier_range_blockable-is-not-set.patch new file mode 100644 index 00000000000..6ceb1d448e7 --- /dev/null +++ b/queue-5.4/kvm-arm64-only-reschedule-if-mmu_notifier_range_blockable-is-not-set.patch @@ -0,0 +1,105 @@ +From b5331379bc62611d1026173a09c73573384201d9 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Tue, 11 Aug 2020 11:27:25 +0100 +Subject: KVM: arm64: Only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is not set + +From: Will Deacon + +commit b5331379bc62611d1026173a09c73573384201d9 upstream. + +When an MMU notifier call results in unmapping a range that spans multiple +PGDs, we end up calling into cond_resched_lock() when crossing a PGD boundary, +since this avoids running into RCU stalls during VM teardown. Unfortunately, +if the VM is destroyed as a result of OOM, then blocking is not permitted +and the call to the scheduler triggers the following BUG(): + + | BUG: sleeping function called from invalid context at arch/arm64/kvm/mmu.c:394 + | in_atomic(): 1, irqs_disabled(): 0, non_block: 1, pid: 36, name: oom_reaper + | INFO: lockdep is turned off. + | CPU: 3 PID: 36 Comm: oom_reaper Not tainted 5.8.0 #1 + | Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 + | Call trace: + | dump_backtrace+0x0/0x284 + | show_stack+0x1c/0x28 + | dump_stack+0xf0/0x1a4 + | ___might_sleep+0x2bc/0x2cc + | unmap_stage2_range+0x160/0x1ac + | kvm_unmap_hva_range+0x1a0/0x1c8 + | kvm_mmu_notifier_invalidate_range_start+0x8c/0xf8 + | __mmu_notifier_invalidate_range_start+0x218/0x31c + | mmu_notifier_invalidate_range_start_nonblock+0x78/0xb0 + | __oom_reap_task_mm+0x128/0x268 + | oom_reap_task+0xac/0x298 + | oom_reaper+0x178/0x17c + | kthread+0x1e4/0x1fc + | ret_from_fork+0x10/0x30 + +Use the new 'flags' argument to kvm_unmap_hva_range() to ensure that we +only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is set in the notifier +flags. + +Cc: +Fixes: 8b3405e345b5 ("kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd") +Cc: Marc Zyngier +Cc: Suzuki K Poulose +Cc: James Morse +Signed-off-by: Will Deacon +Message-Id: <20200811102725.7121-3-will@kernel.org> +Signed-off-by: Paolo Bonzini +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + virt/kvm/arm/mmu.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/virt/kvm/arm/mmu.c ++++ b/virt/kvm/arm/mmu.c +@@ -332,7 +332,8 @@ static void unmap_stage2_puds(struct kvm + * destroying the VM), otherwise another faulting VCPU may come in and mess + * with things behind our backs. + */ +-static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) ++static void __unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size, ++ bool may_block) + { + pgd_t *pgd; + phys_addr_t addr = start, end = start + size; +@@ -357,11 +358,16 @@ static void unmap_stage2_range(struct kv + * If the range is too large, release the kvm->mmu_lock + * to prevent starvation and lockup detector warnings. + */ +- if (next != end) ++ if (may_block && next != end) + cond_resched_lock(&kvm->mmu_lock); + } while (pgd++, addr = next, addr != end); + } + ++static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) ++{ ++ __unmap_stage2_range(kvm, start, size, true); ++} ++ + static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, + phys_addr_t addr, phys_addr_t end) + { +@@ -2045,7 +2051,10 @@ static int handle_hva_to_gpa(struct kvm + + static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) + { +- unmap_stage2_range(kvm, gpa, size); ++ unsigned flags = *(unsigned *)data; ++ bool may_block = flags & MMU_NOTIFIER_RANGE_BLOCKABLE; ++ ++ __unmap_stage2_range(kvm, gpa, size, may_block); + return 0; + } + +@@ -2056,7 +2065,7 @@ int kvm_unmap_hva_range(struct kvm *kvm, + return 0; + + trace_kvm_unmap_hva_range(start, end); +- handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); ++ handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, &flags); + return 0; + } + diff --git a/queue-5.4/kvm-pass-mmu-notifier-range-flags-to-kvm_unmap_hva_range.patch b/queue-5.4/kvm-pass-mmu-notifier-range-flags-to-kvm_unmap_hva_range.patch new file mode 100644 index 00000000000..0d424b13dfb --- /dev/null +++ b/queue-5.4/kvm-pass-mmu-notifier-range-flags-to-kvm_unmap_hva_range.patch @@ -0,0 +1,170 @@ +From fdfe7cbd58806522e799e2a50a15aee7f2cbb7b6 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Tue, 11 Aug 2020 11:27:24 +0100 +Subject: KVM: Pass MMU notifier range flags to kvm_unmap_hva_range() + +From: Will Deacon + +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: +Cc: Marc Zyngier +Cc: Suzuki K Poulose +Cc: James Morse +Signed-off-by: Will Deacon +Message-Id: <20200811102725.7121-2-will@kernel.org> +Signed-off-by: Paolo Bonzini +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/include/asm/kvm_host.h | 2 +- + arch/arm64/include/asm/kvm_host.h | 2 +- + arch/mips/include/asm/kvm_host.h | 2 +- + arch/mips/kvm/mmu.c | 3 ++- + arch/powerpc/include/asm/kvm_host.h | 3 ++- + arch/powerpc/kvm/book3s.c | 3 ++- + arch/powerpc/kvm/e500_mmu_host.c | 3 ++- + arch/x86/include/asm/kvm_host.h | 3 ++- + arch/x86/kvm/mmu.c | 3 ++- + virt/kvm/arm/mmu.c | 2 +- + virt/kvm/kvm_main.c | 3 ++- + 11 files changed, 18 insertions(+), 11 deletions(-) + +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -266,7 +266,7 @@ int __kvm_arm_vcpu_set_events(struct kvm + + #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, unsigned flags); + int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); + + unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -427,7 +427,7 @@ int __kvm_arm_vcpu_set_events(struct kvm + + #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, unsigned flags); + int 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); +--- a/arch/mips/include/asm/kvm_host.h ++++ b/arch/mips/include/asm/kvm_host.h +@@ -939,7 +939,7 @@ enum kvm_mips_fault_result kvm_trap_emul + + #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, unsigned flags); + int 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); +--- a/arch/mips/kvm/mmu.c ++++ b/arch/mips/kvm/mmu.c +@@ -512,7 +512,8 @@ static int kvm_unmap_hva_handler(struct + 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, ++ unsigned flags) + { + handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); + +--- a/arch/powerpc/include/asm/kvm_host.h ++++ b/arch/powerpc/include/asm/kvm_host.h +@@ -58,7 +58,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, ++ unsigned flags); + 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 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); +--- a/arch/powerpc/kvm/book3s.c ++++ b/arch/powerpc/kvm/book3s.c +@@ -867,7 +867,8 @@ void kvmppc_core_commit_memory_region(st + kvm->arch.kvm_ops->commit_memory_region(kvm, mem, old, new, change); + } + +-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, ++ unsigned flags) + { + return kvm->arch.kvm_ops->unmap_hva_range(kvm, start, end); + } +--- a/arch/powerpc/kvm/e500_mmu_host.c ++++ b/arch/powerpc/kvm/e500_mmu_host.c +@@ -734,7 +734,8 @@ static int kvm_unmap_hva(struct kvm *kvm + 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, ++ unsigned flags) + { + /* kvm_unmap_hva flushes everything anyways */ + kvm_unmap_hva(kvm, start); +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -1553,7 +1553,8 @@ asmlinkage void kvm_spurious_fault(void) + _ASM_EXTABLE(666b, 667b) + + #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, ++ unsigned flags); + int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end); + int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); + int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -2045,7 +2045,8 @@ static int kvm_handle_hva(struct kvm *kv + 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, ++ unsigned flags) + { + return kvm_handle_hva_range(kvm, start, end, 0, kvm_unmap_rmapp); + } +--- a/virt/kvm/arm/mmu.c ++++ b/virt/kvm/arm/mmu.c +@@ -2050,7 +2050,7 @@ static int kvm_unmap_hva_handler(struct + } + + int kvm_unmap_hva_range(struct kvm *kvm, +- unsigned long start, unsigned long end) ++ unsigned long start, unsigned long end, unsigned flags) + { + if (!kvm->arch.pgd) + return 0; +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -425,7 +425,8 @@ static int kvm_mmu_notifier_invalidate_r + * count is also read inside the mmu_lock critical section. + */ + kvm->mmu_notifier_count++; +- need_tlb_flush = kvm_unmap_hva_range(kvm, range->start, range->end); ++ need_tlb_flush = kvm_unmap_hva_range(kvm, range->start, range->end, ++ range->flags); + need_tlb_flush |= kvm->tlbs_dirty; + /* we've to flush the tlb before the pages can be freed */ + if (need_tlb_flush) diff --git a/queue-5.4/series b/queue-5.4/series index b7d0ec1ac4f..fd03a943924 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -105,3 +105,5 @@ epoll-keep-a-reference-on-files-added-to-the-check-list.patch do_epoll_ctl-clean-the-failure-exits-up-a-bit.patch mm-hugetlb-fix-calculation-of-adjust_range_if_pmd_sharing_possible.patch xen-don-t-reschedule-in-preemption-off-sections.patch +kvm-pass-mmu-notifier-range-flags-to-kvm_unmap_hva_range.patch +kvm-arm64-only-reschedule-if-mmu_notifier_range_blockable-is-not-set.patch