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 }