2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2011 Wind River Systems,
7 * written by Ralf Baechle <ralf@linux-mips.org>
9 #include <linux/errno.h>
11 #include <linux/mman.h>
12 #include <linux/module.h>
13 #include <linux/random.h>
14 #include <linux/sched.h>
16 unsigned long shm_align_mask
= PAGE_SIZE
- 1; /* Sane caches */
18 EXPORT_SYMBOL(shm_align_mask
);
20 #define COLOUR_ALIGN(addr,pgoff) \
21 ((((addr) + shm_align_mask) & ~shm_align_mask) + \
22 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
24 unsigned long arch_get_unmapped_area(struct file
*filp
, unsigned long addr
,
25 unsigned long len
, unsigned long pgoff
, unsigned long flags
)
27 struct vm_area_struct
* vmm
;
33 if (flags
& MAP_FIXED
) {
34 /* Even MAP_FIXED mappings must reside within TASK_SIZE. */
35 if (TASK_SIZE
- len
< addr
)
39 * We do not accept a shared mapping if it would violate
40 * cache aliasing constraints.
42 if ((flags
& MAP_SHARED
) &&
43 ((addr
- (pgoff
<< PAGE_SHIFT
)) & shm_align_mask
))
49 if (filp
|| (flags
& MAP_SHARED
))
53 addr
= COLOUR_ALIGN(addr
, pgoff
);
55 addr
= PAGE_ALIGN(addr
);
56 vmm
= find_vma(current
->mm
, addr
);
57 if (TASK_SIZE
- len
>= addr
&&
58 (!vmm
|| addr
+ len
<= vmm
->vm_start
))
61 addr
= current
->mm
->mmap_base
;
63 addr
= COLOUR_ALIGN(addr
, pgoff
);
65 addr
= PAGE_ALIGN(addr
);
67 for (vmm
= find_vma(current
->mm
, addr
); ; vmm
= vmm
->vm_next
) {
68 /* At this point: (!vmm || addr < vmm->vm_end). */
69 if (TASK_SIZE
- len
< addr
)
71 if (!vmm
|| addr
+ len
<= vmm
->vm_start
)
75 addr
= COLOUR_ALIGN(addr
, pgoff
);
79 void arch_pick_mmap_layout(struct mm_struct
*mm
)
81 unsigned long random_factor
= 0UL;
83 if (current
->flags
& PF_RANDOMIZE
) {
84 random_factor
= get_random_int();
85 random_factor
= random_factor
<< PAGE_SHIFT
;
86 if (TASK_IS_32BIT_ADDR
)
87 random_factor
&= 0xfffffful
;
89 random_factor
&= 0xffffffful
;
92 mm
->mmap_base
= TASK_UNMAPPED_BASE
+ random_factor
;
93 mm
->get_unmapped_area
= arch_get_unmapped_area
;
94 mm
->unmap_area
= arch_unmap_area
;
97 static inline unsigned long brk_rnd(void)
99 unsigned long rnd
= get_random_int();
101 rnd
= rnd
<< PAGE_SHIFT
;
102 /* 8MB for 32bit, 256MB for 64bit */
103 if (TASK_IS_32BIT_ADDR
)
104 rnd
= rnd
& 0x7ffffful
;
106 rnd
= rnd
& 0xffffffful
;
111 unsigned long arch_randomize_brk(struct mm_struct
*mm
)
113 unsigned long base
= mm
->brk
;
116 ret
= PAGE_ALIGN(base
+ brk_rnd());