| 1 | /*- |
| 2 | * SPDX-License-Identifier: (BSD-3-Clause AND MIT-CMU) |
| 3 | * |
| 4 | * Copyright (c) 1991, 1993 |
| 5 | *	The Regents of the University of California. All rights reserved. |
| 6 | * |
| 7 | * This code is derived from software contributed to Berkeley by |
| 8 | * The Mach Operating System project at Carnegie-Mellon University. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * 3. Neither the name of the University nor the names of its contributors |
| 19 | * may be used to endorse or promote products derived from this software |
| 20 | * without specific prior written permission. |
| 21 | * |
| 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 32 | * SUCH DAMAGE. |
| 33 | * |
| 34 | * |
| 35 | * Copyright (c) 1987, 1990 Carnegie-Mellon University. |
| 36 | * All rights reserved. |
| 37 | * |
| 38 | * Authors: Avadis Tevanian, Jr., Michael Wayne Young |
| 39 | * |
| 40 | * Permission to use, copy, modify and distribute this software and |
| 41 | * its documentation is hereby granted, provided that both the copyright |
| 42 | * notice and this permission notice appear in all copies of the |
| 43 | * software, derivative works or modified versions, and any portions |
| 44 | * thereof, and that both notices appear in supporting documentation. |
| 45 | * |
| 46 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
| 47 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND |
| 48 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
| 49 | * |
| 50 | * Carnegie Mellon requests users of this software to return to |
| 51 | * |
| 52 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
| 53 | * School of Computer Science |
| 54 | * Carnegie Mellon University |
| 55 | * Pittsburgh PA 15213-3890 |
| 56 | * |
| 57 | * any improvements or extensions that they make and grant Carnegie the |
| 58 | * rights to redistribute these changes. |
| 59 | */ |
| 60 | |
| 61 | /* |
| 62 | *	Virtual memory map module definitions. |
| 63 | */ |
| 64 | #ifndef	_VM_MAP_ |
| 65 | #define	_VM_MAP_ |
| 66 | |
| 67 | #include <sys/lock.h> |
| 68 | #include <sys/sx.h> |
| 69 | #include <sys/_mutex.h> |
| 70 | |
| 71 | /* |
| 72 | *	Types defined: |
| 73 | * |
| 74 | *	vm_map_t		the high-level address map data structure. |
| 75 | *	vm_map_entry_t		an entry in an address map. |
| 76 | */ |
| 77 | |
| 78 | typedef u_int vm_eflags_t; |
| 79 | |
| 80 | /* |
| 81 | *	Objects which live in maps may be either VM objects, or |
| 82 | *	another map (called a "sharing map") which denotes read-write |
| 83 | *	sharing with other maps. |
| 84 | */ |
| 85 | union vm_map_object { |
| 86 | 	struct vm_object *vm_object;	/* object object */ |
| 87 | 	struct vm_map *sub_map;		/* belongs to another map */ |
| 88 | }; |
| 89 | |
| 90 | /* |
| 91 | *	Address map entries consist of start and end addresses, |
| 92 | *	a VM object (or sharing map) and offset into that object, |
| 93 | *	and user-exported inheritance and protection information. |
| 94 | *	Also included is control information for virtual copy operations. |
| 95 | * |
| 96 | *	For stack gap map entries (MAP_ENTRY_GUARD | MAP_ENTRY_STACK_GAP), |
| 97 | *	the next_read member is reused as the stack_guard_page storage, and |
| 98 | *	offset is the stack protection. |
| 99 | */ |
| 100 | struct vm_map_entry { |
| 101 | 	struct vm_map_entry *left;	/* left child or previous entry */ |
| 102 | 	struct vm_map_entry *right;	/* right child or next entry */ |
| 103 | 	vm_offset_t start;		/* start address */ |
| 104 | 	vm_offset_t end;		/* end address */ |
| 105 | 	vm_offset_t next_read;		/* vaddr of the next sequential read */ |
| 106 | 	vm_size_t max_free;		/* max free space in subtree */ |
| 107 | 	union vm_map_object object;	/* object I point to */ |
| 108 | 	vm_ooffset_t offset;		/* offset into object */ |
| 109 | 	vm_eflags_t eflags;		/* map entry flags */ |
| 110 | 	vm_prot_t protection;		/* protection code */ |
| 111 | 	vm_prot_t max_protection;	/* maximum protection */ |
| 112 | 	vm_inherit_t inheritance;	/* inheritance */ |
| 113 | 	uint8_t read_ahead;		/* pages in the read-ahead window */ |
| 114 | 	int wired_count;		/* can be paged if = 0 */ |
| 115 | 	struct ucred *cred;		/* tmp storage for creator ref */ |
| 116 | 	struct thread *wiring_thread; |
| 117 | }; |
| 118 | |
| 119 | #define	MAP_ENTRY_NOSYNC		0x00000001 |
| 120 | #define	MAP_ENTRY_IS_SUB_MAP		0x00000002 |
| 121 | #define	MAP_ENTRY_COW			0x00000004 |
| 122 | #define	MAP_ENTRY_NEEDS_COPY		0x00000008 |
| 123 | #define	MAP_ENTRY_NOFAULT		0x00000010 |
| 124 | #define	MAP_ENTRY_USER_WIRED		0x00000020 |
| 125 | |
| 126 | #define	MAP_ENTRY_BEHAV_NORMAL		0x00000000	/* default behavior */ |
| 127 | #define	MAP_ENTRY_BEHAV_SEQUENTIAL	0x00000040	/* expect sequential |
| 128 | 							 access */ |
| 129 | #define	MAP_ENTRY_BEHAV_RANDOM		0x00000080	/* expect random |
| 130 | 							 access */ |
| 131 | #define	MAP_ENTRY_BEHAV_RESERVED	0x000000c0	/* future use */ |
| 132 | #define	MAP_ENTRY_BEHAV_MASK		0x000000c0 |
| 133 | #define	MAP_ENTRY_IN_TRANSITION		0x00000100	/* entry being |
| 134 | 							 changed */ |
| 135 | #define	MAP_ENTRY_NEEDS_WAKEUP		0x00000200	/* waiters in |
| 136 | 							 transition */ |
| 137 | #define	MAP_ENTRY_NOCOREDUMP		0x00000400	/* don't include in |
| 138 | 							 a core */ |
| 139 | #define	MAP_ENTRY_VN_EXEC		0x00000800	/* text vnode mapping */ |
| 140 | #define	MAP_ENTRY_GROWS_DOWN		0x00001000	/* top-down stacks */ |
| 141 | #define	MAP_ENTRY_UNUSED0		0x00002000 |
| 142 | |
| 143 | #define	MAP_ENTRY_WIRE_SKIPPED		0x00004000 |
| 144 | #define	MAP_ENTRY_WRITECNT		0x00008000	/* tracked writeable |
| 145 | 							 mapping */ |
| 146 | #define	MAP_ENTRY_GUARD			0x00010000 |
| 147 | #define	MAP_ENTRY_STACK_GAP		0x00020000 |
| 148 | #define	MAP_ENTRY_UNUSED1		0x00040000 |
| 149 | #define	MAP_ENTRY_HEADER		0x00080000 |
| 150 | |
| 151 | #define	MAP_ENTRY_SPLIT_BOUNDARY_MASK	0x00300000 |
| 152 | #define	MAP_ENTRY_SPLIT_BOUNDARY_SHIFT	20 |
| 153 | #define	MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry)			\ |
| 154 | 	(((entry)->eflags & MAP_ENTRY_SPLIT_BOUNDARY_MASK) >>	\ |
| 155 | 	 MAP_ENTRY_SPLIT_BOUNDARY_SHIFT) |
| 156 | |
| 157 | #ifdef	_KERNEL |
| 158 | static __inline u_char |
| 159 | vm_map_entry_behavior(vm_map_entry_t entry) |
| 160 | { |
| 161 | 	return (entry->eflags & MAP_ENTRY_BEHAV_MASK); |
| 162 | } |
| 163 | |
| 164 | static __inline int |
| 165 | vm_map_entry_user_wired_count(vm_map_entry_t entry) |
| 166 | { |
| 167 | 	if (entry->eflags & MAP_ENTRY_USER_WIRED) |
| 168 | 		return (1); |
| 169 | 	return (0); |
| 170 | } |
| 171 | |
| 172 | static __inline int |
| 173 | vm_map_entry_system_wired_count(vm_map_entry_t entry) |
| 174 | { |
| 175 | 	return (entry->wired_count - vm_map_entry_user_wired_count(entry)); |
| 176 | } |
| 177 | #endif	/* _KERNEL */ |
| 178 | |
| 179 | /* |
| 180 | *	A map is a set of map entries. These map entries are |
| 181 | *	organized as a threaded binary search tree. The tree is |
| 182 | *	ordered based upon the start and end addresses contained |
| 183 | *	within each map entry. The largest gap between an entry in a |
| 184 | *	subtree and one of its neighbors is saved in the max_free |
| 185 | *	field, and that field is updated when the tree is restructured. |
| 186 | * |
| 187 | *	Sleator and Tarjan's top-down splay algorithm is employed to |
| 188 | *	control height imbalance in the binary search tree. |
| 189 | * |
| 190 | *	The map's min offset value is stored in map->header.end, and |
| 191 | *	its max offset value is stored in map->header.start. These |
| 192 | *	values act as sentinels for any forward or backward address |
| 193 | *	scan of the list. The right and left fields of the map |
| 194 | *	header point to the first and list map entries. The map |
| 195 | *	header has a special value for the eflags field, |
| 196 | *	MAP_ENTRY_HEADER, that is set initially, is never changed, |
| 197 | *	and prevents an eflags match of the header with any other map |
| 198 | *	entry. |
| 199 | * |
| 200 | *	List of locks |
| 201 | *	(c)	const until freed |
| 202 | */ |
| 203 | struct vm_map { |
| 204 | 	struct vm_map_entry header;	/* List of entries */ |
| 205 | 	union { |
| 206 | 		struct sx lock;			/* Lock for map data */ |
| 207 | 		struct mtx system_mtx; |
| 208 | 	}; |
| 209 | 	int nentries;			/* Number of entries */ |
| 210 | 	vm_size_t size;			/* virtual size */ |
| 211 | 	u_int timestamp;		/* Version number */ |
| 212 | 	u_int flags;			/* flags for this vm_map */ |
| 213 | 	vm_map_entry_t root;		/* Root of a binary search tree */ |
| 214 | 	pmap_t pmap;			/* (c) Physical map */ |
| 215 | 	vm_offset_t anon_loc; |
| 216 | 	int busy; |
| 217 | #ifdef DIAGNOSTIC |
| 218 | 	int nupdates; |
| 219 | #endif |
| 220 | }; |
| 221 | |
| 222 | /* |
| 223 | * vm_map flags values |
| 224 | */ |
| 225 | #define	MAP_WIREFUTURE		0x00000001	/* wire all future pages */ |
| 226 | #define	MAP_BUSY_WAKEUP		0x00000002	/* thread(s) waiting on busy |
| 227 | 						 state */ |
| 228 | #define	MAP_IS_SUB_MAP		0x00000004	/* has parent */ |
| 229 | #define	MAP_ASLR		0x00000008	/* enabled ASLR */ |
| 230 | #define	MAP_ASLR_IGNSTART	0x00000010	/* ASLR ignores data segment */ |
| 231 | #define	MAP_REPLENISH		0x00000020	/* kmapent zone needs to be |
| 232 | 						 refilled */ |
| 233 | #define	MAP_WXORX		0x00000040	/* enforce W^X */ |
| 234 | #define	MAP_ASLR_STACK		0x00000080	/* stack location is |
| 235 | 						 randomized */ |
| 236 | #define	MAP_NEEDS_WAKEUP	0x40000000 |
| 237 | #define	MAP_SYSTEM_MAP		0x80000000 |
| 238 | |
| 239 | #ifdef	_KERNEL |
| 240 | #if defined(KLD_MODULE) && !defined(KLD_TIED) |
| 241 | #define	vm_map_max(map)		vm_map_max_KBI((map)) |
| 242 | #define	vm_map_min(map)		vm_map_min_KBI((map)) |
| 243 | #define	vm_map_pmap(map)	vm_map_pmap_KBI((map)) |
| 244 | #define	vm_map_range_valid(map, start, end)	\ |
| 245 | 	vm_map_range_valid_KBI((map), (start), (end)) |
| 246 | #else |
| 247 | static __inline vm_offset_t |
| 248 | vm_map_max(const struct vm_map *map) |
| 249 | { |
| 250 | |
| 251 | 	return (map->header.start); |
| 252 | } |
| 253 | |
| 254 | static __inline vm_offset_t |
| 255 | vm_map_min(const struct vm_map *map) |
| 256 | { |
| 257 | |
| 258 | 	return (map->header.end); |
| 259 | } |
| 260 | |
| 261 | static __inline pmap_t |
| 262 | vm_map_pmap(vm_map_t map) |
| 263 | { |
| 264 | 	return (map->pmap); |
| 265 | } |
| 266 | |
| 267 | static __inline void |
| 268 | vm_map_modflags(vm_map_t map, u_int set, u_int clear) |
| 269 | { |
| 270 | 	map->flags = (map->flags | set) & ~clear; |
| 271 | } |
| 272 | |
| 273 | static inline bool |
| 274 | vm_map_range_valid(vm_map_t map, vm_offset_t start, vm_offset_t end) |
| 275 | { |
| 276 | 	if (end < start) |
| 277 | 		return (false); |
| 278 | 	if (start < vm_map_min(map) || end > vm_map_max(map)) |
| 279 | 		return (false); |
| 280 | 	return (true); |
| 281 | } |
| 282 | |
| 283 | static inline bool |
| 284 | vm_map_is_system(vm_map_t map) |
| 285 | { |
| 286 | 	return ((map->flags & MAP_SYSTEM_MAP) != 0); |
| 287 | } |
| 288 | |
| 289 | #endif	/* KLD_MODULE */ |
| 290 | #endif	/* _KERNEL */ |
| 291 | |
| 292 | /* |
| 293 | * Shareable process virtual address space. |
| 294 | * |
| 295 | * List of locks |
| 296 | *	(c)	const until freed |
| 297 | */ |
| 298 | struct vmspace { |
| 299 | 	struct vm_map vm_map;	/* VM address map */ |
| 300 | 	struct shmmap_state *vm_shm;	/* SYS5 shared memory private data XXX */ |
| 301 | 	segsz_t vm_swrss;	/* resident set size before last swap */ |
| 302 | 	segsz_t vm_tsize;	/* text size (pages) XXX */ |
| 303 | 	segsz_t vm_dsize;	/* data size (pages) XXX */ |
| 304 | 	segsz_t vm_ssize;	/* stack size (pages) */ |
| 305 | 	caddr_t vm_taddr;	/* (c) user virtual address of text */ |
| 306 | 	caddr_t vm_daddr;	/* (c) user virtual address of data */ |
| 307 | 	caddr_t vm_maxsaddr;	/* user VA at max stack growth */ |
| 308 | 	vm_offset_t vm_stacktop; /* top of the stack, may not be page-aligned */ |
| 309 | 	vm_offset_t vm_shp_base; /* shared page address */ |
| 310 | 	u_int vm_refcnt;	/* number of references */ |
| 311 | 	/* |
| 312 | 	 * Keep the PMAP last, so that CPU-specific variations of that |
| 313 | 	 * structure on a single architecture don't result in offset |
| 314 | 	 * variations of the machine-independent fields in the vmspace. |
| 315 | 	 */ |
| 316 | 	struct pmap vm_pmap;	/* private physical map */ |
| 317 | }; |
| 318 | |
| 319 | #ifdef	_KERNEL |
| 320 | static __inline pmap_t |
| 321 | vmspace_pmap(struct vmspace *vmspace) |
| 322 | { |
| 323 | 	return &vmspace->vm_pmap; |
| 324 | } |
| 325 | #endif	/* _KERNEL */ |
| 326 | |
| 327 | #ifdef	_KERNEL |
| 328 | /* |
| 329 | *	Macros:		vm_map_lock, etc. |
| 330 | *	Function: |
| 331 | *		Perform locking on the data portion of a map. Note that |
| 332 | *		these macros mimic procedure calls returning void. The |
| 333 | *		semicolon is supplied by the user of these macros, not |
| 334 | *		by the macros themselves. The macros can safely be used |
| 335 | *		as unbraced elements in a higher level statement. |
| 336 | */ |
| 337 | |
| 338 | void _vm_map_lock(vm_map_t map, const char *file, int line); |
| 339 | void _vm_map_unlock(vm_map_t map, const char *file, int line); |
| 340 | int _vm_map_unlock_and_wait(vm_map_t map, int timo, const char *file, int line); |
| 341 | void _vm_map_lock_read(vm_map_t map, const char *file, int line); |
| 342 | void _vm_map_unlock_read(vm_map_t map, const char *file, int line); |
| 343 | int _vm_map_trylock(vm_map_t map, const char *file, int line); |
| 344 | int _vm_map_trylock_read(vm_map_t map, const char *file, int line); |
| 345 | int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line); |
| 346 | void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line); |
| 347 | int vm_map_locked(vm_map_t map); |
| 348 | void vm_map_wakeup(vm_map_t map); |
| 349 | void vm_map_busy(vm_map_t map); |
| 350 | void vm_map_unbusy(vm_map_t map); |
| 351 | void vm_map_wait_busy(vm_map_t map); |
| 352 | vm_offset_t vm_map_max_KBI(const struct vm_map *map); |
| 353 | vm_offset_t vm_map_min_KBI(const struct vm_map *map); |
| 354 | pmap_t vm_map_pmap_KBI(vm_map_t map); |
| 355 | bool vm_map_range_valid_KBI(vm_map_t map, vm_offset_t start, vm_offset_t end); |
| 356 | |
| 357 | #define	vm_map_lock(map)	_vm_map_lock(map, LOCK_FILE, LOCK_LINE) |
| 358 | #define	vm_map_unlock(map)	_vm_map_unlock(map, LOCK_FILE, LOCK_LINE) |
| 359 | #define	vm_map_unlock_and_wait(map, timo)	\ |
| 360 | 			_vm_map_unlock_and_wait(map, timo, LOCK_FILE, LOCK_LINE) |
| 361 | #define	vm_map_lock_read(map)	_vm_map_lock_read(map, LOCK_FILE, LOCK_LINE) |
| 362 | #define	vm_map_unlock_read(map)	_vm_map_unlock_read(map, LOCK_FILE, LOCK_LINE) |
| 363 | #define	vm_map_trylock(map)	_vm_map_trylock(map, LOCK_FILE, LOCK_LINE) |
| 364 | #define	vm_map_trylock_read(map)	\ |
| 365 | 			_vm_map_trylock_read(map, LOCK_FILE, LOCK_LINE) |
| 366 | #define	vm_map_lock_upgrade(map)	\ |
| 367 | 			_vm_map_lock_upgrade(map, LOCK_FILE, LOCK_LINE) |
| 368 | #define	vm_map_lock_downgrade(map)	\ |
| 369 | 			_vm_map_lock_downgrade(map, LOCK_FILE, LOCK_LINE) |
| 370 | |
| 371 | long vmspace_resident_count(struct vmspace *vmspace); |
| 372 | #endif	/* _KERNEL */ |
| 373 | |
| 374 | /* |
| 375 | * Copy-on-write flags for vm_map operations |
| 376 | */ |
| 377 | #define	MAP_INHERIT_SHARE	0x00000001 |
| 378 | #define	MAP_COPY_ON_WRITE	0x00000002 |
| 379 | #define	MAP_NOFAULT		0x00000004 |
| 380 | #define	MAP_PREFAULT		0x00000008 |
| 381 | #define	MAP_PREFAULT_PARTIAL	0x00000010 |
| 382 | #define	MAP_DISABLE_SYNCER	0x00000020 |
| 383 | #define	MAP_CHECK_EXCL		0x00000040 |
| 384 | #define	MAP_CREATE_GUARD	0x00000080 |
| 385 | #define	MAP_DISABLE_COREDUMP	0x00000100 |
| 386 | #define	MAP_PREFAULT_MADVISE	0x00000200 /* from (user) madvise request */ |
| 387 | #define	MAP_WRITECOUNT		0x00000400 |
| 388 | #define	MAP_REMAP		0x00000800 |
| 389 | #define	MAP_STACK_AREA		0x00001000 |
| 390 | #define	MAP_COW_UNUSED0		0x00002000 |
| 391 | #define	MAP_ACC_CHARGED		0x00004000 |
| 392 | #define	MAP_ACC_NO_CHARGE	0x00008000 |
| 393 | #define	MAP_COW_UNUSED1		0x00010000 |
| 394 | #define	MAP_CREATE_STACK_GAP	0x00020000 |
| 395 | #define	MAP_VN_EXEC		0x00040000 |
| 396 | #define	MAP_SPLIT_BOUNDARY_MASK	0x00180000 |
| 397 | #define	MAP_NO_HINT		0x00200000 |
| 398 | |
| 399 | #define	MAP_SPLIT_BOUNDARY_SHIFT 19 |
| 400 | |
| 401 | /* |
| 402 | * vm_fault option flags |
| 403 | */ |
| 404 | #define	VM_FAULT_NORMAL	0x00	/* Nothing special */ |
| 405 | #define	VM_FAULT_WIRE	0x01	/* Wire the mapped page */ |
| 406 | #define	VM_FAULT_DIRTY	0x02	/* Dirty the page; use w/VM_PROT_COPY */ |
| 407 | #define	VM_FAULT_NOFILL	0x04	/* Fail if the pager doesn't have a copy */ |
| 408 | |
| 409 | /* |
| 410 | * Initially, mappings are slightly sequential. The maximum window size must |
| 411 | * account for the map entry's "read_ahead" field being defined as an uint8_t. |
| 412 | */ |
| 413 | #define	VM_FAULT_READ_AHEAD_MIN		7 |
| 414 | #define	VM_FAULT_READ_AHEAD_INIT	15 |
| 415 | #define	VM_FAULT_READ_AHEAD_MAX		min(atop(maxphys) - 1, UINT8_MAX) |
| 416 | |
| 417 | /* |
| 418 | * The following "find_space" options are supported by vm_map_find(). |
| 419 | * |
| 420 | * For VMFS_ALIGNED_SPACE, the desired alignment is specified to |
| 421 | * the macro argument as log base 2 of the desired alignment. |
| 422 | */ |
| 423 | #define	VMFS_NO_SPACE		0	/* don't find; use the given range */ |
| 424 | #define	VMFS_ANY_SPACE		1	/* find a range with any alignment */ |
| 425 | #define	VMFS_OPTIMAL_SPACE	2	/* find a range with optimal alignment*/ |
| 426 | #define	VMFS_SUPER_SPACE	3	/* find a superpage-aligned range */ |
| 427 | #define	VMFS_ALIGNED_SPACE(x)	((x) << 8) /* find a range with fixed alignment */ |
| 428 | |
| 429 | /* |
| 430 | * vm_map_wire and vm_map_unwire option flags |
| 431 | */ |
| 432 | #define VM_MAP_WIRE_SYSTEM	0	/* wiring in a kernel map */ |
| 433 | #define VM_MAP_WIRE_USER	1	/* wiring in a user map */ |
| 434 | |
| 435 | #define VM_MAP_WIRE_NOHOLES	0	/* region must not have holes */ |
| 436 | #define VM_MAP_WIRE_HOLESOK	2	/* region may have holes */ |
| 437 | |
| 438 | #define VM_MAP_WIRE_WRITE	4	/* Validate writable. */ |
| 439 | |
| 440 | typedef int vm_map_entry_reader(void *token, vm_map_entry_t addr, |
| 441 | vm_map_entry_t dest); |
| 442 | |
| 443 | #ifndef _KERNEL |
| 444 | /* |
| 445 | * Find the successor of a map_entry, using a reader to dereference pointers. |
| 446 | * '*clone' is a copy of a vm_map entry. 'reader' is used to copy a map entry |
| 447 | * at some address into '*clone'. Change *clone to a copy of the next map |
| 448 | * entry, and return the address of that entry, or NULL if copying has failed. |
| 449 | * |
| 450 | * This function is made available to user-space code that needs to traverse |
| 451 | * map entries. |
| 452 | */ |
| 453 | static inline vm_map_entry_t |
| 454 | vm_map_entry_read_succ(void *token, struct vm_map_entry *const clone, |
| 455 | vm_map_entry_reader reader) |
| 456 | { |
| 457 | 	vm_map_entry_t after, backup; |
| 458 | 	vm_offset_t start; |
| 459 | |
| 460 | 	after = clone->right; |
| 461 | 	start = clone->start; |
| 462 | 	if (!reader(token, after, clone)) |
| 463 | 		return (NULL); |
| 464 | 	backup = clone->left; |
| 465 | 	if (!reader(token, backup, clone)) |
| 466 | 		return (NULL); |
| 467 | 	if (clone->start > start) { |
| 468 | 		do { |
| 469 | 			after = backup; |
| 470 | 			backup = clone->left; |
| 471 | 			if (!reader(token, backup, clone)) |
| 472 | 				return (NULL); |
| 473 | 		} while (clone->start != start); |
| 474 | 	} |
| 475 | 	if (!reader(token, after, clone)) |
| 476 | 		return (NULL); |
| 477 | 	return (after); |
| 478 | } |
| 479 | #endif				/* ! _KERNEL */ |
| 480 | |
| 481 | #ifdef _KERNEL |
| 482 | boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); |
| 483 | int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t); |
| 484 | int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, |
| 485 | vm_offset_t, int, vm_prot_t, vm_prot_t, int); |
| 486 | int vm_map_find_locked(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, |
| 487 | vm_size_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int); |
| 488 | int vm_map_find_min(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, |
| 489 | vm_size_t, vm_offset_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int); |
| 490 | int vm_map_find_aligned(vm_map_t map, vm_offset_t *addr, vm_size_t length, |
| 491 | vm_offset_t max_addr, vm_offset_t alignment); |
| 492 | int vm_map_fixed(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_size_t, |
| 493 | vm_prot_t, vm_prot_t, int); |
| 494 | vm_offset_t vm_map_findspace(vm_map_t, vm_offset_t, vm_size_t); |
| 495 | int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t); |
| 496 | void vm_map_init(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); |
| 497 | void vm_map_init_system(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); |
| 498 | int vm_map_insert (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_offset_t, vm_prot_t, vm_prot_t, int); |
| 499 | int vm_map_lookup (vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *, |
| 500 | vm_pindex_t *, vm_prot_t *, boolean_t *); |
| 501 | int vm_map_lookup_locked(vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *, |
| 502 | vm_pindex_t *, vm_prot_t *, boolean_t *); |
| 503 | void vm_map_lookup_done (vm_map_t, vm_map_entry_t); |
| 504 | boolean_t vm_map_lookup_entry (vm_map_t, vm_offset_t, vm_map_entry_t *); |
| 505 | |
| 506 | static inline vm_map_entry_t |
| 507 | vm_map_entry_first(vm_map_t map) |
| 508 | { |
| 509 | |
| 510 | 	return (map->header.right); |
| 511 | } |
| 512 | |
| 513 | static inline vm_map_entry_t |
| 514 | vm_map_entry_succ(vm_map_entry_t entry) |
| 515 | { |
| 516 | 	vm_map_entry_t after; |
| 517 | |
| 518 | 	after = entry->right; |
| 519 | 	if (after->left->start > entry->start) { |
| 520 | 		do |
| 521 | 			after = after->left; |
| 522 | 		while (after->left != entry); |
| 523 | 	} |
| 524 | 	return (after); |
| 525 | } |
| 526 | |
| 527 | #define VM_MAP_ENTRY_FOREACH(it, map)		\ |
| 528 | 	for ((it) = vm_map_entry_first(map);	\ |
| 529 | 	 (it) != &(map)->header;		\ |
| 530 | 	 (it) = vm_map_entry_succ(it)) |
| 531 | |
| 532 | #define	VM_MAP_PROTECT_SET_PROT		0x0001 |
| 533 | #define	VM_MAP_PROTECT_SET_MAXPROT	0x0002 |
| 534 | #define	VM_MAP_PROTECT_GROWSDOWN	0x0004 |
| 535 | |
| 536 | int vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end, |
| 537 | vm_prot_t new_prot, vm_prot_t new_maxprot, int flags); |
| 538 | int vm_map_remove (vm_map_t, vm_offset_t, vm_offset_t); |
| 539 | vm_map_entry_t vm_map_try_merge_entries(vm_map_t map, vm_map_entry_t prev, |
| 540 | vm_map_entry_t entry); |
| 541 | void vm_map_startup (void); |
| 542 | int vm_map_submap (vm_map_t, vm_offset_t, vm_offset_t, vm_map_t); |
| 543 | int vm_map_sync(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t); |
| 544 | int vm_map_madvise (vm_map_t, vm_offset_t, vm_offset_t, int); |
| 545 | int vm_map_stack (vm_map_t, vm_offset_t, vm_size_t, vm_prot_t, vm_prot_t, int); |
| 546 | int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, |
| 547 | int flags); |
| 548 | int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags); |
| 549 | int vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm_offset_t end, |
| 550 | int flags); |
| 551 | long vmspace_swap_count(struct vmspace *vmspace); |
| 552 | void vm_map_entry_set_vnode_text(vm_map_entry_t entry, bool add); |
| 553 | #endif				/* _KERNEL */ |
| 554 | #endif				/* _VM_MAP_ */ |