1 /* 2 * arch/sh/mm/mmap.c 3 * 4 * Copyright (C) 2008 - 2009 Paul Mundt 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 #include <linux/io.h> 11 #include <linux/mm.h> 12 #include <linux/sched/mm.h> 13 #include <linux/mman.h> 14 #include <linux/module.h> 15 #include <asm/page.h> 16 #include <asm/processor.h> 17 18 unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ 19 EXPORT_SYMBOL(shm_align_mask); 20 21 #ifdef CONFIG_MMU 22 static const pgprot_t protection_map[16] = { 23 [VM_NONE] = PAGE_NONE, 24 [VM_READ] = PAGE_READONLY, 25 [VM_WRITE] = PAGE_COPY, 26 [VM_WRITE | VM_READ] = PAGE_COPY, 27 [VM_EXEC] = PAGE_EXECREAD, 28 [VM_EXEC | VM_READ] = PAGE_EXECREAD, 29 [VM_EXEC | VM_WRITE] = PAGE_COPY, 30 [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY, 31 [VM_SHARED] = PAGE_NONE, 32 [VM_SHARED | VM_READ] = PAGE_READONLY, 33 [VM_SHARED | VM_WRITE] = PAGE_WRITEONLY, 34 [VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED, 35 [VM_SHARED | VM_EXEC] = PAGE_EXECREAD, 36 [VM_SHARED | VM_EXEC | VM_READ] = PAGE_EXECREAD, 37 [VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_RWX, 38 [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_RWX 39 }; 40 DECLARE_VM_GET_PAGE_PROT 41 42 /* 43 * To avoid cache aliases, we map the shared page with same color. 44 */ 45 static inline unsigned long COLOUR_ALIGN(unsigned long addr, 46 unsigned long pgoff) 47 { 48 unsigned long base = (addr + shm_align_mask) & ~shm_align_mask; 49 unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask; 50 51 return base + off; 52 } 53 54 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 55 unsigned long len, unsigned long pgoff, unsigned long flags, 56 vm_flags_t vm_flags) 57 { 58 struct mm_struct *mm = current->mm; 59 struct vm_area_struct *vma; 60 int do_colour_align; 61 struct vm_unmapped_area_info info = {}; 62 63 if (flags & MAP_FIXED) { 64 /* We do not accept a shared mapping if it would violate 65 * cache aliasing constraints. 66 */ 67 if ((flags & MAP_SHARED) && 68 ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) 69 return -EINVAL; 70 return addr; 71 } 72 73 if (unlikely(len > TASK_SIZE)) 74 return -ENOMEM; 75 76 do_colour_align = 0; 77 if (filp || (flags & MAP_SHARED)) 78 do_colour_align = 1; 79 80 if (addr) { 81 if (do_colour_align) 82 addr = COLOUR_ALIGN(addr, pgoff); 83 else 84 addr = PAGE_ALIGN(addr); 85 86 vma = find_vma(mm, addr); 87 if (TASK_SIZE - len >= addr && 88 (!vma || addr + len <= vm_start_gap(vma))) 89 return addr; 90 } 91 92 info.length = len; 93 info.low_limit = TASK_UNMAPPED_BASE; 94 info.high_limit = TASK_SIZE; 95 info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0; 96 info.align_offset = pgoff << PAGE_SHIFT; 97 return vm_unmapped_area(&info); 98 } 99 100 unsigned long 101 arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 102 const unsigned long len, const unsigned long pgoff, 103 const unsigned long flags, vm_flags_t vm_flags) 104 { 105 struct vm_area_struct *vma; 106 struct mm_struct *mm = current->mm; 107 unsigned long addr = addr0; 108 int do_colour_align; 109 struct vm_unmapped_area_info info = {}; 110 111 if (flags & MAP_FIXED) { 112 /* We do not accept a shared mapping if it would violate 113 * cache aliasing constraints. 114 */ 115 if ((flags & MAP_SHARED) && 116 ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) 117 return -EINVAL; 118 return addr; 119 } 120 121 if (unlikely(len > TASK_SIZE)) 122 return -ENOMEM; 123 124 do_colour_align = 0; 125 if (filp || (flags & MAP_SHARED)) 126 do_colour_align = 1; 127 128 /* requesting a specific address */ 129 if (addr) { 130 if (do_colour_align) 131 addr = COLOUR_ALIGN(addr, pgoff); 132 else 133 addr = PAGE_ALIGN(addr); 134 135 vma = find_vma(mm, addr); 136 if (TASK_SIZE - len >= addr && 137 (!vma || addr + len <= vm_start_gap(vma))) 138 return addr; 139 } 140 141 info.flags = VM_UNMAPPED_AREA_TOPDOWN; 142 info.length = len; 143 info.low_limit = PAGE_SIZE; 144 info.high_limit = mm->mmap_base; 145 info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0; 146 info.align_offset = pgoff << PAGE_SHIFT; 147 addr = vm_unmapped_area(&info); 148 149 /* 150 * A failed mmap() very likely causes application failure, 151 * so fall back to the bottom-up function here. This scenario 152 * can happen with large stack limits and large mmap() 153 * allocations. 154 */ 155 if (addr & ~PAGE_MASK) { 156 VM_BUG_ON(addr != -ENOMEM); 157 info.flags = 0; 158 info.low_limit = TASK_UNMAPPED_BASE; 159 info.high_limit = TASK_SIZE; 160 addr = vm_unmapped_area(&info); 161 } 162 163 return addr; 164 } 165 #endif /* CONFIG_MMU */ 166 167 /* 168 * You really shouldn't be using read() or write() on /dev/mem. This 169 * might go away in the future. 170 */ 171 int valid_phys_addr_range(phys_addr_t addr, size_t count) 172 { 173 if (addr < __MEMORY_START) 174 return 0; 175 if (addr + count > __pa(high_memory)) 176 return 0; 177 178 return 1; 179 } 180 181 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) 182 { 183 return 1; 184 } 185