1 /* $OpenBSD: osf1_mmap.c,v 1.6 2006/03/04 19:33:21 miod Exp $ */
2 /* $NetBSD: osf1_mmap.c,v 1.5 2000/04/11 05:26:27 chs Exp $ */
3
4 /*
5 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christopher G. Demetriou
18 * for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/mman.h>
38 #include <sys/mount.h>
39 #include <sys/syscallargs.h>
40 #include <uvm/uvm.h>
41
42 #include <compat/osf1/osf1.h>
43 #include <compat/osf1/osf1_syscallargs.h>
44 #include <compat/osf1/osf1_cvt.h>
45
46 int
47 osf1_sys_madvise(p, v, retval)
48 struct proc *p;
49 void *v;
50 register_t *retval;
51 {
52 struct osf1_sys_madvise_args *uap = v;
53 struct sys_madvise_args a;
54 int error;
55
56 SCARG(&a, addr) = SCARG(uap, addr);
57 SCARG(&a, len) = SCARG(uap, len);
58
59 error = 0;
60 switch (SCARG(uap, behav)) {
61 case OSF1_MADV_NORMAL:
62 SCARG(&a, behav) = MADV_NORMAL;
63 break;
64
65 case OSF1_MADV_RANDOM:
66 SCARG(&a, behav) = MADV_RANDOM;
67 break;
68
69 case OSF1_MADV_SEQUENTIAL:
70 SCARG(&a, behav) = MADV_SEQUENTIAL;
71 break;
72
73 case OSF1_MADV_WILLNEED:
74 SCARG(&a, behav) = MADV_WILLNEED;
75 break;
76
77 case OSF1_MADV_DONTNEED_COMPAT:
78 SCARG(&a, behav) = MADV_DONTNEED;
79 break;
80 #if 0
81 case OSF1_MADV_SPACEAVAIL:
82 SCARG(&a, behav) = MADV_SPACEAVAIL;
83 break;
84 #endif
85 case OSF1_MADV_DONTNEED:
86 /*
87 * XXX not supported. In Digital UNIX, this flushes all
88 * XXX data in the region and replaces it with ZFOD pages.
89 */
90 error = EINVAL;
91 break;
92
93 default:
94 error = EINVAL;
95 break;
96 }
97
98 if (error == 0) {
99 error = sys_madvise(p, &a, retval);
100
101 /*
102 * NetBSD madvise() currently always returns ENOSYS.
103 * Digital UNIX says that non-operational requests (i.e.
104 * valid, but unimplemented 'behav') will return success.
105 */
106 if (error == ENOSYS)
107 error = 0;
108 }
109 return (error);
110 }
111
112 int
113 osf1_sys_mmap(p, v, retval)
114 struct proc *p;
115 void *v;
116 register_t *retval;
117 {
118 struct osf1_sys_mmap_args *uap = v;
119 struct sys_mmap_args a;
120 unsigned long leftovers;
121
122 SCARG(&a, addr) = SCARG(uap, addr);
123 SCARG(&a, len) = SCARG(uap, len);
124 SCARG(&a, fd) = SCARG(uap, fd);
125 SCARG(&a, pad) = 0;
126 SCARG(&a, pos) = SCARG(uap, pos);
127
128 /* translate prot */
129 SCARG(&a, prot) = emul_flags_translate(osf1_mmap_prot_xtab,
130 SCARG(uap, prot), &leftovers);
131 if (leftovers != 0)
132 return (EINVAL);
133
134 /* translate flags */
135 SCARG(&a, flags) = emul_flags_translate(osf1_mmap_flags_xtab,
136 SCARG(uap, flags), &leftovers);
137 if (leftovers != 0)
138 return (EINVAL);
139
140 /*
141 * XXX The following code is evil.
142 *
143 * The OSF/1 mmap() function attempts to map non-fixed entries
144 * near the address that the user specified. Therefore, for
145 * non-fixed entries we try to find space in the address space
146 * starting at that address. If the user specified zero, we
147 * start looking at at least NBPG, so that programs can't
148 * accidentally live through deferencing NULL.
149 *
150 * The need for this kludgery is increased by the fact that
151 * the loader data segment is mapped at
152 * (end of user address space) - 1G, MAXDSIZ is 1G, and
153 * the VM system tries allocate non-fixed mappings _AFTER_
154 * (start of data) + MAXDSIZ. With the loader, of course,
155 * that means that it'll start trying at
156 * (end of user address space), and will never succeed!
157 *
158 * Notes:
159 *
160 * * Though we find space here, if something else (e.g. a second
161 * thread) were mucking with the address space the mapping
162 * we found might be used by another mmap(), and this call
163 * would clobber that region.
164 *
165 * * In general, tricks like this only work for MAP_ANON mappings,
166 * because of sharing/cache issues. That's not a problem on
167 * the Alpha, and though it's not good style to abuse that fact,
168 * there's little choice.
169 *
170 * * In order for this to be done right, the VM system should
171 * really try to use the requested 'addr' passed in to mmap()
172 * as a hint, even if non-fixed. If it's passed as zero,
173 * _maybe_ then try (start of data) + MAXDSIZ, or maybe
174 * provide a better way to avoid the data region altogether.
175 */
176 if ((SCARG(&a, flags) & MAP_FIXED) == 0) {
177 vaddr_t addr = round_page((vaddr_t)SCARG(&a, addr));
178 vsize_t size = round_page((vsize_t)SCARG(&a, len));
179 int fixed = 0;
180
181 vm_map_lock(&p->p_vmspace->vm_map);
182
183 /* if non-NULL address given, start looking there */
184 /* XXX - UVM */
185 if (addr != 0 && uvm_map_findspace(&p->p_vmspace->vm_map,
186 addr, size, &addr, NULL, 0, 0, 0) != NULL) {
187 fixed = 1;
188 goto done;
189 }
190
191 /* didn't find anything. take it again from the top. */
192 if (uvm_map_findspace(&p->p_vmspace->vm_map, NBPG, size, &addr,
193 NULL, 0, 0, 0) != NULL) {
194 fixed = 1;
195 goto done;
196 }
197
198 done:
199 vm_map_unlock(&p->p_vmspace->vm_map);
200 if (fixed) {
201 SCARG(&a, flags) |= MAP_FIXED;
202 SCARG(&a, addr) = (void *)addr;
203 }
204 }
205
206 return sys_mmap(p, &a, retval);
207 }
208
209 int
210 osf1_sys_mprotect(p, v, retval)
211 struct proc *p;
212 void *v;
213 register_t *retval;
214 {
215 struct osf1_sys_mprotect_args *uap = v;
216 struct sys_mprotect_args a;
217 unsigned long leftovers;
218
219 SCARG(&a, addr) = SCARG(uap, addr);
220 SCARG(&a, len) = SCARG(uap, len);
221
222 /* translate prot */
223 SCARG(&a, prot) = emul_flags_translate(osf1_mmap_prot_xtab,
224 SCARG(uap, prot), &leftovers);
225 if (leftovers != 0)
226 return (EINVAL);
227
228 return sys_mprotect(p, &a, retval);
229 }