]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
arch/sparc: teach arch_get_unmapped_area{_topdown} to handle hugetlb mappings
authorOscar Salvador <osalvador@suse.de>
Mon, 7 Oct 2024 07:50:32 +0000 (09:50 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 1 Nov 2024 04:28:59 +0000 (21:28 -0700)
We want to stop special casing hugetlb mappings and make them go through
generic channels, so teach arch_get_unmapped_area{_topdown} to handle
those.

sparc specific hugetlb function does not set info.align_offset, and does
not care about adjusting the align_mask for MAP_SHARED cases, so the same
here for compatibility.

Link: https://lkml.kernel.org/r/20241007075037.267650-5-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>
arch/sparc/kernel/sys_sparc_32.c
arch/sparc/kernel/sys_sparc_64.c

index 80822f922e767158359ad8a434932d10de673c3c..fb31bc0c5b48825d203c2b6faa4981f4c002e2e7 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/utsname.h>
 #include <linux/smp.h>
 #include <linux/ipc.h>
+#include <linux/hugetlb.h>
 
 #include <linux/uaccess.h>
 #include <asm/unistd.h>
@@ -42,12 +43,16 @@ SYSCALL_DEFINE0(getpagesize)
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
 {
        struct vm_unmapped_area_info info = {};
+       bool file_hugepage = false;
+
+       if (filp && is_file_hugepages(filp))
+               file_hugepage = true;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) &&
+               if (!file_hugepage && (flags & MAP_SHARED) &&
                    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
                        return -EINVAL;
                return addr;
@@ -62,9 +67,13 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        info.length = len;
        info.low_limit = addr;
        info.high_limit = TASK_SIZE;
-       info.align_mask = (flags & MAP_SHARED) ?
-               (PAGE_MASK & (SHMLBA - 1)) : 0;
-       info.align_offset = pgoff << PAGE_SHIFT;
+       if (!file_hugepage) {
+               info.align_mask = (flags & MAP_SHARED) ?
+                       (PAGE_MASK & (SHMLBA - 1)) : 0;
+               info.align_offset = pgoff << PAGE_SHIFT;
+       } else {
+               info.align_mask = huge_page_mask_align(filp);
+       }
        return vm_unmapped_area(&info);
 }
 
index acade309dc2fbdac75afd68073e8e330be6a2e50..c5a284df7b417ead44094a499f61362242407e70 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/context_tracking.h>
 #include <linux/timex.h>
 #include <linux/uaccess.h>
+#include <linux/hugetlb.h>
 
 #include <asm/utrap.h>
 #include <asm/unistd.h>
@@ -87,6 +88,16 @@ static inline unsigned long COLOR_ALIGN(unsigned long addr,
        return base + off;
 }
 
+static unsigned long get_align_mask(struct file *filp, unsigned long flags)
+{
+       if (filp && is_file_hugepages(filp))
+               return huge_page_mask_align(filp);
+       if (filp || (flags & MAP_SHARED))
+               return PAGE_MASK & (SHMLBA - 1);
+
+       return 0;
+}
+
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
 {
        struct mm_struct *mm = current->mm;
@@ -94,12 +105,16 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        unsigned long task_size = TASK_SIZE;
        int do_color_align;
        struct vm_unmapped_area_info info = {};
+       bool file_hugepage = false;
+
+       if (filp && is_file_hugepages(filp))
+               file_hugepage = true;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) &&
+               if (!file_hugepage && (flags & MAP_SHARED) &&
                    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
                        return -EINVAL;
                return addr;
@@ -111,7 +126,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
                return -ENOMEM;
 
        do_color_align = 0;
-       if (filp || (flags & MAP_SHARED))
+       if ((filp || (flags & MAP_SHARED)) && !file_hugepage)
                do_color_align = 1;
 
        if (addr) {
@@ -129,8 +144,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        info.length = len;
        info.low_limit = TASK_UNMAPPED_BASE;
        info.high_limit = min(task_size, VA_EXCLUDE_START);
-       info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
-       info.align_offset = pgoff << PAGE_SHIFT;
+       info.align_mask = get_align_mask(filp, flags);
+       if (!file_hugepage)
+               info.align_offset = pgoff << PAGE_SHIFT;
        addr = vm_unmapped_area(&info);
 
        if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
@@ -154,15 +170,19 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        unsigned long addr = addr0;
        int do_color_align;
        struct vm_unmapped_area_info info = {};
+       bool file_hugepage = false;
 
        /* This should only ever run for 32-bit processes.  */
        BUG_ON(!test_thread_flag(TIF_32BIT));
 
+       if (filp && is_file_hugepages(filp))
+               file_hugepage = true;
+
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) &&
+               if (!file_hugepage && (flags & MAP_SHARED) &&
                    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
                        return -EINVAL;
                return addr;
@@ -172,7 +192,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                return -ENOMEM;
 
        do_color_align = 0;
-       if (filp || (flags & MAP_SHARED))
+       if ((filp || (flags & MAP_SHARED)) && !file_hugepage)
                do_color_align = 1;
 
        /* requesting a specific address */
@@ -192,8 +212,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        info.length = len;
        info.low_limit = PAGE_SIZE;
        info.high_limit = mm->mmap_base;
-       info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
-       info.align_offset = pgoff << PAGE_SHIFT;
+       info.align_mask = get_align_mask(filp, flags);
+       if (!file_hugepage)
+               info.align_offset = pgoff << PAGE_SHIFT;
        addr = vm_unmapped_area(&info);
 
        /*