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: stable/11/sys/vm/vm_unix.c 341467 2018-12-04 15:04:48Z emaste $"); 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 74341467Semastesys_obreak(struct thread *td, struct obreak_args *uap) 751541Srgrimes{ 7683366Sjulian struct vmspace *vm = td->td_proc->p_vmspace; 77245296Szont vm_map_t map = &vm->vm_map; 7816679Sdyson vm_offset_t new, old, base; 79244384Szont rlim_t datalim, lmemlim, vmemlim; 80226343Smarcel int prot, rv; 8179224Sdillon int error = 0; 82118771Sbms boolean_t do_map_wirefuture; 831541Srgrimes 84284215Smjg datalim = lim_cur(td, RLIMIT_DATA); 85284215Smjg lmemlim = lim_cur(td, RLIMIT_MEMLOCK); 86284215Smjg vmemlim = lim_cur(td, RLIMIT_VMEM); 87125454Sjhb 88118771Sbms do_map_wirefuture = FALSE; 8998460Salc new = round_page((vm_offset_t)uap->nsize); 90245296Szont vm_map_lock(map); 9179224Sdillon 9216679Sdyson base = round_page((vm_offset_t) vm->vm_daddr); 9366748Sdwmalone old = base + ctob(vm->vm_dsize); 9416679Sdyson if (new > base) { 9566748Sdwmalone /* 9698498Salc * Check the resource limit, but allow a process to reduce 9798498Salc * its usage, even if it remains over the limit. 9866748Sdwmalone */ 99125454Sjhb if (new - base > datalim && new > old) { 10079224Sdillon error = ENOMEM; 10179224Sdillon goto done; 10279224Sdillon } 103245296Szont if (new > vm_map_max(map)) { 10479224Sdillon error = ENOMEM; 10579224Sdillon goto done; 10679224Sdillon } 10716679Sdyson } else if (new < base) { 10816679Sdyson /* 10916679Sdyson * This is simply an invalid value. If someone wants to 11016679Sdyson * do fancy address space manipulations, mmap and munmap 11116679Sdyson * can do most of what the user would want. 11216679Sdyson */ 11379224Sdillon error = EINVAL; 11479224Sdillon goto done; 11516679Sdyson } 11616679Sdyson if (new > old) { 117245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 118245296Szont if (ptoa(pmap_wired_count(map->pmap)) + 119244384Szont (new - old) > lmemlim) { 120244384Szont error = ENOMEM; 121244384Szont goto done; 122244384Szont } 123244384Szont } 124245296Szont if (map->size + (new - old) > vmemlim) { 12598833Sdillon error = ENOMEM; 12698833Sdillon goto done; 12798833Sdillon } 128223825Strasz#ifdef RACCT 129282213Strasz if (racct_enable) { 130282213Strasz PROC_LOCK(td->td_proc); 131282213Strasz error = racct_set(td->td_proc, RACCT_DATA, new - base); 132244384Szont if (error != 0) { 133282213Strasz PROC_UNLOCK(td->td_proc); 134282213Strasz error = ENOMEM; 135282213Strasz goto done; 136282213Strasz } 137282213Strasz error = racct_set(td->td_proc, RACCT_VMEM, 138282213Strasz map->size + (new - old)); 139282213Strasz if (error != 0) { 140244384Szont racct_set_force(td->td_proc, RACCT_DATA, 141244384Szont old - base); 142244384Szont PROC_UNLOCK(td->td_proc); 143244384Szont error = ENOMEM; 144244384Szont goto done; 145244384Szont } 146282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 147282213Strasz error = racct_set(td->td_proc, RACCT_MEMLOCK, 148282213Strasz ptoa(pmap_wired_count(map->pmap)) + 149282213Strasz (new - old)); 150282213Strasz if (error != 0) { 151282213Strasz racct_set_force(td->td_proc, RACCT_DATA, 152282213Strasz old - base); 153282213Strasz racct_set_force(td->td_proc, RACCT_VMEM, 154282213Strasz map->size); 155282213Strasz PROC_UNLOCK(td->td_proc); 156282213Strasz error = ENOMEM; 157282213Strasz goto done; 158282213Strasz } 159282213Strasz } 160282213Strasz PROC_UNLOCK(td->td_proc); 161244384Szont } 162223825Strasz#endif 163226343Smarcel prot = VM_PROT_RW; 164226343Smarcel#ifdef COMPAT_FREEBSD32 165268351Smarcel#if defined(__amd64__) 166226388Skib if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32)) 167226343Smarcel prot |= VM_PROT_EXECUTE; 168226343Smarcel#endif 169226343Smarcel#endif 170245296Szont rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0); 1711541Srgrimes if (rv != KERN_SUCCESS) { 172223825Strasz#ifdef RACCT 173282213Strasz if (racct_enable) { 174282213Strasz PROC_LOCK(td->td_proc); 175282213Strasz racct_set_force(td->td_proc, 176282213Strasz RACCT_DATA, old - base); 177282213Strasz racct_set_force(td->td_proc, 178282213Strasz RACCT_VMEM, map->size); 179282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 180282213Strasz racct_set_force(td->td_proc, 181282213Strasz RACCT_MEMLOCK, 182282213Strasz ptoa(pmap_wired_count(map->pmap))); 183282213Strasz } 184282213Strasz PROC_UNLOCK(td->td_proc); 185244384Szont } 186223825Strasz#endif 18779224Sdillon error = ENOMEM; 18879224Sdillon goto done; 1891541Srgrimes } 19098460Salc vm->vm_dsize += btoc(new - old); 191118771Sbms /* 192118771Sbms * Handle the MAP_WIREFUTURE case for legacy applications, 193118771Sbms * by marking the newly mapped range of pages as wired. 194118771Sbms * We are not required to perform a corresponding 195118771Sbms * vm_map_unwire() before vm_map_delete() below, as 196118771Sbms * it will forcibly unwire the pages in the range. 197118771Sbms * 198118771Sbms * XXX If the pages cannot be wired, no error is returned. 199118771Sbms */ 200245296Szont if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { 201118771Sbms if (bootverbose) 202118771Sbms printf("obreak: MAP_WIREFUTURE set\n"); 203118771Sbms do_map_wirefuture = TRUE; 204118771Sbms } 20516679Sdyson } else if (new < old) { 206245296Szont rv = vm_map_delete(map, new, old); 2071541Srgrimes if (rv != KERN_SUCCESS) { 20879224Sdillon error = ENOMEM; 20979224Sdillon goto done; 2101541Srgrimes } 21116679Sdyson vm->vm_dsize -= btoc(old - new); 212223825Strasz#ifdef RACCT 213282213Strasz if (racct_enable) { 214282213Strasz PROC_LOCK(td->td_proc); 215282213Strasz racct_set_force(td->td_proc, RACCT_DATA, new - base); 216282213Strasz racct_set_force(td->td_proc, RACCT_VMEM, map->size); 217282213Strasz if (!old_mlock && map->flags & MAP_WIREFUTURE) { 218282213Strasz racct_set_force(td->td_proc, RACCT_MEMLOCK, 219282213Strasz ptoa(pmap_wired_count(map->pmap))); 220282213Strasz } 221282213Strasz PROC_UNLOCK(td->td_proc); 222244384Szont } 223223825Strasz#endif 2241541Srgrimes } 22579224Sdillondone: 226245296Szont vm_map_unlock(map); 227118771Sbms 228118771Sbms if (do_map_wirefuture) 229245296Szont (void) vm_map_wire(map, old, new, 230118771Sbms VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); 231118771Sbms 23279224Sdillon return (error); 2331541Srgrimes} 2341541Srgrimes 23512221Sbde#ifndef _SYS_SYSPROTO_H_ 2361541Srgrimesstruct ovadvise_args { 2375455Sdg int anom; 2381541Srgrimes}; 23912221Sbde#endif 2401549Srgrimes 24182697Sdillon/* 24282697Sdillon * MPSAFE 24382697Sdillon */ 2441541Srgrimes/* ARGSUSED */ 2451541Srgrimesint 246341467Semastesys_ovadvise(struct thread *td, struct ovadvise_args *uap) 2471541Srgrimes{ 24879224Sdillon /* START_GIANT_OPTIONAL */ 24979224Sdillon /* END_GIANT_OPTIONAL */ 2501541Srgrimes return (EINVAL); 2511541Srgrimes} 252