Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/mm/mmap.c
26444 views
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
186