Skip to content

Commit 0f09071

Browse files
willdeacongregkh
authored andcommitted
KVM: arm64: Only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is not set
commit b533137 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: <[email protected]> Fixes: 8b3405e ("kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd") Cc: Marc Zyngier <[email protected]> Cc: Suzuki K Poulose <[email protected]> Cc: James Morse <[email protected]> Signed-off-by: Will Deacon <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> [will: Backport to 4.19; use 'blockable' instead of non-existent MMU_NOTIFIER_RANGE_BLOCKABLE flag] Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a53dc16 commit 0f09071

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

virt/kvm/arm/mmu.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd,
323323
* destroying the VM), otherwise another faulting VCPU may come in and mess
324324
* with things behind our backs.
325325
*/
326-
static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
326+
static void __unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size,
327+
bool may_block)
327328
{
328329
pgd_t *pgd;
329330
phys_addr_t addr = start, end = start + size;
@@ -348,11 +349,16 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
348349
* If the range is too large, release the kvm->mmu_lock
349350
* to prevent starvation and lockup detector warnings.
350351
*/
351-
if (next != end)
352+
if (may_block && next != end)
352353
cond_resched_lock(&kvm->mmu_lock);
353354
} while (pgd++, addr = next, addr != end);
354355
}
355356

357+
static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
358+
{
359+
__unmap_stage2_range(kvm, start, size, true);
360+
}
361+
356362
static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
357363
phys_addr_t addr, phys_addr_t end)
358364
{
@@ -1820,7 +1826,9 @@ static int handle_hva_to_gpa(struct kvm *kvm,
18201826

18211827
static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data)
18221828
{
1823-
unmap_stage2_range(kvm, gpa, size);
1829+
bool may_block = *(bool *)data;
1830+
1831+
__unmap_stage2_range(kvm, gpa, size, may_block);
18241832
return 0;
18251833
}
18261834

@@ -1831,7 +1839,7 @@ int kvm_unmap_hva_range(struct kvm *kvm,
18311839
return 0;
18321840

18331841
trace_kvm_unmap_hva_range(start, end);
1834-
handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL);
1842+
handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, &blockable);
18351843
return 0;
18361844
}
18371845

0 commit comments

Comments
 (0)