xref: /openbmc/linux/arch/csky/abiv1/mmap.c (revision 2fa49589)
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