Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
0003 
0004 #include <linux/fs.h>
0005 #include <linux/mm.h>
0006 #include <linux/mman.h>
0007 #include <linux/shm.h>
0008 #include <linux/sched.h>
0009 #include <linux/random.h>
0010 #include <linux/io.h>
0011 
0012 #define COLOUR_ALIGN(addr,pgoff)        \
0013     ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +  \
0014      (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
0015 
0016 /*
0017  * We need to ensure that shared mappings are correctly aligned to
0018  * avoid aliasing issues with VIPT caches.  We need to ensure that
0019  * a specific page of an object is always mapped at a multiple of
0020  * SHMLBA bytes.
0021  *
0022  * We unconditionally provide this function for all cases.
0023  */
0024 unsigned long
0025 arch_get_unmapped_area(struct file *filp, unsigned long addr,
0026         unsigned long len, unsigned long pgoff, unsigned long flags)
0027 {
0028     struct mm_struct *mm = current->mm;
0029     struct vm_area_struct *vma;
0030     int do_align = 0;
0031     struct vm_unmapped_area_info info;
0032 
0033     /*
0034      * We only need to do colour alignment if either the I or D
0035      * caches alias.
0036      */
0037     do_align = filp || (flags & MAP_SHARED);
0038 
0039     /*
0040      * We enforce the MAP_FIXED case.
0041      */
0042     if (flags & MAP_FIXED) {
0043         if (flags & MAP_SHARED &&
0044             (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
0045             return -EINVAL;
0046         return addr;
0047     }
0048 
0049     if (len > TASK_SIZE)
0050         return -ENOMEM;
0051 
0052     if (addr) {
0053         if (do_align)
0054             addr = COLOUR_ALIGN(addr, pgoff);
0055         else
0056             addr = PAGE_ALIGN(addr);
0057 
0058         vma = find_vma(mm, addr);
0059         if (TASK_SIZE - len >= addr &&
0060             (!vma || addr + len <= vm_start_gap(vma)))
0061             return addr;
0062     }
0063 
0064     info.flags = 0;
0065     info.length = len;
0066     info.low_limit = mm->mmap_base;
0067     info.high_limit = TASK_SIZE;
0068     info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
0069     info.align_offset = pgoff << PAGE_SHIFT;
0070     return vm_unmapped_area(&info);
0071 }