Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arch/x86: teach arch_get_unmapped_area_vmflags to handle hugetlb mappings

We want to stop special casing hugetlb mappings and make them go through
generic channels, so teach arch_get_unmapped_area_{topdown_}vmflags to
handle those.

x86 specific hugetlb function does not set either info.start_gap or
info.align_offset so the same here for compatibility.

Link: https://lkml.kernel.org/r/20241007075037.267650-4-osalvador@suse.de
Signed-off-by: Oscar Salvador <osalvador@suse.de>
Cc: David Hildenbrand <david@redhat.com>
Cc: Donet Tom <donettom@linux.ibm.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Peter Xu <peterx@redhat.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Oscar Salvador and committed by
Andrew Morton
1317a5e7 7d7dba7f

+16 -8
+16 -8
arch/x86/kernel/sys_x86_64.c
··· 18 18 #include <linux/random.h> 19 19 #include <linux/uaccess.h> 20 20 #include <linux/elf.h> 21 + #include <linux/hugetlb.h> 21 22 22 23 #include <asm/elf.h> 23 24 #include <asm/ia32.h> ··· 26 25 /* 27 26 * Align a virtual address to avoid aliasing in the I$ on AMD F15h. 28 27 */ 29 - static unsigned long get_align_mask(void) 28 + static unsigned long get_align_mask(struct file *filp) 30 29 { 30 + if (filp && is_file_hugepages(filp)) 31 + return huge_page_mask_align(filp); 31 32 /* handle 32- and 64-bit case with a single conditional */ 32 33 if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32()))) 33 34 return 0; ··· 52 49 */ 53 50 static unsigned long get_align_bits(void) 54 51 { 55 - return va_align.bits & get_align_mask(); 52 + return va_align.bits & get_align_mask(NULL); 56 53 } 57 54 58 55 static int __init control_va_addr_alignment(char *str) ··· 151 148 info.length = len; 152 149 info.low_limit = begin; 153 150 info.high_limit = end; 154 - info.align_offset = pgoff << PAGE_SHIFT; 155 - info.start_gap = stack_guard_placement(vm_flags); 151 + if (!(filp && is_file_hugepages(filp))) { 152 + info.align_offset = pgoff << PAGE_SHIFT; 153 + info.start_gap = stack_guard_placement(vm_flags); 154 + } 156 155 if (filp) { 157 - info.align_mask = get_align_mask(); 156 + info.align_mask = get_align_mask(filp); 158 157 info.align_offset += get_align_bits(); 159 158 } 159 + 160 160 return vm_unmapped_area(&info); 161 161 } 162 162 ··· 205 199 info.low_limit = PAGE_SIZE; 206 200 207 201 info.high_limit = get_mmap_base(0); 208 - info.start_gap = stack_guard_placement(vm_flags); 202 + if (!(filp && is_file_hugepages(filp))) { 203 + info.start_gap = stack_guard_placement(vm_flags); 204 + info.align_offset = pgoff << PAGE_SHIFT; 205 + } 209 206 210 207 /* 211 208 * If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area ··· 220 211 if (addr > DEFAULT_MAP_WINDOW && !in_32bit_syscall()) 221 212 info.high_limit += TASK_SIZE_MAX - DEFAULT_MAP_WINDOW; 222 213 223 - info.align_offset = pgoff << PAGE_SHIFT; 224 214 if (filp) { 225 - info.align_mask = get_align_mask(); 215 + info.align_mask = get_align_mask(filp); 226 216 info.align_offset += get_align_bits(); 227 217 } 228 218 addr = vm_unmapped_area(&info);