1 /* $NetBSD: uvm_unix.c,v 1.4 1998/03/09 00:58:59 mrg Exp $ */ 2 3 /* 4 * XXXCDC: "ROUGH DRAFT" QUALITY UVM PRE-RELEASE FILE! 5 * >>>USE AT YOUR OWN RISK, WORK IS NOT FINISHED<<< 6 */ 7 /* 8 * Copyright (c) 1997 Charles D. Cranor and Washington University. 9 * Copyright (c) 1991, 1993 The Regents of the University of California. 10 * Copyright (c) 1988 University of Utah. 11 * 12 * All rights reserved. 13 * 14 * This code is derived from software contributed to Berkeley by 15 * the Systems Programming Group of the University of Utah Computer 16 * Science Department. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. All advertising materials mentioning features or use of this software 27 * must display the following acknowledgement: 28 * This product includes software developed by Charles D. Cranor, 29 * Washington University, the University of California, Berkeley and 30 * its contributors. 31 * 4. Neither the name of the University nor the names of its contributors 32 * may be used to endorse or promote products derived from this software 33 * without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 * 47 * from: Utah $Hdr: vm_unix.c 1.1 89/11/07$ 48 * @(#)vm_unix.c 8.1 (Berkeley) 6/11/93 49 * from: Id: uvm_unix.c,v 1.1.2.2 1997/08/25 18:52:30 chuck Exp 50 */ 51 52 /* 53 * uvm_unix.c: traditional sbrk/grow interface to vm. 54 */ 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/proc.h> 59 #include <sys/resourcevar.h> 60 #include <sys/vnode.h> 61 #include <sys/core.h> 62 63 #include <sys/mount.h> 64 #include <sys/syscallargs.h> 65 66 #include <vm/vm.h> 67 #include <uvm/uvm.h> 68 69 70 /* 71 * sys_obreak: set break 72 */ 73 74 int 75 sys_obreak(p, v, retval) 76 struct proc *p; 77 void *v; 78 register_t *retval; 79 { 80 struct sys_obreak_args /* { 81 syscallarg(char *) nsize; 82 } */ *uap = v; 83 register struct vmspace *vm = p->p_vmspace; 84 vm_offset_t new, old; 85 int rv; 86 register int diff; 87 88 old = (vm_offset_t)vm->vm_daddr; 89 new = round_page(SCARG(uap, nsize)); 90 if ((int)(new - old) > p->p_rlimit[RLIMIT_DATA].rlim_cur) 91 return(ENOMEM); 92 93 old = round_page(old + ctob(vm->vm_dsize)); 94 diff = new - old; 95 96 /* 97 * grow or shrink? 98 */ 99 100 if (diff > 0) { 101 102 rv = uvm_map(&vm->vm_map, &old, diff, NULL, UVM_UNKNOWN_OFFSET, 103 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY, 104 UVM_ADV_NORMAL, UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED| 105 UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)); 106 107 if (rv != KERN_SUCCESS) { 108 uprintf("sbrk: grow failed, return = %d\n", rv); 109 return(ENOMEM); 110 } 111 vm->vm_dsize += btoc(diff); 112 113 } else if (diff < 0) { 114 115 diff = -diff; 116 rv = uvm_deallocate(&vm->vm_map, new, diff); 117 if (rv != KERN_SUCCESS) { 118 uprintf("sbrk: shrink failed, return = %d\n", rv); 119 return(ENOMEM); 120 } 121 vm->vm_dsize -= btoc(diff); 122 123 } 124 return(0); 125 } 126 127 /* 128 * uvm_grow: enlarge the "stack segment" to include sp. 129 */ 130 131 int 132 uvm_grow(p, sp) 133 struct proc *p; 134 vm_offset_t sp; 135 { 136 register struct vmspace *vm = p->p_vmspace; 137 register int si; 138 139 /* 140 * For user defined stacks (from sendsig). 141 */ 142 if (sp < (vm_offset_t)vm->vm_maxsaddr) 143 return (0); 144 145 /* 146 * For common case of already allocated (from trap). 147 */ 148 if (sp >= USRSTACK - ctob(vm->vm_ssize)) 149 return (1); 150 151 /* 152 * Really need to check vs limit and increment stack size if ok. 153 */ 154 si = clrnd(btoc(USRSTACK-sp) - vm->vm_ssize); 155 if (vm->vm_ssize + si > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) 156 return (0); 157 vm->vm_ssize += si; 158 return (1); 159 } 160 161 /* 162 * sys_oadvise: old advice system call 163 */ 164 165 /* ARGSUSED */ 166 int 167 sys_ovadvise(p, v, retval) 168 struct proc *p; 169 void *v; 170 register_t *retval; 171 { 172 #if 0 173 struct sys_ovadvise_args /* { 174 syscallarg(int) anom; 175 } */ *uap = v; 176 #endif 177 178 return (EINVAL); 179 } 180 181 /* 182 * uvm_coredump: dump core! 183 */ 184 185 int 186 uvm_coredump(p, vp, cred, chdr) 187 struct proc *p; 188 struct vnode *vp; 189 struct ucred *cred; 190 struct core *chdr; 191 { 192 register struct vmspace *vm = p->p_vmspace; 193 register vm_map_t map = &vm->vm_map; 194 register vm_map_entry_t entry; 195 vm_offset_t start, end; 196 struct coreseg cseg; 197 off_t offset; 198 int flag, error = 0; 199 200 if (!map->is_main_map) { 201 #ifdef DEBUG 202 uprintf("uvm_coredump: %s map 0x%lx: pmap=0x%lx,ref=%d," 203 "nentries=%d,version=%d\n", 204 (map->is_main_map ? "Task" : "Share"), 205 (long)map, (long)(map->pmap), 206 map->ref_count, map->nentries, 207 map->timestamp); 208 #endif 209 return (EIO); 210 } 211 212 offset = chdr->c_hdrsize + chdr->c_seghdrsize + chdr->c_cpusize; 213 214 for (entry = map->header.next; entry != &map->header; 215 entry = entry->next) { 216 217 if (UVM_ET_ISMAP(entry)) { 218 #ifdef DEBUG 219 uprintf("uvm_coredump: entry: share=0x%lx, " 220 "offset=0x%lx\n", (long) entry->object.share_map, 221 (long) entry->offset); 222 #endif 223 continue; 224 } 225 226 if (!(entry->protection & VM_PROT_WRITE)) 227 continue; 228 229 start = entry->start; 230 end = entry->end; 231 232 if (start >= VM_MAXUSER_ADDRESS) 233 continue; 234 235 if (end > VM_MAXUSER_ADDRESS) 236 end = VM_MAXUSER_ADDRESS; 237 238 if (start >= (vm_offset_t)vm->vm_maxsaddr) { 239 flag = CORE_STACK; 240 start = trunc_page(USRSTACK - ctob(vm->vm_ssize)); 241 if (start >= end) 242 continue; 243 } else 244 flag = CORE_DATA; 245 246 /* 247 * Set up a new core file segment. 248 */ 249 CORE_SETMAGIC(cseg, CORESEGMAGIC, CORE_GETMID(*chdr), flag); 250 cseg.c_addr = start; 251 cseg.c_size = end - start; 252 253 error = vn_rdwr(UIO_WRITE, vp, 254 (caddr_t)&cseg, chdr->c_seghdrsize, 255 offset, UIO_SYSSPACE, 256 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 257 if (error) 258 break; 259 260 offset += chdr->c_seghdrsize; 261 error = vn_rdwr(UIO_WRITE, vp, 262 (caddr_t)cseg.c_addr, (int)cseg.c_size, 263 offset, UIO_USERSPACE, 264 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 265 if (error) 266 break; 267 268 offset += cseg.c_size; 269 chdr->c_nseg++; 270 } 271 272 return (error); 273 } 274 275