[PATCH] ARM: mm: align hugetlb mappings to the huge page size

Karl Mehltretter posted 1 patch 3 weeks, 4 days ago
arch/arm/mm/mmap.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
[PATCH] ARM: mm: align hugetlb mappings to the huge page size
Posted by Karl Mehltretter 3 weeks, 4 days ago
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

Commit 7bd3f1e1a9ae ("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.

Fixes: 7bd3f1e1a9ae ("mm: make hugetlb mappings go through mm_get_unmapped_area_vmflags")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Tested an LPAE multi_v7_defconfig kernel on QEMU virt with
-cpu max,aarch64=off and -cpu cortex-a15, using both the default and
legacy VA layouts. The LTP hugemmap01/04/05/06, hugefork01/02,
hugeshmat01, hugeshmget01, and hugefallocate01 tests gave 16 TPASS and
no failures on either CPU model.

Also tested on a Raspberry Pi 400. The unpatched kernel returned a
misaligned address and became unresponsive while touching the mapping.
The patched kernel returned an aligned address, touched the full mapping,
and unmapped it cleanly.

 arch/arm/mm/mmap.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 3dbb383c26d54..dbb3f07a77852 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -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);
 
base-commit: abdf623ddb75b24659018d3952d8f61937306ae5
-- 
2.53.0
Re: [PATCH] ARM: mm: align hugetlb mappings to the huge page size
Posted by Muchun Song 2 days, 3 hours ago

> On Sep 1, 2026, at 16:57, Karl Mehltretter <kmehltretter@gmail.com> wrote:
> 
> 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
> 
> Commit 7bd3f1e1a9ae ("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.
> 
> Fixes: 7bd3f1e1a9ae ("mm: make hugetlb mappings go through mm_get_unmapped_area_vmflags")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>

Besides 32-bit Arm, the same regression appears to affect MIPS and
SuperH: both support HugeTLB and provide custom arch_get_unmapped_area*()
implementations that only enforce cache-colouring alignment, not the
hstate’s huge-page alignment.

Acked-by: Muchun Song <muchun.song@linux.dev>

Thanks.
Re: [PATCH] ARM: mm: align hugetlb mappings to the huge page size
Posted by Karl Mehltretter 2 days, 6 hours ago
Hi,

A friendly ping on this patch. I came across the ARM32 alignment
issue again while testing Ackerley's HugeTLB subpool series [1]
on v7.3-rc3 in QEMU (Cortex-A15, LPAE).

I've now retested with this alignment fix applied on top of the
full series, keeping the kernel configuration and test image
unchanged. All six ordinary HugeTLB mapping and cleanup tests
pass with both one and four virtual CPUs, without the previously
observed panic.

Would someone have a chance to take a look? Happy to provide the
configuration and logs if useful.

[1] https://lore.kernel.org/r/20260916-hugetlb-subpool-always-track-used-v3-0-38aae9b5ccdd@google.com/

Thanks,
Karl