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$"); 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 86125454Sjhb PROC_LOCK(td->td_proc); 87125454Sjhb datalim = lim_cur(td->td_proc, RLIMIT_DATA); 88244384Szont lmemlim = lim_cur(td->td_proc, RLIMIT_MEMLOCK); 89125454Sjhb vmemlim = lim_cur(td->td_proc, RLIMIT_VMEM); 90125454Sjhb PROC_UNLOCK(td->td_proc); 91125454Sjhb 92118771Sbms do_map_wirefuture = FALSE; 9398460Salc new = round_page((vm_offset_t)uap->nsize); 94245296Szont vm_map_lock(map); 9579224Sdillon 9616679Sdyson base = round_page((vm_offset_t) vm->vm_daddr); 9766748Sdwmalone old = base + ctob(vm->vm_dsize); 9816679Sdyson if (new > base) { 9966748Sdwmalone /* 10098498Salc * Check the resource limit, but allow a process to reduce 10198498Salc * its usage, even if it remains over the limit. 10266748Sdwmalone */ 103125454Sjhb if (new - base > datalim && new > old) { 10479224Sdillon error = ENOMEM; 10579224Sdillon goto done; 10679224Sdillon } 107245296Szont if (new > vm_map_max(map)) { 10879224Sdillon error = ENOMEM; 10979224Sdillon goto done; 11079224Sdillon } 11116679Sdyson } else if (new < base) { 11216679Sdyson /* 11316679Sdyson * This is simply an invalid value. If someone wants to 11416679Sdyson * do fancy address space manipulations, mmap and munmap 11516679Sdyson * can do most of what the user would want. 11616679Sdyson */ 11779224Sdillon error = EINVAL; 11879224Sdillon goto done; 11916679Sdyson } 12016679Sdyson if (new > old) { 121245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 122245296Szont if (ptoa(pmap_wired_count(map->pmap)) + 123244384Szont (new - old) > lmemlim) { 124244384Szont error = ENOMEM; 125244384Szont goto done; 126244384Szont } 127244384Szont } 128245296Szont if (map->size + (new - old) > vmemlim) { 12998833Sdillon error = ENOMEM; 13098833Sdillon goto done; 13198833Sdillon } 132223825Strasz#ifdef RACCT 133220373Strasz PROC_LOCK(td->td_proc); 134220373Strasz error = racct_set(td->td_proc, RACCT_DATA, new - base); 135220373Strasz if (error != 0) { 136220373Strasz PROC_UNLOCK(td->td_proc); 137220373Strasz error = ENOMEM; 138220373Strasz goto done; 139220373Strasz } 140220373Strasz error = racct_set(td->td_proc, RACCT_VMEM, 141245296Szont map->size + (new - old)); 142220373Strasz if (error != 0) { 143220373Strasz racct_set_force(td->td_proc, RACCT_DATA, old - base); 144220373Strasz PROC_UNLOCK(td->td_proc); 145220373Strasz error = ENOMEM; 146220373Strasz goto done; 147220373Strasz } 148245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 149244384Szont error = racct_set(td->td_proc, RACCT_MEMLOCK, 150245296Szont ptoa(pmap_wired_count(map->pmap)) + (new - old)); 151244384Szont if (error != 0) { 152244384Szont racct_set_force(td->td_proc, RACCT_DATA, 153244384Szont old - base); 154244384Szont racct_set_force(td->td_proc, RACCT_VMEM, 155245296Szont map->size); 156244384Szont PROC_UNLOCK(td->td_proc); 157244384Szont error = ENOMEM; 158244384Szont goto done; 159244384Szont } 160244384Szont } 161220373Strasz PROC_UNLOCK(td->td_proc); 162223825Strasz#endif 163226343Smarcel prot = VM_PROT_RW; 164226343Smarcel#ifdef COMPAT_FREEBSD32 165226343Smarcel#if defined(__amd64__) || defined(__ia64__) 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 173220373Strasz PROC_LOCK(td->td_proc); 174220373Strasz racct_set_force(td->td_proc, RACCT_DATA, old - base); 175245296Szont racct_set_force(td->td_proc, RACCT_VMEM, map->size); 176245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 177244384Szont racct_set_force(td->td_proc, RACCT_MEMLOCK, 178245296Szont ptoa(pmap_wired_count(map->pmap))); 179244384Szont } 180220373Strasz PROC_UNLOCK(td->td_proc); 181223825Strasz#endif 18279224Sdillon error = ENOMEM; 18379224Sdillon goto done; 1841541Srgrimes } 18598460Salc vm->vm_dsize += btoc(new - old); 186118771Sbms /* 187118771Sbms * Handle the MAP_WIREFUTURE case for legacy applications, 188118771Sbms * by marking the newly mapped range of pages as wired. 189118771Sbms * We are not required to perform a corresponding 190118771Sbms * vm_map_unwire() before vm_map_delete() below, as 191118771Sbms * it will forcibly unwire the pages in the range. 192118771Sbms * 193118771Sbms * XXX If the pages cannot be wired, no error is returned. 194118771Sbms */ 195245296Szont if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { 196118771Sbms if (bootverbose) 197118771Sbms printf("obreak: MAP_WIREFUTURE set\n"); 198118771Sbms do_map_wirefuture = TRUE; 199118771Sbms } 20016679Sdyson } else if (new < old) { 201245296Szont rv = vm_map_delete(map, new, old); 2021541Srgrimes if (rv != KERN_SUCCESS) { 20379224Sdillon error = ENOMEM; 20479224Sdillon goto done; 2051541Srgrimes } 20616679Sdyson vm->vm_dsize -= btoc(old - new); 207223825Strasz#ifdef RACCT 208220373Strasz PROC_LOCK(td->td_proc); 209220373Strasz racct_set_force(td->td_proc, RACCT_DATA, new - base); 210245296Szont racct_set_force(td->td_proc, RACCT_VMEM, map->size); 211245296Szont if (!old_mlock && map->flags & MAP_WIREFUTURE) { 212244384Szont racct_set_force(td->td_proc, RACCT_MEMLOCK, 213245296Szont ptoa(pmap_wired_count(map->pmap))); 214244384Szont } 215220373Strasz PROC_UNLOCK(td->td_proc); 216223825Strasz#endif 2171541Srgrimes } 21879224Sdillondone: 219245296Szont vm_map_unlock(map); 220118771Sbms 221118771Sbms if (do_map_wirefuture) 222245296Szont (void) vm_map_wire(map, old, new, 223118771Sbms VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); 224118771Sbms 22579224Sdillon return (error); 2261541Srgrimes} 2271541Srgrimes 22812221Sbde#ifndef _SYS_SYSPROTO_H_ 2291541Srgrimesstruct ovadvise_args { 2305455Sdg int anom; 2311541Srgrimes}; 23212221Sbde#endif 2331549Srgrimes 23482697Sdillon/* 23582697Sdillon * MPSAFE 23682697Sdillon */ 2371541Srgrimes/* ARGSUSED */ 2381541Srgrimesint 239225617Skmacysys_ovadvise(td, uap) 24083366Sjulian struct thread *td; 2411541Srgrimes struct ovadvise_args *uap; 2421541Srgrimes{ 24379224Sdillon /* START_GIANT_OPTIONAL */ 24479224Sdillon /* END_GIANT_OPTIONAL */ 2451541Srgrimes return (EINVAL); 2461541Srgrimes} 247