1139825Simp/*- 21541Srgrimes * Copyright (c) 1988 University of Utah. 31541Srgrimes * Copyright (c) 1991, 1993 41541Srgrimes * The Regents of the University of California. All rights reserved. 51541Srgrimes * 61541Srgrimes * This code is derived from software contributed to Berkeley by 71541Srgrimes * the Systems Programming Group of the University of Utah Computer 81541Srgrimes * Science Department. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 341541Srgrimes * from: Utah $Hdr: vm_unix.c 1.1 89/11/07$ 351541Srgrimes * 361541Srgrimes * @(#)vm_unix.c 8.1 (Berkeley) 6/11/93 371541Srgrimes */ 381541Srgrimes 39226343Smarcel#include "opt_compat.h" 40226343Smarcel 411541Srgrimes/* 421541Srgrimes * Traditional sbrk/grow interface to VM 431541Srgrimes */ 4477139Sjhb 45116226Sobrien#include <sys/cdefs.h> 46116226Sobrien__FBSDID("$FreeBSD: releng/11.0/sys/vm/vm_unix.c 284215 2015-06-10 10:48:12Z mjg $"); 47116226Sobrien 481541Srgrimes#include <sys/param.h> 4976166Smarkm#include <sys/lock.h> 5076981Sjhb#include <sys/mutex.h> 511541Srgrimes#include <sys/proc.h> 52220373Strasz#include <sys/racct.h> 531541Srgrimes#include <sys/resourcevar.h> 54226343Smarcel#include <sys/sysent.h> 5576981Sjhb#include <sys/sysproto.h> 5676827Salfred#include <sys/systm.h> 571541Srgrimes 581541Srgrimes#include <vm/vm.h> 5912662Sdg#include <vm/vm_param.h> 6012662Sdg#include <vm/pmap.h> 6112662Sdg#include <vm/vm_map.h> 621541Srgrimes 6312221Sbde#ifndef _SYS_SYSPROTO_H_ 641541Srgrimesstruct obreak_args { 6512206Sbde char *nsize; 661541Srgrimes}; 6712221Sbde#endif 681549Srgrimes 6982697Sdillon/* 7082697Sdillon * MPSAFE 7182697Sdillon */ 721541Srgrimes/* ARGSUSED */ 731541Srgrimesint 74225617Skmacysys_obreak(td, uap) 7583366Sjulian struct thread *td; 761541Srgrimes struct obreak_args *uap; 771541Srgrimes{ 7883366Sjulian struct vmspace *vm = td->td_proc->p_vmspace; 79245296Szont vm_map_t map = &vm->vm_map; 8016679Sdyson vm_offset_t new, old, base; 81244384Szont rlim_t datalim, lmemlim, vmemlim; 82226343Smarcel int prot, rv; 8379224Sdillon int error = 0; 84118771Sbms boolean_t do_map_wirefuture; 851541Srgrimes 86284215Smjg datalim = lim_cur(td, RLIMIT_DATA); 87284215Smjg lmemlim = lim_cur(td, RLIMIT_MEMLOCK); 88284215Smjg vmemlim = lim_cur(td, RLIMIT_VMEM); 89125454Sjhb 90118771Sbms do_map_wirefuture = FALSE; 9198460Salc new = round_page((vm_offset_t)uap->nsize); 92245296Szont vm_map_lock(map); 9379224Sdillon 9416679Sdyson base = round_page((vm_offset_t) vm->vm_daddr); 9566748Sdwmalone old = base + ctob(vm->vm_dsize); 9616679Sdyson if (new > base) { 9766748Sdwmalone /* 9898498Salc * Check the resource limit, but allow a process to reduce 9998498Salc * its usage, even if it remains over the limit. 10066748Sdwmalone */ 101125454Sjhb if (new - base > datalim && new > old) { 10279224Sdillon error = ENOMEM; 10379224Sdillon goto done; 10479224Sdillon } 105245296Szont if (new > vm_map_max(map)) { 10679224Sdillon error = ENOMEM; 10779224Sdillon goto done; 10879224Sdillon } 10916679Sdyson } else if (new < base) { 11016679Sdyson /* 11116679Sdyson * This is simply an invalid value. If someone wants to 11216679Sdyson * do fancy address space manipulations, mmap and munmap 11316679Sdyson * can do most of what the user would want. 11416679Sdyson */ 11579224Sdillon error = EINVAL; 11679224Sdillon goto done; 11716679Sdyson } 11816679Sdyson if (new > old) { 119245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 120245296Szont if (ptoa(pmap_wired_count(map->pmap)) + 121244384Szont (new - old) > lmemlim) { 122244384Szont error = ENOMEM; 123244384Szont goto done; 124244384Szont } 125244384Szont } 126245296Szont if (map->size + (new - old) > vmemlim) { 12798833Sdillon error = ENOMEM; 12898833Sdillon goto done; 12998833Sdillon } 130223825Strasz#ifdef RACCT 131282213Strasz if (racct_enable) { 132282213Strasz PROC_LOCK(td->td_proc); 133282213Strasz error = racct_set(td->td_proc, RACCT_DATA, new - base); 134244384Szont if (error != 0) { 135282213Strasz PROC_UNLOCK(td->td_proc); 136282213Strasz error = ENOMEM; 137282213Strasz goto done; 138282213Strasz } 139282213Strasz error = racct_set(td->td_proc, RACCT_VMEM, 140282213Strasz map->size + (new - old)); 141282213Strasz if (error != 0) { 142244384Szont racct_set_force(td->td_proc, RACCT_DATA, 143244384Szont old - base); 144244384Szont PROC_UNLOCK(td->td_proc); 145244384Szont error = ENOMEM; 146244384Szont goto done; 147244384Szont } 148282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 149282213Strasz error = racct_set(td->td_proc, RACCT_MEMLOCK, 150282213Strasz ptoa(pmap_wired_count(map->pmap)) + 151282213Strasz (new - old)); 152282213Strasz if (error != 0) { 153282213Strasz racct_set_force(td->td_proc, RACCT_DATA, 154282213Strasz old - base); 155282213Strasz racct_set_force(td->td_proc, RACCT_VMEM, 156282213Strasz map->size); 157282213Strasz PROC_UNLOCK(td->td_proc); 158282213Strasz error = ENOMEM; 159282213Strasz goto done; 160282213Strasz } 161282213Strasz } 162282213Strasz PROC_UNLOCK(td->td_proc); 163244384Szont } 164223825Strasz#endif 165226343Smarcel prot = VM_PROT_RW; 166226343Smarcel#ifdef COMPAT_FREEBSD32 167268351Smarcel#if defined(__amd64__) 168226388Skib if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32)) 169226343Smarcel prot |= VM_PROT_EXECUTE; 170226343Smarcel#endif 171226343Smarcel#endif 172245296Szont rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0); 1731541Srgrimes if (rv != KERN_SUCCESS) { 174223825Strasz#ifdef RACCT 175282213Strasz if (racct_enable) { 176282213Strasz PROC_LOCK(td->td_proc); 177282213Strasz racct_set_force(td->td_proc, 178282213Strasz RACCT_DATA, old - base); 179282213Strasz racct_set_force(td->td_proc, 180282213Strasz RACCT_VMEM, map->size); 181282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 182282213Strasz racct_set_force(td->td_proc, 183282213Strasz RACCT_MEMLOCK, 184282213Strasz ptoa(pmap_wired_count(map->pmap))); 185282213Strasz } 186282213Strasz PROC_UNLOCK(td->td_proc); 187244384Szont } 188223825Strasz#endif 18979224Sdillon error = ENOMEM; 19079224Sdillon goto done; 1911541Srgrimes } 19298460Salc vm->vm_dsize += btoc(new - old); 193118771Sbms /* 194118771Sbms * Handle the MAP_WIREFUTURE case for legacy applications, 195118771Sbms * by marking the newly mapped range of pages as wired. 196118771Sbms * We are not required to perform a corresponding 197118771Sbms * vm_map_unwire() before vm_map_delete() below, as 198118771Sbms * it will forcibly unwire the pages in the range. 199118771Sbms * 200118771Sbms * XXX If the pages cannot be wired, no error is returned. 201118771Sbms */ 202245296Szont if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { 203118771Sbms if (bootverbose) 204118771Sbms printf("obreak: MAP_WIREFUTURE set\n"); 205118771Sbms do_map_wirefuture = TRUE; 206118771Sbms } 20716679Sdyson } else if (new < old) { 208245296Szont rv = vm_map_delete(map, new, old); 2091541Srgrimes if (rv != KERN_SUCCESS) { 21079224Sdillon error = ENOMEM; 21179224Sdillon goto done; 2121541Srgrimes } 21316679Sdyson vm->vm_dsize -= btoc(old - new); 214223825Strasz#ifdef RACCT 215282213Strasz if (racct_enable) { 216282213Strasz PROC_LOCK(td->td_proc); 217282213Strasz racct_set_force(td->td_proc, RACCT_DATA, new - base); 218282213Strasz racct_set_force(td->td_proc, RACCT_VMEM, map->size); 219282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 220282213Strasz racct_set_force(td->td_proc, RACCT_MEMLOCK, 221282213Strasz ptoa(pmap_wired_count(map->pmap))); 222282213Strasz } 223282213Strasz PROC_UNLOCK(td->td_proc); 224244384Szont } 225223825Strasz#endif 2261541Srgrimes } 22779224Sdillondone: 228245296Szont vm_map_unlock(map); 229118771Sbms 230118771Sbms if (do_map_wirefuture) 231245296Szont (void) vm_map_wire(map, old, new, 232118771Sbms VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); 233118771Sbms 23479224Sdillon return (error); 2351541Srgrimes} 2361541Srgrimes 23712221Sbde#ifndef _SYS_SYSPROTO_H_ 2381541Srgrimesstruct ovadvise_args { 2395455Sdg int anom; 2401541Srgrimes}; 24112221Sbde#endif 2421549Srgrimes 24382697Sdillon/* 24482697Sdillon * MPSAFE 24582697Sdillon */ 2461541Srgrimes/* ARGSUSED */ 2471541Srgrimesint 248225617Skmacysys_ovadvise(td, uap) 24983366Sjulian struct thread *td; 2501541Srgrimes struct ovadvise_args *uap; 2511541Srgrimes{ 25279224Sdillon /* START_GIANT_OPTIONAL */ 25379224Sdillon /* END_GIANT_OPTIONAL */ 2541541Srgrimes return (EINVAL); 2551541Srgrimes} 256