mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ARM: 9524/1: mm: align hugetlb mappings to the huge page size
mmap(MAP_HUGETLB) on 32-bit Arm can return an address which is not aligned to the huge page size. In a QEMU virt guest, unmapping the VMA then hits the alignment check in __unmap_hugepage_range(): kernel BUG at mm/hugetlb.c:5213! Internal error: Oops - BUG: 0 [#1] SMP ARM PC is at __unmap_hugepage_range+0x540/0x584 LR is at __zap_vma_range+0x13a0/0x1410 Commit7bd3f1e1a9("mm: make hugetlb mappings go through mm_get_unmapped_area_vmflags") made hugetlb mappings use the architecture's arch_get_unmapped_area(). The generic implementations handle hugetlb alignment, but the Arm implementations only account for the optional SHMLBA cache-colouring constraint. A 4 KiB-page kernel can therefore align the mapping to 4 KiB or 16 KiB instead of the required 2 MiB. Set the alignment mask from the file's hstate for hugetlb mappings in both Arm implementations. Huge-page alignment also satisfies the SHMLBA constraint. Assisted-by: LLM Fixes:7bd3f1e1a9("mm: make hugetlb mappings go through mm_get_unmapped_area_vmflags") Cc: stable@vger.kernel.org Acked-by: Muchun Song <muchun.song@linux.dev> Link: https://lore.kernel.org/r/20260901085740.66283-1-kmehltretter@gmail.com/ Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
2d4234f999
commit
1eb87d8f77
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <asm/cachetype.h>
|
||||
|
||||
#define COLOUR_ALIGN(addr,pgoff) \
|
||||
|
|
@ -72,7 +73,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||
if (filp && is_file_hugepages(filp))
|
||||
info.align_mask = huge_page_mask_align(filp);
|
||||
else
|
||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||
info.align_offset = pgoff << PAGE_SHIFT;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
|
@ -123,7 +127,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|||
info.length = len;
|
||||
info.low_limit = FIRST_USER_ADDRESS;
|
||||
info.high_limit = mm->mmap_base;
|
||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||
if (filp && is_file_hugepages(filp))
|
||||
info.align_mask = huge_page_mask_align(filp);
|
||||
else
|
||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||
info.align_offset = pgoff << PAGE_SHIFT;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user