Skip to content

Commit 4896269

Browse files
author
Fox Snowpatch
committed
1 parent ddf9a4c commit 4896269

File tree

23 files changed

+120
-0
lines changed

23 files changed

+120
-0
lines changed

arch/alpha/kernel/osf_sys.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,8 @@ arch_get_unmapped_area_1(unsigned long addr, unsigned long len,
12231223
info.length = len;
12241224
info.low_limit = addr;
12251225
info.high_limit = limit;
1226+
info.hint = addr;
1227+
info.mmap_flags = flags;
12261228
return vm_unmapped_area(&info);
12271229
}
12281230

arch/arc/mm/mmap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
2929
struct vm_area_struct *vma;
3030
struct vm_unmapped_area_info info = {};
3131

32+
info.hint = addr;
33+
info.mmap_flags = flags;
34+
3235
/*
3336
* We enforce the MAP_FIXED case.
3437
*/

arch/arm/mm/mmap.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
3636
int aliasing = cache_is_vipt_aliasing();
3737
struct vm_unmapped_area_info info = {};
3838

39+
info.hint = addr;
40+
info.mmap_flags = flags;
41+
3942
/*
4043
* We only need to do colour alignment if either the I or D
4144
* caches alias.
@@ -56,6 +59,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
5659
if (len > TASK_SIZE)
5760
return -ENOMEM;
5861

62+
5963
if (addr) {
6064
if (do_align)
6165
addr = COLOUR_ALIGN(addr, pgoff);
@@ -88,6 +92,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
8892
int aliasing = cache_is_vipt_aliasing();
8993
struct vm_unmapped_area_info info = {};
9094

95+
info.hint = addr;
96+
info.mmap_flags = flags;
97+
9198
/*
9299
* We only need to do colour alignment if either the I or D
93100
* caches alias.

arch/csky/abiv1/mmap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
3535
.align_offset = pgoff << PAGE_SHIFT
3636
};
3737

38+
info.hint = addr;
39+
info.mmap_flags = flags;
40+
3841
/*
3942
* We only need to do colour alignment if either the I or D
4043
* caches alias.

arch/loongarch/mm/mmap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
2727
int do_color_align;
2828
struct vm_unmapped_area_info info = {};
2929

30+
info.hint = addr;
31+
info.mmap_flags = flags;
32+
3033
if (unlikely(len > TASK_SIZE))
3134
return -ENOMEM;
3235

arch/mips/mm/mmap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
3636
int do_color_align;
3737
struct vm_unmapped_area_info info = {};
3838

39+
info.hint = addr;
40+
info.mmap_flags = flags;
41+
3942
if (unlikely(len > TASK_SIZE))
4043
return -ENOMEM;
4144

arch/parisc/kernel/sys_parisc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
108108
.length = len
109109
};
110110

111+
info.hint = addr;
112+
info.mmap_flags = flags;
113+
111114
if (unlikely(len > TASK_SIZE))
112115
return -ENOMEM;
113116

arch/powerpc/mm/book3s64/slice.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
286286
.length = len,
287287
.align_mask = PAGE_MASK & ((1ul << pshift) - 1),
288288
};
289+
290+
info.hint = addr;
291+
info.mmap_flags = flags;
292+
289293
/*
290294
* Check till the allow max value for this mmap request
291295
*/
@@ -331,6 +335,9 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
331335
};
332336
unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr);
333337

338+
info.hint = addr;
339+
info.mmap_flags = flags;
340+
334341
/*
335342
* If we are trying to allocate above DEFAULT_MAP_WINDOW
336343
* Add the different to the mmap_base.

arch/s390/mm/hugetlbpage.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
254254
info.low_limit = current->mm->mmap_base;
255255
info.high_limit = TASK_SIZE;
256256
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
257+
info.hint = addr;
258+
info.mmap_flags = flags;
257259
return vm_unmapped_area(&info);
258260
}
259261

@@ -270,6 +272,8 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
270272
info.low_limit = PAGE_SIZE;
271273
info.high_limit = current->mm->mmap_base;
272274
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
275+
info.hint = addr;
276+
info.mmap_flags = flags;
273277
addr = vm_unmapped_area(&info);
274278

275279
/*

arch/s390/mm/mmap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
8888
struct vm_area_struct *vma;
8989
struct vm_unmapped_area_info info = {};
9090

91+
info.hint = addr;
92+
info.mmap_flags = flags;
93+
9194
if (len > TASK_SIZE - mmap_min_addr)
9295
return -ENOMEM;
9396

@@ -123,6 +126,9 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long ad
123126
struct mm_struct *mm = current->mm;
124127
struct vm_unmapped_area_info info = {};
125128

129+
info.hint = addr;
130+
info.mmap_flags = flags;
131+
126132
/* requested length too big for entire address space */
127133
if (len > TASK_SIZE - mmap_min_addr)
128134
return -ENOMEM;

