Skip to content

Commit ba925fa

Browse files
gerald-schaeferhcahca
authored andcommitted
s390/gmap: improve THP splitting
During s390_enable_sie(), we need to take care of splitting all qemu user process THP mappings. This is currently done with follow_page(FOLL_SPLIT), by simply iterating over all vma ranges, with PAGE_SIZE increment. This logic is sub-optimal and can result in a lot of unnecessary overhead, especially when using qemu and ASAN with large shadow map. Ilya reported significant system slow-down with one CPU busy for a long time and overall unresponsiveness. Fix this by using walk_page_vma() and directly calling split_huge_pmd() only for present pmds, which greatly reduces overhead. Cc: <[email protected]> # v5.4+ Reported-by: Ilya Leoshkevich <[email protected]> Tested-by: Ilya Leoshkevich <[email protected]> Acked-by: Christian Borntraeger <[email protected]> Signed-off-by: Gerald Schaefer <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent f0cbd3b commit ba925fa

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

arch/s390/mm/gmap.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,23 +2485,36 @@ void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long bitmap[4],
24852485
}
24862486
EXPORT_SYMBOL_GPL(gmap_sync_dirty_log_pmd);
24872487

2488+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
2489+
static int thp_split_walk_pmd_entry(pmd_t *pmd, unsigned long addr,
2490+
unsigned long end, struct mm_walk *walk)
2491+
{
2492+
struct vm_area_struct *vma = walk->vma;
2493+
2494+
split_huge_pmd(vma, pmd, addr);
2495+
return 0;
2496+
}
2497+
2498+
static const struct mm_walk_ops thp_split_walk_ops = {
2499+
.pmd_entry = thp_split_walk_pmd_entry,
2500+
};
2501+
24882502
static inline void thp_split_mm(struct mm_struct *mm)
24892503
{
2490-
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
24912504
struct vm_area_struct *vma;
2492-
unsigned long addr;
24932505

24942506
for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
2495-
for (addr = vma->vm_start;
2496-
addr < vma->vm_end;
2497-
addr += PAGE_SIZE)
2498-
follow_page(vma, addr, FOLL_SPLIT);
24992507
vma->vm_flags &= ~VM_HUGEPAGE;
25002508
vma->vm_flags |= VM_NOHUGEPAGE;
2509+
walk_page_vma(vma, &thp_split_walk_ops, NULL);
25012510
}
25022511
mm->def_flags |= VM_NOHUGEPAGE;
2503-
#endif
25042512
}
2513+
#else
2514+
static inline void thp_split_mm(struct mm_struct *mm)
2515+
{
2516+
}
2517+
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
25052518

25062519
/*
25072520
* Remove all empty zero pages from the mapping for lazy refaulting

0 commit comments

Comments
 (0)