Skip to content

Commit 5994bc9

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: Limit stage2_apply_range() batch size to largest block
Presently stage2_apply_range() works on a batch of memory addressed by a stage 2 root table entry for the VM. Depending on the IPA limit of the VM and PAGE_SIZE of the host, this could address a massive range of memory. Some examples: 4 level, 4K paging -> 512 GB batch size 3 level, 64K paging -> 4TB batch size Unsurprisingly, working on such a large range of memory can lead to soft lockups. When running dirty_log_perf_test: ./dirty_log_perf_test -m -2 -s anonymous_thp -b 4G -v 48 watchdog: BUG: soft lockup - CPU#0 stuck for 45s! [dirty_log_perf_:16703] Modules linked in: vfat fat cdc_ether usbnet mii xhci_pci xhci_hcd sha3_generic gq(O) CPU: 0 PID: 16703 Comm: dirty_log_perf_ Tainted: G O 6.0.0-smp-DEV #1 pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : dcache_clean_inval_poc+0x24/0x38 lr : clean_dcache_guest_page+0x28/0x4c sp : ffff800021763990 pmr_save: 000000e0 x29: ffff800021763990 x28: 0000000000000005 x27: 0000000000000de0 x26: 0000000000000001 x25: 00400830b13bc77f x24: ffffad4f91ead9c0 x23: 0000000000000000 x22: ffff8000082ad9c8 x21: 0000fffafa7bc000 x20: ffffad4f9066ce50 x19: 0000000000000003 x18: ffffad4f92402000 x17: 000000000000011b x16: 000000000000011b x15: 0000000000000124 x14: ffff07ff8301d280 x13: 0000000000000000 x12: 00000000ffffffff x11: 0000000000010001 x10: fffffc0000000000 x9 : ffffad4f9069e580 x8 : 000000000000000c x7 : 0000000000000000 x6 : 000000000000003f x5 : ffff07ffa2076980 x4 : 0000000000000001 x3 : 000000000000003f x2 : 0000000000000040 x1 : ffff0830313bd000 x0 : ffff0830313bcc40 Call trace: dcache_clean_inval_poc+0x24/0x38 stage2_unmap_walker+0x138/0x1ec __kvm_pgtable_walk+0x130/0x1d4 __kvm_pgtable_walk+0x170/0x1d4 __kvm_pgtable_walk+0x170/0x1d4 __kvm_pgtable_walk+0x170/0x1d4 kvm_pgtable_stage2_unmap+0xc4/0xf8 kvm_arch_flush_shadow_memslot+0xa4/0x10c kvm_set_memslot+0xb8/0x454 __kvm_set_memory_region+0x194/0x244 kvm_vm_ioctl_set_memory_region+0x58/0x7c kvm_vm_ioctl+0x49c/0x560 __arm64_sys_ioctl+0x9c/0xd4 invoke_syscall+0x4c/0x124 el0_svc_common+0xc8/0x194 do_el0_svc+0x38/0xc0 el0_svc+0x2c/0xa4 el0t_64_sync_handler+0x84/0xf0 el0t_64_sync+0x1a0/0x1a4 Use the largest supported block mapping for the configured page size as the batch granularity. In so doing the walker is guaranteed to visit a leaf only once. Signed-off-by: Oliver Upton <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3b5c082 commit 5994bc9

File tree

2 files changed

+8
-21
lines changed

2 files changed

+8
-21
lines changed

arch/arm64/include/asm/stage2_pgtable.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,6 @@
1010

1111
#include <linux/pgtable.h>
1212

13-
/*
14-
* PGDIR_SHIFT determines the size a top-level page table entry can map
15-
* and depends on the number of levels in the page table. Compute the
16-
* PGDIR_SHIFT for a given number of levels.
17-
*/
18-
#define pt_levels_pgdir_shift(lvls) ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (lvls))
19-
2013
/*
2114
* The hardware supports concatenation of up to 16 tables at stage2 entry
2215
* level and we use the feature whenever possible, which means we resolve 4
@@ -30,24 +23,11 @@
3023
#define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4)
3124
#define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr)
3225

33-
/* stage2_pgdir_shift() is the size mapped by top-level stage2 entry for the VM */
34-
#define stage2_pgdir_shift(kvm) pt_levels_pgdir_shift(kvm_stage2_levels(kvm))
35-
#define stage2_pgdir_size(kvm) (1ULL << stage2_pgdir_shift(kvm))
36-
#define stage2_pgdir_mask(kvm) ~(stage2_pgdir_size(kvm) - 1)
37-
3826
/*
3927
* kvm_mmmu_cache_min_pages() is the number of pages required to install
4028
* a stage-2 translation. We pre-allocate the entry level page table at
4129
* the VM creation.
4230
*/
4331
#define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1)
4432

45-
static inline phys_addr_t
46-
stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
47-
{
48-
phys_addr_t boundary = (addr + stage2_pgdir_size(kvm)) & stage2_pgdir_mask(kvm);
49-
50-
return (boundary - 1 < end - 1) ? boundary : end;
51-
}
52-
5333
#endif /* __ARM64_S2_PGTABLE_H_ */

arch/arm64/kvm/mmu.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ static phys_addr_t hyp_idmap_vector;
3131

3232
static unsigned long io_map_base;
3333

34+
static phys_addr_t stage2_range_addr_end(phys_addr_t addr, phys_addr_t end)
35+
{
36+
phys_addr_t size = kvm_granule_size(KVM_PGTABLE_MIN_BLOCK_LEVEL);
37+
phys_addr_t boundary = ALIGN_DOWN(addr + size, size);
38+
39+
return (boundary - 1 < end - 1) ? boundary : end;
40+
}
3441

3542
/*
3643
* Release kvm_mmu_lock periodically if the memory region is large. Otherwise,
@@ -52,7 +59,7 @@ static int stage2_apply_range(struct kvm *kvm, phys_addr_t addr,
5259
if (!pgt)
5360
return -EINVAL;
5461

55-
next = stage2_pgd_addr_end(kvm, addr, end);
62+
next = stage2_range_addr_end(addr, end);
5663
ret = fn(pgt, addr, next - addr);
5764
if (ret)
5865
break;

0 commit comments

Comments
 (0)