arch/sh/mm/mmap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
5959
int do_colour_align;
6060
struct vm_unmapped_area_info info = {};
6161

62+
info.hint = addr;
63+
info.mmap_flags = flags;
64+
6265
if (flags & MAP_FIXED) {
6366
/* We do not accept a shared mapping if it would violate
6467
* cache aliasing constraints.
@@ -107,6 +110,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
107110
int do_colour_align;
108111
struct vm_unmapped_area_info info = {};
109112

113+
info.hint = addr;
114+
info.mmap_flags = flags;
115+
110116
if (flags & MAP_FIXED) {
111117
/* We do not accept a shared mapping if it would violate
112118
* cache aliasing constraints.

arch/sparc/kernel/sys_sparc_32.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
4343
{
4444
struct vm_unmapped_area_info info = {};
4545

46+
info.hint = addr;
47+
info.mmap_flags = flags;
48+
4649
if (flags & MAP_FIXED) {
4750
/* We do not accept a shared mapping if it would violate
4851
* cache aliasing constraints.

arch/sparc/kernel/sys_sparc_64.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
9595
int do_color_align;
9696
struct vm_unmapped_area_info info = {};
9797

98+
info.hint = addr;
99+
info.mmap_flags = flags;
100+
98101
if (flags & MAP_FIXED) {
99102
/* We do not accept a shared mapping if it would violate
100103
* cache aliasing constraints.
@@ -155,6 +158,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
155158
int do_color_align;
156159
struct vm_unmapped_area_info info = {};
157160

161+
info.hint = addr;
162+
info.mmap_flags = flags;
163+
158164
/* This should only ever run for 32-bit processes. */
159165
BUG_ON(!test_thread_flag(TIF_32BIT));
160166

arch/sparc/mm/hugetlbpage.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
4040
info.low_limit = TASK_UNMAPPED_BASE;
4141
info.high_limit = min(task_size, VA_EXCLUDE_START);
4242
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
43+
info.hint = addr;
44+
info.mmap_flags = flags;
4345
addr = vm_unmapped_area(&info);
4446

4547
if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
@@ -71,6 +73,8 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
7173
info.low_limit = PAGE_SIZE;
7274
info.high_limit = mm->mmap_base;
7375
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
76+
info.hint = addr;
77+
info.mmap_flags = flags;
7478
addr = vm_unmapped_area(&info);
7579

7680
/*

arch/x86/kernel/sys_x86_64.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ arch_get_unmapped_area_vmflags(struct file *filp, unsigned long addr, unsigned l
129129
struct vm_unmapped_area_info info = {};
130130
unsigned long begin, end;
131131

132+
info.hint = addr;
133+
info.mmap_flags = flags;
134+
132135
if (flags & MAP_FIXED)
133136
return addr;
134137

@@ -167,6 +170,9 @@ arch_get_unmapped_area_topdown_vmflags(struct file *filp, unsigned long addr0,
167170
unsigned long addr = addr0;
168171
struct vm_unmapped_area_info info = {};
169172

173+
info.hint = addr;
174+
info.mmap_flags = flags;
175+
170176
/* requested length too big for entire address space */
171177
if (len > TASK_SIZE)
172178
return -ENOMEM;

arch/x86/mm/hugetlbpage.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
2929

3030
info.length = len;
3131
info.low_limit = get_mmap_base(1);
32+
info.hint = addr;
33+
info.mmap_flags = flags;
3234

3335
/*
3436
* If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area
@@ -52,6 +54,8 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
5254
info.length = len;
5355
info.low_limit = PAGE_SIZE;
5456
info.high_limit = get_mmap_base(0);
57+
info.hint = addr;
58+
info.mmap_flags = flags;
5559

5660
/*
5761
* If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area

fs/hugetlbfs/inode.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
182182
info.low_limit = current->mm->mmap_base;
183183
info.high_limit = arch_get_mmap_end(addr, len, flags);
184184
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
185+
info.hint = addr;
186+
info.mmap_flags = flags;
185187
return vm_unmapped_area(&info);
186188
}
187189

@@ -197,6 +199,8 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
197199
info.low_limit = PAGE_SIZE;
198200
info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
199201
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
202+
info.hint = addr;
203+
info.mmap_flags = flags;
200204
addr = vm_unmapped_area(&info);
201205

202206
/*

include/linux/mm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3434,6 +3434,8 @@ struct vm_unmapped_area_info {
34343434
unsigned long align_mask;
34353435
unsigned long align_offset;
34363436
unsigned long start_gap;
3437+
unsigned long hint;
3438+
unsigned long mmap_flags;
34373439
};
34383440

34393441
extern unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info);

include/uapi/asm-generic/mman-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
3434
* uninitialized */
35+
#define MAP_BELOW_HINT 0x8000000 /* give out address that is below (inclusive) hint address */
3536

3637
/*
3738
* Flags for mlock

mm/mmap.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,9 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
17661766
{
17671767
unsigned long addr;
17681768

1769+
if (info->hint != 0 && info->mmap_flags & MAP_BELOW_HINT)
1770+
info->high_limit = MIN(info->high_limit, info->hint + info->length);
1771+
17691772
if (info->flags & VM_UNMAPPED_AREA_TOPDOWN)
17701773
addr = unmapped_area_topdown(info);
17711774
else
@@ -1796,6 +1799,9 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
17961799
struct vm_unmapped_area_info info = {};
17971800
const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
17981801

1802+
info.hint = addr;
1803+
info.mmap_flags = flags;
1804+
17991805
if (len > mmap_end - mmap_min_addr)
18001806
return -ENOMEM;
18011807

@@ -1841,6 +1847,9 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
18411847
struct vm_unmapped_area_info info = {};
18421848
const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
18431849

1850+
info.hint = addr;
1851+
info.mmap_flags = flags;
1852+
18441853
/* requested length too big for entire address space */
18451854
if (len > mmap_end - mmap_min_addr)
18461855
return -ENOMEM;

tools/include/uapi/asm-generic/mman-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
3434
* uninitialized */
35+
#define MAP_BELOW_HINT 0x8000000 /* give out address that is below (inclusive) hint address */
3536

3637
/*
3738
* Flags for mlock

tools/testing/selftests/mm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ TEST_GEN_FILES += hugepage-shm
5050
TEST_GEN_FILES += hugepage-vmemmap
5151
TEST_GEN_FILES += khugepaged
5252
TEST_GEN_FILES += madv_populate
53+
TEST_GEN_FILES += map_below_hint
5354
TEST_GEN_FILES += map_fixed_noreplace
5455
TEST_GEN_FILES += map_hugetlb
5556
TEST_GEN_FILES += map_populate
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Test the MAP_BELOW_HINT mmap flag.
4+
*/
5+
#include <sys/mman.h>
6+
#include <errno.h>
7+
#include "../kselftest.h"
8+
9+
#define ADDR (1 << 20)
10+
#define LENGTH (ADDR / 10000)
11+
12+
#define MAP_BELOW_HINT 0x8000000 /* Not defined in all libc */
13+
14+
/*
15+
* Map memory with MAP_BELOW_HINT until no memory left. Ensure that all returned
16+
* addresses are below the hint.
17+
*/
18+
int main(int argc, char **argv)
19+
{
20+
void *addr;
21+
22+
do {
23+
addr = mmap((void *)ADDR, LENGTH, PROT_READ | PROT_WRITE,
24+
MAP_PRIVATE | MAP_ANONYMOUS | MAP_BELOW_HINT, -1, 0);
25+
} while (addr != MAP_FAILED && (unsigned long)addr <= ADDR);
26+
27+
if (errno == ENOMEM)
28+
ksft_test_result_pass("MAP_BELOW_HINT works\n");
29+
else
30+
ksft_test_result_fail("mmap returned address above hint with MAP_BELOW_HINT with error: %s\n",
31+
strerror(errno));
32+
}

0 commit comments

Comments
 (0)