1 /* $NetBSD: uvm_unix.c,v 1.7 1998/10/11 23:18:21 chuck 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 vaddr_t new, old; 85 int rv; 86 register int diff; 87 88 old = (vaddr_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 vaddr_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 < (vaddr_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 vaddr_t start, end; 196 struct coreseg cseg; 197 off_t offset; 198 int flag, error = 0; 199 200 offset = chdr->c_hdrsize + chdr->c_seghdrsize + chdr->c_cpusize; 201 202 for (entry = map->header.next; entry != &map->header; 203 entry = entry->next) { 204 205 /* should never happen for a user process */ 206 if (UVM_ET_ISSUBMAP(entry)) { 207 panic("uvm_coredump: user process with submap?"); 208 } 209 210 if (!(entry->protection & VM_PROT_WRITE)) 211 continue; 212 213 start = entry->start; 214 end = entry->end; 215 216 if (start >= VM_MAXUSER_ADDRESS) 217 continue; 218 219 if (end > VM_MAXUSER_ADDRESS) 220 end = VM_MAXUSER_ADDRESS; 221 222 if (start >= (vaddr_t)vm->vm_maxsaddr) { 223 flag = CORE_STACK; 224 start = trunc_page(USRSTACK - ctob(vm->vm_ssize)); 225 if (start >= end) 226 continue; 227 } else 228 flag = CORE_DATA; 229 230 /* 231 * Set up a new core file segment. 232 */ 233 CORE_SETMAGIC(cseg, CORESEGMAGIC, CORE_GETMID(*chdr), flag); 234 cseg.c_addr = start; 235 cseg.c_size = end - start; 236 237 error = vn_rdwr(UIO_WRITE, vp, 238 (caddr_t)&cseg, chdr->c_seghdrsize, 239 offset, UIO_SYSSPACE, 240 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 241 if (error) 242 break; 243 244 offset += chdr->c_seghdrsize; 245 error = vn_rdwr(UIO_WRITE, vp, 246 (caddr_t)cseg.c_addr, (int)cseg.c_size, 247 offset, UIO_USERSPACE, 248 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 249 if (error) 250 break; 251 252 offset += cseg.c_size; 253 chdr->c_nseg++; 254 } 255 256 return (error); 257 } 258 259