vm_unix.c revision 244384
11844Swollman/*-
227910Sasami * Copyright (c) 1988 University of Utah.
31638Srgrimes * Copyright (c) 1991, 1993
41844Swollman *	The Regents of the University of California.  All rights reserved.
51638Srgrimes *
61638Srgrimes * This code is derived from software contributed to Berkeley by
71638Srgrimes * the Systems Programming Group of the University of Utah Computer
81844Swollman * Science Department.
91638Srgrimes *
102827Sjkh * Redistribution and use in source and binary forms, with or without
111844Swollman * modification, are permitted provided that the following conditions
121844Swollman * are met:
1326051Sasami * 1. Redistributions of source code must retain the above copyright
141844Swollman *    notice, this list of conditions and the following disclaimer.
151638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
162827Sjkh *    notice, this list of conditions and the following disclaimer in the
171638Srgrimes *    documentation and/or other materials provided with the distribution.
182827Sjkh * 4. Neither the name of the University nor the names of its contributors
191638Srgrimes *    may be used to endorse or promote products derived from this software
2027028Spst *    without specific prior written permission.
211844Swollman *
221844Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231638Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241638Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251638Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261638Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271844Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281844Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291638Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3024750Sbde * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311844Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321844Swollman * SUCH DAMAGE.
338321Sbde *
341844Swollman * from: Utah $Hdr: vm_unix.c 1.1 89/11/07$
352351Sbde *
361638Srgrimes *	@(#)vm_unix.c	8.1 (Berkeley) 6/11/93
372351Sbde */
382351Sbde
392351Sbde#include "opt_compat.h"
402351Sbde
412351Sbde/*
422351Sbde * Traditional sbrk/grow interface to VM
4324750Sbde */
442351Sbde
451638Srgrimes#include <sys/cdefs.h>
461638Srgrimes__FBSDID("$FreeBSD: head/sys/vm/vm_unix.c 244384 2012-12-18 07:35:01Z zont $");
471638Srgrimes
481638Srgrimes#include <sys/param.h>
491638Srgrimes#include <sys/lock.h>
501638Srgrimes#include <sys/mutex.h>
511844Swollman#include <sys/proc.h>
521638Srgrimes#include <sys/racct.h>
531638Srgrimes#include <sys/resourcevar.h>
541638Srgrimes#include <sys/sysent.h>
551638Srgrimes#include <sys/sysproto.h>
5618340Sswallace#include <sys/systm.h>
571638Srgrimes
581638Srgrimes#include <vm/vm.h>
5916663Sjkh#include <vm/vm_param.h>
6014444Swosch#include <vm/pmap.h>
6116826Sphk#include <vm/vm_map.h>
6216437Sphk
631638Srgrimes#ifndef _SYS_SYSPROTO_H_
6416437Sphkstruct obreak_args {
651638Srgrimes	char *nsize;
6627910Sasami};
6724750Sbde#endif
6824750Sbde
6925110Sbde/*
7024750Sbde * MPSAFE
7124750Sbde */
721638Srgrimes/* ARGSUSED */
731638Srgrimesint
741638Srgrimessys_obreak(td, uap)
751638Srgrimes	struct thread *td;
761638Srgrimes	struct obreak_args *uap;
7716663Sjkh{
781638Srgrimes	struct vmspace *vm = td->td_proc->p_vmspace;
791844Swollman	vm_offset_t new, old, base;
801996Swollman	rlim_t datalim, lmemlim, vmemlim;
811638Srgrimes	int prot, rv;
821638Srgrimes	int error = 0;
831638Srgrimes	boolean_t do_map_wirefuture;
8423542Sbde
851638Srgrimes	PROC_LOCK(td->td_proc);
861638Srgrimes	datalim = lim_cur(td->td_proc, RLIMIT_DATA);
871638Srgrimes	lmemlim = lim_cur(td->td_proc, RLIMIT_MEMLOCK);
881638Srgrimes	vmemlim = lim_cur(td->td_proc, RLIMIT_VMEM);
891638Srgrimes	PROC_UNLOCK(td->td_proc);
901638Srgrimes
911638Srgrimes	do_map_wirefuture = FALSE;
921638Srgrimes	new = round_page((vm_offset_t)uap->nsize);
932351Sbde	vm_map_lock(&vm->vm_map);
941638Srgrimes
956031Sjkh	base = round_page((vm_offset_t) vm->vm_daddr);
961638Srgrimes	old = base + ctob(vm->vm_dsize);
971638Srgrimes	if (new > base) {
981638Srgrimes		/*
9916663Sjkh		 * Check the resource limit, but allow a process to reduce
1001844Swollman		 * its usage, even if it remains over the limit.
1011844Swollman		 */
1021844Swollman		if (new - base > datalim && new > old) {
1031638Srgrimes			error = ENOMEM;
1041844Swollman			goto done;
1051638Srgrimes		}
1061638Srgrimes		if (new > vm_map_max(&vm->vm_map)) {
1075585Sjkh			error = ENOMEM;
1084442Sphk			goto done;
10916663Sjkh		}
11026760Sjkh	} else if (new < base) {
11126760Sjkh		/*
11226760Sjkh		 * This is simply an invalid value.  If someone wants to
1134442Sphk		 * do fancy address space manipulations, mmap and munmap
1144442Sphk		 * can do most of what the user would want.
1151638Srgrimes		 */
11616663Sjkh		error = EINVAL;
1171638Srgrimes		goto done;
1181638Srgrimes	}
1191638Srgrimes	if (new > old) {
1201638Srgrimes		if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
1211638Srgrimes			if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
12224861Sjkh			    (new - old) > lmemlim) {
12324861Sjkh				error = ENOMEM;
12424861Sjkh				goto done;
12524861Sjkh			}
1261638Srgrimes		}
12716663Sjkh		if (vm->vm_map.size + (new - old) > vmemlim) {
1281638Srgrimes			error = ENOMEM;
12924861Sjkh			goto done;
13024861Sjkh		}
13124861Sjkh#ifdef RACCT
1321638Srgrimes		PROC_LOCK(td->td_proc);
1331638Srgrimes		error = racct_set(td->td_proc, RACCT_DATA, new - base);
13424861Sjkh		if (error != 0) {
1351638Srgrimes			PROC_UNLOCK(td->td_proc);
1361638Srgrimes			error = ENOMEM;
1371638Srgrimes			goto done;
1381844Swollman		}
1391638Srgrimes		error = racct_set(td->td_proc, RACCT_VMEM,
14011136Swollman		    vm->vm_map.size + (new - old));
1411638Srgrimes		if (error != 0) {
1421844Swollman			racct_set_force(td->td_proc, RACCT_DATA, old - base);
1431844Swollman			PROC_UNLOCK(td->td_proc);
14416663Sjkh			error = ENOMEM;
145			goto done;
146		}
147		if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
148			error = racct_set(td->td_proc, RACCT_MEMLOCK,
149			    ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
150			    (new - old));
151			if (error != 0) {
152				racct_set_force(td->td_proc, RACCT_DATA,
153				    old - base);
154				racct_set_force(td->td_proc, RACCT_VMEM,
155				    vm->vm_map.size);
156				PROC_UNLOCK(td->td_proc);
157				error = ENOMEM;
158				goto done;
159			}
160		}
161		PROC_UNLOCK(td->td_proc);
162#endif
163		prot = VM_PROT_RW;
164#ifdef COMPAT_FREEBSD32
165#if defined(__amd64__) || defined(__ia64__)
166		if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32))
167			prot |= VM_PROT_EXECUTE;
168#endif
169#endif
170		rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new,
171		    prot, VM_PROT_ALL, 0);
172		if (rv != KERN_SUCCESS) {
173#ifdef RACCT
174			PROC_LOCK(td->td_proc);
175			racct_set_force(td->td_proc, RACCT_DATA, old - base);
176			racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
177			if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
178				racct_set_force(td->td_proc, RACCT_MEMLOCK,
179				    ptoa(vmspace_wired_count(
180				    td->td_proc->p_vmspace)));
181			}
182			PROC_UNLOCK(td->td_proc);
183#endif
184			error = ENOMEM;
185			goto done;
186		}
187		vm->vm_dsize += btoc(new - old);
188		/*
189		 * Handle the MAP_WIREFUTURE case for legacy applications,
190		 * by marking the newly mapped range of pages as wired.
191		 * We are not required to perform a corresponding
192		 * vm_map_unwire() before vm_map_delete() below, as
193		 * it will forcibly unwire the pages in the range.
194		 *
195		 * XXX If the pages cannot be wired, no error is returned.
196		 */
197		if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
198			if (bootverbose)
199				printf("obreak: MAP_WIREFUTURE set\n");
200			do_map_wirefuture = TRUE;
201		}
202	} else if (new < old) {
203		rv = vm_map_delete(&vm->vm_map, new, old);
204		if (rv != KERN_SUCCESS) {
205			error = ENOMEM;
206			goto done;
207		}
208		vm->vm_dsize -= btoc(old - new);
209#ifdef RACCT
210		PROC_LOCK(td->td_proc);
211		racct_set_force(td->td_proc, RACCT_DATA, new - base);
212		racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
213		if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
214			racct_set_force(td->td_proc, RACCT_MEMLOCK,
215			    ptoa(vmspace_wired_count(td->td_proc->p_vmspace)));
216		}
217		PROC_UNLOCK(td->td_proc);
218#endif
219	}
220done:
221	vm_map_unlock(&vm->vm_map);
222
223	if (do_map_wirefuture)
224		(void) vm_map_wire(&vm->vm_map, old, new,
225		    VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
226
227	return (error);
228}
229
230#ifndef _SYS_SYSPROTO_H_
231struct ovadvise_args {
232	int anom;
233};
234#endif
235
236/*
237 * MPSAFE
238 */
239/* ARGSUSED */
240int
241sys_ovadvise(td, uap)
242	struct thread *td;
243	struct ovadvise_args *uap;
244{
245	/* START_GIANT_OPTIONAL */
246	/* END_GIANT_OPTIONAL */
247	return (EINVAL);
248}
249