~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mm/mmap.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp