Branch data Line data Source code
1 : : /*
2 : : * linux/arch/arm/mm/mmap.c
3 : : */
4 : : #include <linux/fs.h>
5 : : #include <linux/mm.h>
6 : : #include <linux/mman.h>
7 : : #include <linux/shm.h>
8 : : #include <linux/sched.h>
9 : : #include <linux/io.h>
10 : : #include <linux/personality.h>
11 : : #include <linux/random.h>
12 : : #include <asm/cachetype.h>
13 : :
14 : : #define COLOUR_ALIGN(addr,pgoff) \
15 : : ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
16 : : (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
17 : :
18 : : /* gap between mmap and stack */
19 : : #define MIN_GAP (128*1024*1024UL)
20 : : #define MAX_GAP ((TASK_SIZE)/6*5)
21 : :
22 : : static int mmap_is_legacy(void)
23 : : {
24 [ + + ]: 27240 : if (current->personality & ADDR_COMPAT_LAYOUT)
25 : : return 1;
26 : :
27 [ + + ]: 27234 : if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
28 : : return 1;
29 : :
30 : 26502 : return sysctl_legacy_va_layout;
31 : : }
32 : :
33 : : static unsigned long mmap_base(unsigned long rnd)
34 : : {
35 : : unsigned long gap = rlimit(RLIMIT_STACK);
36 : :
37 [ - + ]: 26509 : if (gap < MIN_GAP)
38 : : gap = MIN_GAP;
39 [ # # ]: 0 : else if (gap > MAX_GAP)
40 : : gap = MAX_GAP;
41 : :
42 : 26509 : return PAGE_ALIGN(TASK_SIZE - gap - rnd);
43 : : }
44 : :
45 : : /*
46 : : * We need to ensure that shared mappings are correctly aligned to
47 : : * avoid aliasing issues with VIPT caches. We need to ensure that
48 : : * a specific page of an object is always mapped at a multiple of
49 : : * SHMLBA bytes.
50 : : *
51 : : * We unconditionally provide this function for all cases, however
52 : : * in the VIVT case, we optimise out the alignment rules.
53 : : */
54 : : unsigned long
55 : 0 : arch_get_unmapped_area(struct file *filp, unsigned long addr,
56 : : unsigned long len, unsigned long pgoff, unsigned long flags)
57 : : {
58 : 16980 : struct mm_struct *mm = current->mm;
59 : : struct vm_area_struct *vma;
60 : : int do_align = 0;
61 : : int aliasing = cache_is_vipt_aliasing();
62 : : struct vm_unmapped_area_info info;
63 : :
64 : : /*
65 : : * We only need to do colour alignment if either the I or D
66 : : * caches alias.
67 : : */
68 : : if (aliasing)
69 : : do_align = filp || (flags & MAP_SHARED);
70 : :
71 : : /*
72 : : * We enforce the MAP_FIXED case.
73 : : */
74 [ + + ]: 16980 : if (flags & MAP_FIXED) {
75 : : if (aliasing && flags & MAP_SHARED &&
76 : : (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
77 : : return -EINVAL;
78 : : return addr;
79 : : }
80 : :
81 [ + ]: 11266 : if (len > TASK_SIZE)
82 : : return -ENOMEM;
83 : :
84 [ - + ]: 11267 : if (addr) {
85 : : if (do_align)
86 : : addr = COLOUR_ALIGN(addr, pgoff);
87 : : else
88 : 0 : addr = PAGE_ALIGN(addr);
89 : :
90 : 0 : vma = find_vma(mm, addr);
91 [ # # ][ # # ]: 0 : if (TASK_SIZE - len >= addr &&
92 [ # # ]: 0 : (!vma || addr + len <= vma->vm_start))
93 : : return addr;
94 : : }
95 : :
96 : 11267 : info.flags = 0;
97 : 11267 : info.length = len;
98 : 11267 : info.low_limit = mm->mmap_base;
99 : 11267 : info.high_limit = TASK_SIZE;
100 : 11267 : info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
101 : 11267 : info.align_offset = pgoff << PAGE_SHIFT;
102 : 11267 : return vm_unmapped_area(&info);
103 : : }
104 : :
105 : : unsigned long
106 : 0 : arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
107 : : const unsigned long len, const unsigned long pgoff,
108 : : const unsigned long flags)
109 : : {
110 : : struct vm_area_struct *vma;
111 : 1856444 : struct mm_struct *mm = current->mm;
112 : : unsigned long addr = addr0;
113 : : int do_align = 0;
114 : : int aliasing = cache_is_vipt_aliasing();
115 : : struct vm_unmapped_area_info info;
116 : :
117 : : /*
118 : : * We only need to do colour alignment if either the I or D
119 : : * caches alias.
120 : : */
121 : : if (aliasing)
122 : : do_align = filp || (flags & MAP_SHARED);
123 : :
124 : : /* requested length too big for entire address space */
125 [ + ]: 1856444 : if (len > TASK_SIZE)
126 : : return -ENOMEM;
127 : :
128 [ + + ]: 1856480 : if (flags & MAP_FIXED) {
129 : : if (aliasing && flags & MAP_SHARED &&
130 : : (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
131 : : return -EINVAL;
132 : : return addr;
133 : : }
134 : :
135 : : /* requesting a specific address */
136 [ + + ]: 1608429 : if (addr) {
137 : : if (do_align)
138 : : addr = COLOUR_ALIGN(addr, pgoff);
139 : : else
140 : 134 : addr = PAGE_ALIGN(addr);
141 : 134 : vma = find_vma(mm, addr);
142 [ + - ][ + - ]: 134 : if (TASK_SIZE - len >= addr &&
143 [ + + ]: 134 : (!vma || addr + len <= vma->vm_start))
144 : : return addr;
145 : : }
146 : :
147 : 1608338 : info.flags = VM_UNMAPPED_AREA_TOPDOWN;
148 : 1608338 : info.length = len;
149 : 1608338 : info.low_limit = FIRST_USER_ADDRESS;
150 : 1608338 : info.high_limit = mm->mmap_base;
151 : 1608338 : info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
152 : 1608338 : info.align_offset = pgoff << PAGE_SHIFT;
153 : : addr = vm_unmapped_area(&info);
154 : :
155 : : /*
156 : : * A failed mmap() very likely causes application failure,
157 : : * so fall back to the bottom-up function here. This scenario
158 : : * can happen with large stack limits and large mmap()
159 : : * allocations.
160 : : */
161 [ + + ]: 1608277 : if (addr & ~PAGE_MASK) {
162 : : VM_BUG_ON(addr != -ENOMEM);
163 : 23181 : info.flags = 0;
164 : 23181 : info.low_limit = mm->mmap_base;
165 : 23181 : info.high_limit = TASK_SIZE;
166 : : addr = vm_unmapped_area(&info);
167 : : }
168 : :
169 : 1608286 : return addr;
170 : : }
171 : :
172 : 0 : void arch_pick_mmap_layout(struct mm_struct *mm)
173 : : {
174 : : unsigned long random_factor = 0UL;
175 : :
176 : : /* 8 bits of randomness in 20 address space bits */
177 [ + + ][ + + ]: 27250 : if ((current->flags & PF_RANDOMIZE) &&
178 : 27244 : !(current->personality & ADDR_NO_RANDOMIZE))
179 : 27243 : random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT;
180 : :
181 [ + + ]: 27240 : if (mmap_is_legacy()) {
182 : 731 : mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
183 : 731 : mm->get_unmapped_area = arch_get_unmapped_area;
184 : : } else {
185 : 26509 : mm->mmap_base = mmap_base(random_factor);
186 : 26509 : mm->get_unmapped_area = arch_get_unmapped_area_topdown;
187 : : }
188 : 27240 : }
189 : :
190 : : /*
191 : : * You really shouldn't be using read() or write() on /dev/mem. This
192 : : * might go away in the future.
193 : : */
194 : 0 : int valid_phys_addr_range(phys_addr_t addr, size_t size)
195 : : {
196 [ # # ]: 0 : if (addr < PHYS_OFFSET)
197 : : return 0;
198 [ # # ]: 0 : if (addr + size > __pa(high_memory - 1) + 1)
199 : : return 0;
200 : :
201 : 0 : return 1;
202 : : }
203 : :
204 : : /*
205 : : * Do not allow /dev/mem mappings beyond the supported physical range.
206 : : */
207 : 0 : int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
208 : : {
209 : 0 : return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
210 : : }
211 : :
212 : : #ifdef CONFIG_STRICT_DEVMEM
213 : :
214 : : #include <linux/ioport.h>
215 : :
216 : : /*
217 : : * devmem_is_allowed() checks to see if /dev/mem access to a certain
218 : : * address is valid. The argument is a physical page number.
219 : : * We mimic x86 here by disallowing access to system RAM as well as
220 : : * device-exclusive MMIO regions. This effectively disable read()/write()
221 : : * on /dev/mem.
222 : : */
223 : 0 : int devmem_is_allowed(unsigned long pfn)
224 : : {
225 [ # # ]: 0 : if (iomem_is_exclusive(pfn << PAGE_SHIFT))
226 : : return 0;
227 [ # # ]: 0 : if (!page_is_ram(pfn))
228 : : return 1;
229 : 0 : return 0;
230 : : }
231 : :
232 : : #endif
|