160727d8bSWarner Losh /*- 2796df753SPedro F. Giffuni * SPDX-License-Identifier: (BSD-3-Clause AND MIT-CMU) 351369649SPedro F. Giffuni * 4df8bae1dSRodney W. Grimes * Copyright (c) 1991, 1993 5df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 6df8bae1dSRodney W. Grimes * 7df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley by 8df8bae1dSRodney W. Grimes * The Mach Operating System project at Carnegie-Mellon University. 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 19df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 20df8bae1dSRodney W. Grimes * without specific prior written permission. 21df8bae1dSRodney W. Grimes * 22df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df8bae1dSRodney W. Grimes * SUCH DAMAGE. 33df8bae1dSRodney W. Grimes * 34df8bae1dSRodney W. Grimes * 35df8bae1dSRodney W. Grimes * Copyright (c) 1987, 1990 Carnegie-Mellon University. 36df8bae1dSRodney W. Grimes * All rights reserved. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * Authors: Avadis Tevanian, Jr., Michael Wayne Young 39df8bae1dSRodney W. Grimes * 40df8bae1dSRodney W. Grimes * Permission to use, copy, modify and distribute this software and 41df8bae1dSRodney W. Grimes * its documentation is hereby granted, provided that both the copyright 42df8bae1dSRodney W. Grimes * notice and this permission notice appear in all copies of the 43df8bae1dSRodney W. Grimes * software, derivative works or modified versions, and any portions 44df8bae1dSRodney W. Grimes * thereof, and that both notices appear in supporting documentation. 45df8bae1dSRodney W. Grimes * 46df8bae1dSRodney W. Grimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 47df8bae1dSRodney W. Grimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 48df8bae1dSRodney W. Grimes * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 49df8bae1dSRodney W. Grimes * 50df8bae1dSRodney W. Grimes * Carnegie Mellon requests users of this software to return to 51df8bae1dSRodney W. Grimes * 52df8bae1dSRodney W. Grimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 53df8bae1dSRodney W. Grimes * School of Computer Science 54df8bae1dSRodney W. Grimes * Carnegie Mellon University 55df8bae1dSRodney W. Grimes * Pittsburgh PA 15213-3890 56df8bae1dSRodney W. Grimes * 57df8bae1dSRodney W. Grimes * any improvements or extensions that they make and grant Carnegie the 58df8bae1dSRodney W. Grimes * rights to redistribute these changes. 59df8bae1dSRodney W. Grimes */ 60df8bae1dSRodney W. Grimes 61df8bae1dSRodney W. Grimes /* 62df8bae1dSRodney W. Grimes * Virtual memory map module definitions. 63df8bae1dSRodney W. Grimes */ 64df8bae1dSRodney W. Grimes #ifndef _VM_MAP_ 65df8bae1dSRodney W. Grimes #define _VM_MAP_ 66df8bae1dSRodney W. Grimes 67780b1c09SAlan Cox #include <sys/lock.h> 6812c64974SMaxime Henrion #include <sys/sx.h> 69ea0081b6SAlan Cox #include <sys/_mutex.h> 70559034b7SMark Murray 71df8bae1dSRodney W. Grimes /* 72df8bae1dSRodney W. Grimes * Types defined: 73df8bae1dSRodney W. Grimes * 74df8bae1dSRodney W. Grimes * vm_map_t the high-level address map data structure. 75df8bae1dSRodney W. Grimes * vm_map_entry_t an entry in an address map. 76df8bae1dSRodney W. Grimes */ 77df8bae1dSRodney W. Grimes 789730a5daSPaul Saab typedef u_int vm_eflags_t; 799730a5daSPaul Saab 80df8bae1dSRodney W. Grimes /* 81df8bae1dSRodney W. Grimes * Objects which live in maps may be either VM objects, or 82df8bae1dSRodney W. Grimes * another map (called a "sharing map") which denotes read-write 83df8bae1dSRodney W. Grimes * sharing with other maps. 84df8bae1dSRodney W. Grimes */ 85df8bae1dSRodney W. Grimes union vm_map_object { 86df8bae1dSRodney W. Grimes struct vm_object *vm_object; /* object object */ 87df8bae1dSRodney W. Grimes struct vm_map *sub_map; /* belongs to another map */ 88df8bae1dSRodney W. Grimes }; 89df8bae1dSRodney W. Grimes 90df8bae1dSRodney W. Grimes /* 91df8bae1dSRodney W. Grimes * Address map entries consist of start and end addresses, 92df8bae1dSRodney W. Grimes * a VM object (or sharing map) and offset into that object, 93df8bae1dSRodney W. Grimes * and user-exported inheritance and protection information. 94df8bae1dSRodney W. Grimes * Also included is control information for virtual copy operations. 9521e45c30SKonstantin Belousov * 9617e624caSKonstantin Belousov * For stack gap map entries (MAP_ENTRY_GUARD | MAP_ENTRY_STACK_GAP), 9717e624caSKonstantin Belousov * the next_read member is reused as the stack_guard_page storage, and 9817e624caSKonstantin Belousov * offset is the stack protection. 99df8bae1dSRodney W. Grimes */ 100df8bae1dSRodney W. Grimes struct vm_map_entry { 101c1ad5342SDoug Moore struct vm_map_entry *left; /* left child or previous entry */ 102c1ad5342SDoug Moore struct vm_map_entry *right; /* right child or next entry */ 103df8bae1dSRodney W. Grimes vm_offset_t start; /* start address */ 104df8bae1dSRodney W. Grimes vm_offset_t end; /* end address */ 105381b7242SAlan Cox vm_offset_t next_read; /* vaddr of the next sequential read */ 1060164e057SAlan Cox vm_size_t max_free; /* max free space in subtree */ 107df8bae1dSRodney W. Grimes union vm_map_object object; /* object I point to */ 108a316d390SJohn Dyson vm_ooffset_t offset; /* offset into object */ 1099730a5daSPaul Saab vm_eflags_t eflags; /* map entry flags */ 110df8bae1dSRodney W. Grimes vm_prot_t protection; /* protection code */ 111df8bae1dSRodney W. Grimes vm_prot_t max_protection; /* maximum protection */ 112df8bae1dSRodney W. Grimes vm_inherit_t inheritance; /* inheritance */ 11313458803SAlan Cox uint8_t read_ahead; /* pages in the read-ahead window */ 114df8bae1dSRodney W. Grimes int wired_count; /* can be paged if = 0 */ 115ef694c1aSEdward Tomasz Napierala struct ucred *cred; /* tmp storage for creator ref */ 1160acea7dfSKonstantin Belousov struct thread *wiring_thread; 117df8bae1dSRodney W. Grimes }; 118df8bae1dSRodney W. Grimes 119452a2db8SKonstantin Belousov #define MAP_ENTRY_NOSYNC 0x00000001 120452a2db8SKonstantin Belousov #define MAP_ENTRY_IS_SUB_MAP 0x00000002 121452a2db8SKonstantin Belousov #define MAP_ENTRY_COW 0x00000004 122452a2db8SKonstantin Belousov #define MAP_ENTRY_NEEDS_COPY 0x00000008 123452a2db8SKonstantin Belousov #define MAP_ENTRY_NOFAULT 0x00000010 124452a2db8SKonstantin Belousov #define MAP_ENTRY_USER_WIRED 0x00000020 125afa07f7eSJohn Dyson 126452a2db8SKonstantin Belousov #define MAP_ENTRY_BEHAV_NORMAL 0x00000000 /* default behavior */ 127452a2db8SKonstantin Belousov #define MAP_ENTRY_BEHAV_SEQUENTIAL 0x00000040 /* expect sequential 128452a2db8SKonstantin Belousov access */ 129452a2db8SKonstantin Belousov #define MAP_ENTRY_BEHAV_RANDOM 0x00000080 /* expect random 130452a2db8SKonstantin Belousov access */ 131452a2db8SKonstantin Belousov #define MAP_ENTRY_BEHAV_RESERVED 0x000000c0 /* future use */ 132452a2db8SKonstantin Belousov #define MAP_ENTRY_BEHAV_MASK 0x000000c0 133452a2db8SKonstantin Belousov #define MAP_ENTRY_IN_TRANSITION 0x00000100 /* entry being 134452a2db8SKonstantin Belousov changed */ 135452a2db8SKonstantin Belousov #define MAP_ENTRY_NEEDS_WAKEUP 0x00000200 /* waiters in 136452a2db8SKonstantin Belousov transition */ 137452a2db8SKonstantin Belousov #define MAP_ENTRY_NOCOREDUMP 0x00000400 /* don't include in 138452a2db8SKonstantin Belousov a core */ 139452a2db8SKonstantin Belousov #define MAP_ENTRY_VN_EXEC 0x00000800 /* text vnode mapping */ 140452a2db8SKonstantin Belousov #define MAP_ENTRY_GROWS_DOWN 0x00001000 /* top-down stacks */ 14117e624caSKonstantin Belousov #define MAP_ENTRY_UNUSED0 0x00002000 1427f866e4bSAlan Cox 143452a2db8SKonstantin Belousov #define MAP_ENTRY_WIRE_SKIPPED 0x00004000 144fe7bcbafSKyle Evans #define MAP_ENTRY_WRITECNT 0x00008000 /* tracked writeable 145452a2db8SKonstantin Belousov mapping */ 146452a2db8SKonstantin Belousov #define MAP_ENTRY_GUARD 0x00010000 14703046754SKonstantin Belousov #define MAP_ENTRY_STACK_GAP 0x00020000 14817e624caSKonstantin Belousov #define MAP_ENTRY_UNUSED1 0x00040000 149452a2db8SKonstantin Belousov #define MAP_ENTRY_HEADER 0x00080000 1506d7e8091SKonstantin Belousov 151e2e80fb3SKonstantin Belousov #define MAP_ENTRY_SPLIT_BOUNDARY_MASK 0x00300000 152e2e80fb3SKonstantin Belousov #define MAP_ENTRY_SPLIT_BOUNDARY_SHIFT 20 153d0e4e53eSMark Johnston #define MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry) \ 154d0e4e53eSMark Johnston (((entry)->eflags & MAP_ENTRY_SPLIT_BOUNDARY_MASK) >> \ 155d0e4e53eSMark Johnston MAP_ENTRY_SPLIT_BOUNDARY_SHIFT) 156e2e80fb3SKonstantin Belousov 157794316a8SAlan Cox #ifdef _KERNEL 158794316a8SAlan Cox static __inline u_char 159794316a8SAlan Cox vm_map_entry_behavior(vm_map_entry_t entry) 160794316a8SAlan Cox { 161794316a8SAlan Cox return (entry->eflags & MAP_ENTRY_BEHAV_MASK); 162794316a8SAlan Cox } 1639689d5e5SBrian Feldman 1649689d5e5SBrian Feldman static __inline int 1659689d5e5SBrian Feldman vm_map_entry_user_wired_count(vm_map_entry_t entry) 1669689d5e5SBrian Feldman { 1679689d5e5SBrian Feldman if (entry->eflags & MAP_ENTRY_USER_WIRED) 1689689d5e5SBrian Feldman return (1); 1699689d5e5SBrian Feldman return (0); 1709689d5e5SBrian Feldman } 1719689d5e5SBrian Feldman 1729689d5e5SBrian Feldman static __inline int 1739689d5e5SBrian Feldman vm_map_entry_system_wired_count(vm_map_entry_t entry) 1749689d5e5SBrian Feldman { 1759689d5e5SBrian Feldman return (entry->wired_count - vm_map_entry_user_wired_count(entry)); 1769689d5e5SBrian Feldman } 177794316a8SAlan Cox #endif /* _KERNEL */ 178794316a8SAlan Cox 179df8bae1dSRodney W. Grimes /* 180e94ce826SAlan Cox * A map is a set of map entries. These map entries are 1819da33e8dSKonstantin Belousov * organized as a threaded binary search tree. The tree is 1829da33e8dSKonstantin Belousov * ordered based upon the start and end addresses contained 183c1ad5342SDoug Moore * within each map entry. The largest gap between an entry in a 184c1ad5342SDoug Moore * subtree and one of its neighbors is saved in the max_free 1859da33e8dSKonstantin Belousov * field, and that field is updated when the tree is restructured. 186f0165b1cSKonstantin Belousov * 1871c5196c3SKonstantin Belousov * Sleator and Tarjan's top-down splay algorithm is employed to 1881c5196c3SKonstantin Belousov * control height imbalance in the binary search tree. 189b7d74299SAlan Cox * 1902203c46dSMark Johnston * The map's min offset value is stored in map->header.end, and 1912203c46dSMark Johnston * its max offset value is stored in map->header.start. These 1922203c46dSMark Johnston * values act as sentinels for any forward or backward address 193c1ad5342SDoug Moore * scan of the list. The right and left fields of the map 194c1ad5342SDoug Moore * header point to the first and list map entries. The map 195c1ad5342SDoug Moore * header has a special value for the eflags field, 196c1ad5342SDoug Moore * MAP_ENTRY_HEADER, that is set initially, is never changed, 197c1ad5342SDoug Moore * and prevents an eflags match of the header with any other map 198c1ad5342SDoug Moore * entry. 1992203c46dSMark Johnston * 200089b0733SAlan Cox * List of locks 201089b0733SAlan Cox * (c) const until freed 202df8bae1dSRodney W. Grimes */ 203df8bae1dSRodney W. Grimes struct vm_map { 204df8bae1dSRodney W. Grimes struct vm_map_entry header; /* List of entries */ 2056ed68e6fSKonstantin Belousov union { 20612c64974SMaxime Henrion struct sx lock; /* Lock for map data */ 20736daaecdSAlan Cox struct mtx system_mtx; 2086ed68e6fSKonstantin Belousov }; 209df8bae1dSRodney W. Grimes int nentries; /* Number of entries */ 210df8bae1dSRodney W. Grimes vm_size_t size; /* virtual size */ 21146add125SAlan Cox u_int timestamp; /* Version number */ 212*d939fd2dSKonstantin Belousov u_int flags; /* flags for this vm_map */ 213e94ce826SAlan Cox vm_map_entry_t root; /* Root of a binary search tree */ 214089b0733SAlan Cox pmap_t pmap; /* (c) Physical map */ 215fa50a355SKonstantin Belousov vm_offset_t anon_loc; 216a5db445dSMax Laier int busy; 217461587dcSDoug Moore #ifdef DIAGNOSTIC 218461587dcSDoug Moore int nupdates; 219461587dcSDoug Moore #endif 220df8bae1dSRodney W. Grimes }; 221df8bae1dSRodney W. Grimes 222abd498aaSBruce M Simpson /* 223*d939fd2dSKonstantin Belousov * vm_map flags values 224abd498aaSBruce M Simpson */ 225b4431e95SKonstantin Belousov #define MAP_WIREFUTURE 0x00000001 /* wire all future pages */ 226b4431e95SKonstantin Belousov #define MAP_BUSY_WAKEUP 0x00000002 /* thread(s) waiting on busy 227b4431e95SKonstantin Belousov state */ 228b4431e95SKonstantin Belousov #define MAP_IS_SUB_MAP 0x00000004 /* has parent */ 229b4431e95SKonstantin Belousov #define MAP_ASLR 0x00000008 /* enabled ASLR */ 230b4431e95SKonstantin Belousov #define MAP_ASLR_IGNSTART 0x00000010 /* ASLR ignores data segment */ 231b4431e95SKonstantin Belousov #define MAP_REPLENISH 0x00000020 /* kmapent zone needs to be 232b4431e95SKonstantin Belousov refilled */ 233b4431e95SKonstantin Belousov #define MAP_WXORX 0x00000040 /* enforce W^X */ 234b4431e95SKonstantin Belousov #define MAP_ASLR_STACK 0x00000080 /* stack location is 235b4431e95SKonstantin Belousov randomized */ 236*d939fd2dSKonstantin Belousov #define MAP_NEEDS_WAKEUP 0x40000000 237*d939fd2dSKonstantin Belousov #define MAP_SYSTEM_MAP 0x80000000 238abd498aaSBruce M Simpson 239089b0733SAlan Cox #ifdef _KERNEL 240f4b36404SMatt Macy #if defined(KLD_MODULE) && !defined(KLD_TIED) 24119ea042eSKonstantin Belousov #define vm_map_max(map) vm_map_max_KBI((map)) 24219ea042eSKonstantin Belousov #define vm_map_min(map) vm_map_min_KBI((map)) 24319ea042eSKonstantin Belousov #define vm_map_pmap(map) vm_map_pmap_KBI((map)) 244a7752896SMark Johnston #define vm_map_range_valid(map, start, end) \ 245a7752896SMark Johnston vm_map_range_valid_KBI((map), (start), (end)) 24619ea042eSKonstantin Belousov #else 247089b0733SAlan Cox static __inline vm_offset_t 248f806cdcfSMatthew D Fleming vm_map_max(const struct vm_map *map) 249089b0733SAlan Cox { 250f0165b1cSKonstantin Belousov 251f0165b1cSKonstantin Belousov return (map->header.start); 252089b0733SAlan Cox } 253089b0733SAlan Cox 254089b0733SAlan Cox static __inline vm_offset_t 255f806cdcfSMatthew D Fleming vm_map_min(const struct vm_map *map) 256089b0733SAlan Cox { 257f0165b1cSKonstantin Belousov 258f0165b1cSKonstantin Belousov return (map->header.end); 259089b0733SAlan Cox } 260089b0733SAlan Cox 261089b0733SAlan Cox static __inline pmap_t 262089b0733SAlan Cox vm_map_pmap(vm_map_t map) 263089b0733SAlan Cox { 264089b0733SAlan Cox return (map->pmap); 265089b0733SAlan Cox } 266abd498aaSBruce M Simpson 267abd498aaSBruce M Simpson static __inline void 268*d939fd2dSKonstantin Belousov vm_map_modflags(vm_map_t map, u_int set, u_int clear) 269abd498aaSBruce M Simpson { 270abd498aaSBruce M Simpson map->flags = (map->flags | set) & ~clear; 271abd498aaSBruce M Simpson } 2720f1e6ec5SMark Johnston 2730f1e6ec5SMark Johnston static inline bool 2740f1e6ec5SMark Johnston vm_map_range_valid(vm_map_t map, vm_offset_t start, vm_offset_t end) 2750f1e6ec5SMark Johnston { 2760f1e6ec5SMark Johnston if (end < start) 2770f1e6ec5SMark Johnston return (false); 2780f1e6ec5SMark Johnston if (start < vm_map_min(map) || end > vm_map_max(map)) 2790f1e6ec5SMark Johnston return (false); 2800f1e6ec5SMark Johnston return (true); 2810f1e6ec5SMark Johnston } 2820f1e6ec5SMark Johnston 283c5b19cefSKonstantin Belousov static inline bool 284c5b19cefSKonstantin Belousov vm_map_is_system(vm_map_t map) 285c5b19cefSKonstantin Belousov { 286*d939fd2dSKonstantin Belousov return ((map->flags & MAP_SYSTEM_MAP) != 0); 287c5b19cefSKonstantin Belousov } 288c5b19cefSKonstantin Belousov 28919ea042eSKonstantin Belousov #endif /* KLD_MODULE */ 290089b0733SAlan Cox #endif /* _KERNEL */ 291089b0733SAlan Cox 292df8bae1dSRodney W. Grimes /* 293efeaf95aSDavid Greenman * Shareable process virtual address space. 294366838ddSAlan Cox * 295366838ddSAlan Cox * List of locks 296366838ddSAlan Cox * (c) const until freed 297efeaf95aSDavid Greenman */ 298efeaf95aSDavid Greenman struct vmspace { 299efeaf95aSDavid Greenman struct vm_map vm_map; /* VM address map */ 3008209f090SAlfred Perlstein struct shmmap_state *vm_shm; /* SYS5 shared memory private data XXX */ 301efeaf95aSDavid Greenman segsz_t vm_swrss; /* resident set size before last swap */ 302efeaf95aSDavid Greenman segsz_t vm_tsize; /* text size (pages) XXX */ 303efeaf95aSDavid Greenman segsz_t vm_dsize; /* data size (pages) XXX */ 304efeaf95aSDavid Greenman segsz_t vm_ssize; /* stack size (pages) */ 305366838ddSAlan Cox caddr_t vm_taddr; /* (c) user virtual address of text */ 306366838ddSAlan Cox caddr_t vm_daddr; /* (c) user virtual address of data */ 307efeaf95aSDavid Greenman caddr_t vm_maxsaddr; /* user VA at max stack growth */ 3081811c1e9SMark Johnston vm_offset_t vm_stacktop; /* top of the stack, may not be page-aligned */ 309361971fbSKornel Dulęba vm_offset_t vm_shp_base; /* shared page address */ 310f7db0c95SMark Johnston u_int vm_refcnt; /* number of references */ 3118775db6fSMarcel Moolenaar /* 3128775db6fSMarcel Moolenaar * Keep the PMAP last, so that CPU-specific variations of that 3138775db6fSMarcel Moolenaar * structure on a single architecture don't result in offset 3148775db6fSMarcel Moolenaar * variations of the machine-independent fields in the vmspace. 3158775db6fSMarcel Moolenaar */ 3168775db6fSMarcel Moolenaar struct pmap vm_pmap; /* private physical map */ 317efeaf95aSDavid Greenman }; 318efeaf95aSDavid Greenman 31923955314SAlfred Perlstein #ifdef _KERNEL 32061c075b6SAlan Cox static __inline pmap_t 32161c075b6SAlan Cox vmspace_pmap(struct vmspace *vmspace) 32261c075b6SAlan Cox { 32361c075b6SAlan Cox return &vmspace->vm_pmap; 32461c075b6SAlan Cox } 32561c075b6SAlan Cox #endif /* _KERNEL */ 32661c075b6SAlan Cox 32761c075b6SAlan Cox #ifdef _KERNEL 328df8bae1dSRodney W. Grimes /* 329df8bae1dSRodney W. Grimes * Macros: vm_map_lock, etc. 330df8bae1dSRodney W. Grimes * Function: 33155758214SAlan Cox * Perform locking on the data portion of a map. Note that 33255758214SAlan Cox * these macros mimic procedure calls returning void. The 33355758214SAlan Cox * semicolon is supplied by the user of these macros, not 33455758214SAlan Cox * by the macros themselves. The macros can safely be used 33555758214SAlan Cox * as unbraced elements in a higher level statement. 336df8bae1dSRodney W. Grimes */ 337df8bae1dSRodney W. Grimes 338780b1c09SAlan Cox void _vm_map_lock(vm_map_t map, const char *file, int line); 339780b1c09SAlan Cox void _vm_map_unlock(vm_map_t map, const char *file, int line); 3408304adaaSAlan Cox int _vm_map_unlock_and_wait(vm_map_t map, int timo, const char *file, int line); 341780b1c09SAlan Cox void _vm_map_lock_read(vm_map_t map, const char *file, int line); 342780b1c09SAlan Cox void _vm_map_unlock_read(vm_map_t map, const char *file, int line); 343780b1c09SAlan Cox int _vm_map_trylock(vm_map_t map, const char *file, int line); 34472d97679SDavid Schultz int _vm_map_trylock_read(vm_map_t map, const char *file, int line); 345780b1c09SAlan Cox int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line); 346780b1c09SAlan Cox void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line); 34705a8c414SAlan Cox int vm_map_locked(vm_map_t map); 3489688f931SAlan Cox void vm_map_wakeup(vm_map_t map); 349a5db445dSMax Laier void vm_map_busy(vm_map_t map); 350a5db445dSMax Laier void vm_map_unbusy(vm_map_t map); 351a5db445dSMax Laier void vm_map_wait_busy(vm_map_t map); 35219ea042eSKonstantin Belousov vm_offset_t vm_map_max_KBI(const struct vm_map *map); 35319ea042eSKonstantin Belousov vm_offset_t vm_map_min_KBI(const struct vm_map *map); 35419ea042eSKonstantin Belousov pmap_t vm_map_pmap_KBI(vm_map_t map); 355a7752896SMark Johnston bool vm_map_range_valid_KBI(vm_map_t map, vm_offset_t start, vm_offset_t end); 356780b1c09SAlan Cox 357780b1c09SAlan Cox #define vm_map_lock(map) _vm_map_lock(map, LOCK_FILE, LOCK_LINE) 358780b1c09SAlan Cox #define vm_map_unlock(map) _vm_map_unlock(map, LOCK_FILE, LOCK_LINE) 3598304adaaSAlan Cox #define vm_map_unlock_and_wait(map, timo) \ 3608304adaaSAlan Cox _vm_map_unlock_and_wait(map, timo, LOCK_FILE, LOCK_LINE) 361780b1c09SAlan Cox #define vm_map_lock_read(map) _vm_map_lock_read(map, LOCK_FILE, LOCK_LINE) 362780b1c09SAlan Cox #define vm_map_unlock_read(map) _vm_map_unlock_read(map, LOCK_FILE, LOCK_LINE) 363780b1c09SAlan Cox #define vm_map_trylock(map) _vm_map_trylock(map, LOCK_FILE, LOCK_LINE) 36472d97679SDavid Schultz #define vm_map_trylock_read(map) \ 36572d97679SDavid Schultz _vm_map_trylock_read(map, LOCK_FILE, LOCK_LINE) 366780b1c09SAlan Cox #define vm_map_lock_upgrade(map) \ 367780b1c09SAlan Cox _vm_map_lock_upgrade(map, LOCK_FILE, LOCK_LINE) 368780b1c09SAlan Cox #define vm_map_lock_downgrade(map) \ 369780b1c09SAlan Cox _vm_map_lock_downgrade(map, LOCK_FILE, LOCK_LINE) 37003e9c6c1SJohn Dyson 3711b40f8c0SMatthew Dillon long vmspace_resident_count(struct vmspace *vmspace); 37223955314SAlfred Perlstein #endif /* _KERNEL */ 373df8bae1dSRodney W. Grimes 374bd7e5f99SJohn Dyson /* 375bd7e5f99SJohn Dyson * Copy-on-write flags for vm_map operations 376bd7e5f99SJohn Dyson */ 377452a2db8SKonstantin Belousov #define MAP_INHERIT_SHARE 0x00000001 378452a2db8SKonstantin Belousov #define MAP_COPY_ON_WRITE 0x00000002 379452a2db8SKonstantin Belousov #define MAP_NOFAULT 0x00000004 380452a2db8SKonstantin Belousov #define MAP_PREFAULT 0x00000008 381452a2db8SKonstantin Belousov #define MAP_PREFAULT_PARTIAL 0x00000010 382452a2db8SKonstantin Belousov #define MAP_DISABLE_SYNCER 0x00000020 383452a2db8SKonstantin Belousov #define MAP_CHECK_EXCL 0x00000040 384452a2db8SKonstantin Belousov #define MAP_CREATE_GUARD 0x00000080 385452a2db8SKonstantin Belousov #define MAP_DISABLE_COREDUMP 0x00000100 386452a2db8SKonstantin Belousov #define MAP_PREFAULT_MADVISE 0x00000200 /* from (user) madvise request */ 387fe7bcbafSKyle Evans #define MAP_WRITECOUNT 0x00000400 388452a2db8SKonstantin Belousov #define MAP_REMAP 0x00000800 389d302c053SKonstantin Belousov #define MAP_STACK_AREA 0x00001000 39017e624caSKonstantin Belousov #define MAP_COW_UNUSED0 0x00002000 391452a2db8SKonstantin Belousov #define MAP_ACC_CHARGED 0x00004000 392452a2db8SKonstantin Belousov #define MAP_ACC_NO_CHARGE 0x00008000 39317e624caSKonstantin Belousov #define MAP_COW_UNUSED1 0x00010000 39403046754SKonstantin Belousov #define MAP_CREATE_STACK_GAP 0x00020000 395452a2db8SKonstantin Belousov #define MAP_VN_EXEC 0x00040000 396e2e80fb3SKonstantin Belousov #define MAP_SPLIT_BOUNDARY_MASK 0x00180000 397d8e6f494SAlan Cox #define MAP_NO_HINT 0x00200000 398e2e80fb3SKonstantin Belousov 399e2e80fb3SKonstantin Belousov #define MAP_SPLIT_BOUNDARY_SHIFT 19 400bd7e5f99SJohn Dyson 4017aaaa4fdSJohn Dyson /* 4027aaaa4fdSJohn Dyson * vm_fault option flags 4037aaaa4fdSJohn Dyson */ 404f31695ccSMark Johnston #define VM_FAULT_NORMAL 0x00 /* Nothing special */ 405f31695ccSMark Johnston #define VM_FAULT_WIRE 0x01 /* Wire the mapped page */ 406f31695ccSMark Johnston #define VM_FAULT_DIRTY 0x02 /* Dirty the page; use w/VM_PROT_COPY */ 407f31695ccSMark Johnston #define VM_FAULT_NOFILL 0x04 /* Fail if the pager doesn't have a copy */ 4087aaaa4fdSJohn Dyson 409abd498aaSBruce M Simpson /* 41013458803SAlan Cox * Initially, mappings are slightly sequential. The maximum window size must 41113458803SAlan Cox * account for the map entry's "read_ahead" field being defined as an uint8_t. 41213458803SAlan Cox */ 41313458803SAlan Cox #define VM_FAULT_READ_AHEAD_MIN 7 41413458803SAlan Cox #define VM_FAULT_READ_AHEAD_INIT 15 415cd853791SKonstantin Belousov #define VM_FAULT_READ_AHEAD_MAX min(atop(maxphys) - 1, UINT8_MAX) 41613458803SAlan Cox 41713458803SAlan Cox /* 4185aa60b6fSJohn Baldwin * The following "find_space" options are supported by vm_map_find(). 4195aa60b6fSJohn Baldwin * 4205aa60b6fSJohn Baldwin * For VMFS_ALIGNED_SPACE, the desired alignment is specified to 4215aa60b6fSJohn Baldwin * the macro argument as log base 2 of the desired alignment. 42226c538ffSAlan Cox */ 42326c538ffSAlan Cox #define VMFS_NO_SPACE 0 /* don't find; use the given range */ 42426c538ffSAlan Cox #define VMFS_ANY_SPACE 1 /* find a range with any alignment */ 425ff74a3faSJohn Baldwin #define VMFS_OPTIMAL_SPACE 2 /* find a range with optimal alignment*/ 4265aa60b6fSJohn Baldwin #define VMFS_SUPER_SPACE 3 /* find a superpage-aligned range */ 4275aa60b6fSJohn Baldwin #define VMFS_ALIGNED_SPACE(x) ((x) << 8) /* find a range with fixed alignment */ 42826c538ffSAlan Cox 42926c538ffSAlan Cox /* 430abd498aaSBruce M Simpson * vm_map_wire and vm_map_unwire option flags 431abd498aaSBruce M Simpson */ 432abd498aaSBruce M Simpson #define VM_MAP_WIRE_SYSTEM 0 /* wiring in a kernel map */ 433abd498aaSBruce M Simpson #define VM_MAP_WIRE_USER 1 /* wiring in a user map */ 434abd498aaSBruce M Simpson 435abd498aaSBruce M Simpson #define VM_MAP_WIRE_NOHOLES 0 /* region must not have holes */ 436abd498aaSBruce M Simpson #define VM_MAP_WIRE_HOLESOK 2 /* region may have holes */ 437abd498aaSBruce M Simpson 438e4cd31ddSJeff Roberson #define VM_MAP_WIRE_WRITE 4 /* Validate writable. */ 439e4cd31ddSJeff Roberson 4408b75b1adSDoug Moore typedef int vm_map_entry_reader(void *token, vm_map_entry_t addr, 4418b75b1adSDoug Moore vm_map_entry_t dest); 4428b75b1adSDoug Moore 4438b75b1adSDoug Moore #ifndef _KERNEL 4448b75b1adSDoug Moore /* 4458b75b1adSDoug Moore * Find the successor of a map_entry, using a reader to dereference pointers. 4468b75b1adSDoug Moore * '*clone' is a copy of a vm_map entry. 'reader' is used to copy a map entry 4478b75b1adSDoug Moore * at some address into '*clone'. Change *clone to a copy of the next map 4488b75b1adSDoug Moore * entry, and return the address of that entry, or NULL if copying has failed. 4498b75b1adSDoug Moore * 4508b75b1adSDoug Moore * This function is made available to user-space code that needs to traverse 4518b75b1adSDoug Moore * map entries. 4528b75b1adSDoug Moore */ 4538b75b1adSDoug Moore static inline vm_map_entry_t 4548b75b1adSDoug Moore vm_map_entry_read_succ(void *token, struct vm_map_entry *const clone, 4558b75b1adSDoug Moore vm_map_entry_reader reader) 4568b75b1adSDoug Moore { 4578b75b1adSDoug Moore vm_map_entry_t after, backup; 4588b75b1adSDoug Moore vm_offset_t start; 4598b75b1adSDoug Moore 4608b75b1adSDoug Moore after = clone->right; 4618b75b1adSDoug Moore start = clone->start; 4628b75b1adSDoug Moore if (!reader(token, after, clone)) 4638b75b1adSDoug Moore return (NULL); 4648b75b1adSDoug Moore backup = clone->left; 4658b75b1adSDoug Moore if (!reader(token, backup, clone)) 4668b75b1adSDoug Moore return (NULL); 4678b75b1adSDoug Moore if (clone->start > start) { 4688b75b1adSDoug Moore do { 4698b75b1adSDoug Moore after = backup; 4708b75b1adSDoug Moore backup = clone->left; 4718b75b1adSDoug Moore if (!reader(token, backup, clone)) 4728b75b1adSDoug Moore return (NULL); 4738b75b1adSDoug Moore } while (clone->start != start); 4748b75b1adSDoug Moore } 4758b75b1adSDoug Moore if (!reader(token, after, clone)) 4768b75b1adSDoug Moore return (NULL); 4778b75b1adSDoug Moore return (after); 4788b75b1adSDoug Moore } 4798b75b1adSDoug Moore #endif /* ! _KERNEL */ 4808b75b1adSDoug Moore 4817887f00dSDoug Moore #ifdef _KERNEL 4827887f00dSDoug Moore boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); 4837887f00dSDoug Moore int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t); 4847887f00dSDoug Moore int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, 4857887f00dSDoug Moore vm_offset_t, int, vm_prot_t, vm_prot_t, int); 4860ecbb28cSKonstantin Belousov int vm_map_find_locked(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, 4870ecbb28cSKonstantin Belousov vm_size_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int); 4887887f00dSDoug Moore int vm_map_find_min(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, 4897887f00dSDoug Moore vm_size_t, vm_offset_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int); 4907a9f2da3SKonstantin Belousov int vm_map_find_aligned(vm_map_t map, vm_offset_t *addr, vm_size_t length, 4917a9f2da3SKonstantin Belousov vm_offset_t max_addr, vm_offset_t alignment); 4927887f00dSDoug Moore int vm_map_fixed(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_size_t, 4937887f00dSDoug Moore vm_prot_t, vm_prot_t, int); 4947887f00dSDoug Moore vm_offset_t vm_map_findspace(vm_map_t, vm_offset_t, vm_size_t); 4957887f00dSDoug Moore int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t); 4967887f00dSDoug Moore void vm_map_init(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); 4976ed68e6fSKonstantin Belousov void vm_map_init_system(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); 4987887f00dSDoug Moore 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); 4997887f00dSDoug Moore int vm_map_lookup (vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *, 5007887f00dSDoug Moore vm_pindex_t *, vm_prot_t *, boolean_t *); 5017887f00dSDoug Moore int vm_map_lookup_locked(vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *, 5027887f00dSDoug Moore vm_pindex_t *, vm_prot_t *, boolean_t *); 5037887f00dSDoug Moore void vm_map_lookup_done (vm_map_t, vm_map_entry_t); 5047887f00dSDoug Moore boolean_t vm_map_lookup_entry (vm_map_t, vm_offset_t, vm_map_entry_t *); 5057887f00dSDoug Moore 5067cdcf863SDoug Moore static inline vm_map_entry_t 50783704cc2SDoug Moore vm_map_entry_first(vm_map_t map) 50883704cc2SDoug Moore { 50983704cc2SDoug Moore 510c1ad5342SDoug Moore return (map->header.right); 51183704cc2SDoug Moore } 51283704cc2SDoug Moore 51383704cc2SDoug Moore static inline vm_map_entry_t 5147cdcf863SDoug Moore vm_map_entry_succ(vm_map_entry_t entry) 5157cdcf863SDoug Moore { 516c1ad5342SDoug Moore vm_map_entry_t after; 5177cdcf863SDoug Moore 518c1ad5342SDoug Moore after = entry->right; 519c1ad5342SDoug Moore if (after->left->start > entry->start) { 520c1ad5342SDoug Moore do 521c1ad5342SDoug Moore after = after->left; 522c1ad5342SDoug Moore while (after->left != entry); 523c1ad5342SDoug Moore } 524c1ad5342SDoug Moore return (after); 5257cdcf863SDoug Moore } 5267cdcf863SDoug Moore 5272288078cSDoug Moore #define VM_MAP_ENTRY_FOREACH(it, map) \ 52883704cc2SDoug Moore for ((it) = vm_map_entry_first(map); \ 5292288078cSDoug Moore (it) != &(map)->header; \ 5307cdcf863SDoug Moore (it) = vm_map_entry_succ(it)) 5310659df6fSKonstantin Belousov 5320659df6fSKonstantin Belousov #define VM_MAP_PROTECT_SET_PROT 0x0001 5330659df6fSKonstantin Belousov #define VM_MAP_PROTECT_SET_MAXPROT 0x0002 53490049eabSKonstantin Belousov #define VM_MAP_PROTECT_GROWSDOWN 0x0004 5350659df6fSKonstantin Belousov 5360659df6fSKonstantin Belousov int vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end, 5370659df6fSKonstantin Belousov vm_prot_t new_prot, vm_prot_t new_maxprot, int flags); 5381b40f8c0SMatthew Dillon int vm_map_remove (vm_map_t, vm_offset_t, vm_offset_t); 539ba41b0deSKonstantin Belousov vm_map_entry_t vm_map_try_merge_entries(vm_map_t map, vm_map_entry_t prev, 54083ea714fSDoug Moore vm_map_entry_t entry); 5411b40f8c0SMatthew Dillon void vm_map_startup (void); 5421b40f8c0SMatthew Dillon int vm_map_submap (vm_map_t, vm_offset_t, vm_offset_t, vm_map_t); 543950f8459SAlan Cox int vm_map_sync(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t); 5441b40f8c0SMatthew Dillon int vm_map_madvise (vm_map_t, vm_offset_t, vm_offset_t, int); 5451b40f8c0SMatthew Dillon int vm_map_stack (vm_map_t, vm_offset_t, vm_size_t, vm_prot_t, vm_prot_t, int); 546acd9a301SAlan Cox int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, 547abd498aaSBruce M Simpson int flags); 54854a3a114SMark Johnston int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags); 54954a3a114SMark Johnston int vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm_offset_t end, 550abd498aaSBruce M Simpson int flags); 5512860553aSRebecca Cran long vmspace_swap_count(struct vmspace *vmspace); 55278022527SKonstantin Belousov void vm_map_entry_set_vnode_text(vm_map_entry_t entry, bool add); 553a1287949SEivind Eklund #endif /* _KERNEL */ 554df8bae1dSRodney W. Grimes #endif /* _VM_MAP_ */ 555