1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 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/random.h> 10 #include <linux/io.h> 11 12 unsigned long shm_align_mask = (0x4000 >> 1) - 1; /* Sane caches */ 13 14 #define COLOUR_ALIGN(addr, pgoff) \ 15 ((((addr) + shm_align_mask) & ~shm_align_mask) + \ 16 (((pgoff) << PAGE_SHIFT) & shm_align_mask)) 17 18 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, 19 unsigned long len, unsigned long pgoff, unsigned long flags) 20 { 21 struct vm_area_struct *vmm; 22 int do_color_align; 23 24 if (flags & MAP_FIXED) { 25 /* 26 * We do not accept a shared mapping if it would violate 27 * cache aliasing constraints. 28 */ 29 if ((flags & MAP_SHARED) && 30 ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) 31 return -EINVAL; 32 return addr; 33 } 34 35 if (len > TASK_SIZE) 36 return -ENOMEM; 37 do_color_align = 0; 38 if (filp || (flags & MAP_SHARED)) 39 do_color_align = 1; 40 if (addr) { 41 if (do_color_align) 42 addr = COLOUR_ALIGN(addr, pgoff); 43 else 44 addr = PAGE_ALIGN(addr); 45 vmm = find_vma(current->mm, addr); 46 if (TASK_SIZE - len >= addr && 47 (!vmm || addr + len <= vmm->vm_start)) 48 return addr; 49 } 50 addr = TASK_UNMAPPED_BASE; 51 if (do_color_align) 52 addr = COLOUR_ALIGN(addr, pgoff); 53 else 54 addr = PAGE_ALIGN(addr); 55 56 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { 57 /* At this point: (!vmm || addr < vmm->vm_end). */ 58 if (TASK_SIZE - len < addr) 59 return -ENOMEM; 60 if (!vmm || addr + len <= vmm->vm_start) 61 return addr; 62 addr = vmm->vm_end; 63 if (do_color_align) 64 addr = COLOUR_ALIGN(addr, pgoff); 65 } 66 } 67