4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright 2018 Joyent, Inc.
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
34 * University Copyright- Copyright (c) 1982, 1986, 1988
35 * The Regents of the University of California
38 * University Acknowledgment- Portions of this document are derived from
39 * software developed by the University of California, Berkeley, and its
46 #include <sys/watchpoint.h>
48 #include <vm/faultcode.h>
58 * VM - Address spaces.
62 * Each address space consists of a sorted list of segments
63 * and machine dependent address translation information.
65 * All the hard work is in the segment drivers and the
66 * hardware address translation code.
68 * The segment list is represented as an AVL tree.
70 * The address space lock (a_lock) is a long term lock which serializes
71 * access to certain operations (as_map, as_unmap) and protects the
72 * underlying generic segment data (seg.h) along with some fields in the
73 * address space structure as shown below:
75 * address space structure segment structure
84 * The address space contents lock (a_contents) is a short term
85 * lock that protects most of the data in the address space structure.
86 * This lock is always acquired after the "a_lock" in all situations
87 * except while dealing with AS_CLAIMGAP to avoid deadlocks.
89 * The following fields are protected by this lock:
91 * a_flags (AS_PAGLCK, AS_CLAIMGAP, etc.)
95 * The address space lock (a_lock) is always held prior to any segment
96 * operation. Some segment drivers use the address space lock to protect
97 * some or all of their segment private data, provided the version of
98 * "a_lock" (read vs. write) is consistent with the use of the data.
100 * The following fields are protected by the hat layer lock:
108 kmutex_t a_contents
; /* protect certain fields in the structure */
109 uchar_t a_flags
; /* as attributes */
110 uchar_t a_vbits
; /* used for collecting statistics */
111 kcondvar_t a_cv
; /* used by as_rangelock */
112 struct hat
*a_hat
; /* hat structure */
113 struct hrmstat
*a_hrm
; /* ref and mod bits */
114 caddr_t a_userlimit
; /* highest allowable address in this as */
115 struct seg
*a_seglast
; /* last segment hit on the addr space */
116 krwlock_t a_lock
; /* protects segment related fields */
117 size_t a_size
; /* total size of address space */
118 struct seg
*a_lastgap
; /* last seg found by as_gap() w/ AS_HI (mmap) */
119 struct seg
*a_lastgaphl
; /* last seg saved in as_gap() either for */
120 /* AS_HI or AS_LO used in as_addseg() */
121 avl_tree_t a_segtree
; /* segments in this address space. (AVL tree) */
122 avl_tree_t a_wpage
; /* watched pages (procfs) */
123 uchar_t a_updatedir
; /* mappings changed, rebuild a_objectdir */
124 timespec_t a_updatetime
; /* time when mappings last changed */
125 vnode_t
**a_objectdir
; /* object directory (procfs) */
126 size_t a_sizedir
; /* size of object directory */
127 struct as_callback
*a_callbacks
; /* callback list */
128 proc_t
*a_proc
; /* back pointer to proc */
129 size_t a_resvsize
; /* size of reserved part of address space */
132 #define AS_PAGLCK 0x80
133 #define AS_CLAIMGAP 0x40
134 #define AS_UNMAPWAIT 0x20
135 #define AS_NEEDSPURGE 0x10 /* mostly for seg_nf, see as_purge() */
136 #define AS_NOUNMAPWAIT 0x02
138 #define AS_ISPGLCK(as) ((as)->a_flags & AS_PAGLCK)
139 #define AS_ISCLAIMGAP(as) ((as)->a_flags & AS_CLAIMGAP)
140 #define AS_ISUNMAPWAIT(as) ((as)->a_flags & AS_UNMAPWAIT)
141 #define AS_ISNOUNMAPWAIT(as) ((as)->a_flags & AS_NOUNMAPWAIT)
143 #define AS_SETPGLCK(as) ((as)->a_flags |= AS_PAGLCK)
144 #define AS_SETCLAIMGAP(as) ((as)->a_flags |= AS_CLAIMGAP)
145 #define AS_SETUNMAPWAIT(as) ((as)->a_flags |= AS_UNMAPWAIT)
146 #define AS_SETNOUNMAPWAIT(as) ((as)->a_flags |= AS_NOUNMAPWAIT)
148 #define AS_CLRPGLCK(as) ((as)->a_flags &= ~AS_PAGLCK)
149 #define AS_CLRCLAIMGAP(as) ((as)->a_flags &= ~AS_CLAIMGAP)
150 #define AS_CLRUNMAPWAIT(as) ((as)->a_flags &= ~AS_UNMAPWAIT)
151 #define AS_CLRNOUNMAPWAIT(as) ((as)->a_flags &= ~AS_NOUNMAPWAIT)
153 #define AS_TYPE_64BIT(as) \
154 (((as)->a_userlimit > (caddr_t)UINT32_MAX) ? 1 : 0)
157 * Flags for as_map/as_map_ansegs
159 #define AS_MAP_NO_LPOOB ((uint_t)-1)
160 #define AS_MAP_HEAP ((uint_t)-2)
161 #define AS_MAP_STACK ((uint_t)-3)
164 * The as_callback is the basic structure which supports the ability to
165 * inform clients of specific events pertaining to address space management.
166 * A user calls as_add_callback to register an address space callback
167 * for a range of pages, specifying the events that need to occur.
168 * When as_do_callbacks is called and finds a 'matching' entry, the
169 * callback is called once, and the callback function MUST call
170 * as_delete_callback when all callback activities are complete.
171 * The thread calling as_do_callbacks blocks until the as_delete_callback
172 * is called. This allows for asynchorous events to subside before the
173 * as_do_callbacks thread continues.
175 * An example of the need for this is a driver which has done long-term
176 * locking of memory. Address space management operations (events) such
177 * as as_free, as_umap, and as_setprot will block indefinitely until the
178 * pertinent memory is unlocked. The callback mechanism provides the
179 * way to inform the driver of the event so that the driver may do the
180 * necessary unlocking.
182 * The contents of this structure is protected by a_contents lock
184 typedef void (*callback_func_t
)(struct as
*, void *, uint_t
);
186 struct as_callback
*ascb_next
; /* list link */
187 uint_t ascb_events
; /* event types */
188 callback_func_t ascb_func
; /* callback function */
189 void *ascb_arg
; /* callback argument */
190 caddr_t ascb_saddr
; /* start address */
191 size_t ascb_len
; /* address range */
196 #define AS_FREE_EVENT 0x1
197 #define AS_SETPROT_EVENT 0x2
198 #define AS_UNMAP_EVENT 0x4
199 #define AS_CALLBACK_CALLED ((uint_t)(1U << (8 * sizeof (uint_t) - 1U)))
200 #define AS_UNMAPWAIT_EVENT \
201 (AS_FREE_EVENT | AS_SETPROT_EVENT | AS_UNMAP_EVENT)
202 #define AS_ALL_EVENT \
203 (AS_FREE_EVENT | AS_SETPROT_EVENT | AS_UNMAP_EVENT)
206 /* Return code values for as_callback_delete */
207 enum as_cbdelete_rc
{
209 AS_CALLBACK_NOTFOUND
,
210 AS_CALLBACK_DELETE_DEFERRED
218 #define AH_DIR 0x1 /* direction flag mask */
219 #define AH_LO 0x0 /* find lowest hole */
220 #define AH_HI 0x1 /* find highest hole */
221 #define AH_CONTAIN 0x2 /* hole must contain `addr' */
223 extern struct as kas
; /* kernel's address space */
226 * Macros for address space locking. Note that we use RW_READER_STARVEWRITER
227 * whenever we acquire the address space lock as reader to assure that it can
228 * be used without regard to lock order in conjunction with filesystem locks.
229 * This allows filesystems to safely induce user-level page faults with
230 * filesystem locks held while concurrently allowing filesystem entry points
231 * acquiring those same locks to be called with the address space lock held as
232 * reader. RW_READER_STARVEWRITER thus prevents reader/reader+RW_WRITE_WANTED
233 * deadlocks in the style of fop_write()+as_fault()/as_*()+fop_putpage() and
234 * fop_read()+as_fault()/as_*()+fop_getpage(). (See the Big Theory Statement
235 * in rwlock.c for more information on the semantics of and motivation behind
236 * RW_READER_STARVEWRITER.)
238 #define AS_LOCK_ENTER(as, type) rw_enter(&(as)->a_lock, \
239 (type) == RW_READER ? RW_READER_STARVEWRITER : (type))
240 #define AS_LOCK_EXIT(as) rw_exit(&(as)->a_lock)
241 #define AS_LOCK_DESTROY(as) rw_destroy(&(as)->a_lock)
242 #define AS_LOCK_TRYENTER(as, type) rw_tryenter(&(as)->a_lock, \
243 (type) == RW_READER ? RW_READER_STARVEWRITER : (type))
246 * Macros to test lock states.
248 #define AS_LOCK_HELD(as) RW_LOCK_HELD(&(as)->a_lock)
249 #define AS_READ_HELD(as) RW_READ_HELD(&(as)->a_lock)
250 #define AS_WRITE_HELD(as) RW_WRITE_HELD(&(as)->a_lock)
253 * macros to walk thru segment lists
255 #define AS_SEGFIRST(as) avl_first(&(as)->a_segtree)
256 #define AS_SEGNEXT(as, seg) AVL_NEXT(&(as)->a_segtree, (seg))
257 #define AS_SEGPREV(as, seg) AVL_PREV(&(as)->a_segtree, (seg))
259 typedef int (*segcreate_func_t
)(struct seg
**, void *);
262 void as_avlinit(struct as
*);
263 struct seg
*as_segat(struct as
*as
, caddr_t addr
);
264 void as_rangelock(struct as
*as
);
265 void as_rangeunlock(struct as
*as
);
266 struct as
*as_alloc();
267 void as_free(struct as
*as
);
268 int as_dup(struct as
*as
, struct proc
*forkedproc
);
269 struct seg
*as_findseg(struct as
*as
, caddr_t addr
, int tail
);
270 int as_addseg(struct as
*as
, struct seg
*newseg
);
271 struct seg
*as_removeseg(struct as
*as
, struct seg
*seg
);
272 faultcode_t
as_fault(struct hat
*hat
, struct as
*as
, caddr_t addr
, size_t size
,
273 enum fault_type type
, enum seg_rw rw
);
274 faultcode_t
as_faulta(struct as
*as
, caddr_t addr
, size_t size
);
275 int as_setprot(struct as
*as
, caddr_t addr
, size_t size
, uint_t prot
);
276 int as_checkprot(struct as
*as
, caddr_t addr
, size_t size
, uint_t prot
);
277 int as_unmap(struct as
*as
, caddr_t addr
, size_t size
);
278 int as_map(struct as
*as
, caddr_t addr
, size_t size
, segcreate_func_t crfp
,
280 int as_map_locked(struct as
*as
, caddr_t addr
, size_t size
,
281 segcreate_func_t crfp
, void *argsp
);
282 void as_purge(struct as
*as
);
283 int as_gap(struct as
*as
, size_t minlen
, caddr_t
*basep
, size_t *lenp
,
284 uint_t flags
, caddr_t addr
);
285 int as_gap_aligned(struct as
*as
, size_t minlen
, caddr_t
*basep
,
286 size_t *lenp
, uint_t flags
, caddr_t addr
, size_t align
,
287 size_t redzone
, size_t off
);
289 int as_memory(struct as
*as
, caddr_t
*basep
, size_t *lenp
);
290 int as_incore(struct as
*as
, caddr_t addr
, size_t size
, char *vec
,
292 int as_ctl(struct as
*as
, caddr_t addr
, size_t size
, int func
, int attr
,
293 uintptr_t arg
, ulong_t
*lock_map
, size_t pos
);
294 int as_pagelock(struct as
*as
, struct page
***ppp
, caddr_t addr
,
295 size_t size
, enum seg_rw rw
);
296 void as_pageunlock(struct as
*as
, struct page
**pp
, caddr_t addr
,
297 size_t size
, enum seg_rw rw
);
298 int as_setpagesize(struct as
*as
, caddr_t addr
, size_t size
, uint_t szc
,
300 int as_set_default_lpsize(struct as
*as
, caddr_t addr
, size_t size
);
301 void as_setwatch(struct as
*as
);
302 void as_clearwatch(struct as
*as
);
303 int as_getmemid(struct as
*, caddr_t
, memid_t
*);
305 int as_add_callback(struct as
*, void (*)(), void *, uint_t
,
306 caddr_t
, size_t, int);
307 uint_t
as_delete_callback(struct as
*, void *);
315 #endif /* _VM_AS_H */