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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2017 Joyent, Inc.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
43 #include <sys/vnode.h>
45 #include <vm/seg_enum.h>
46 #include <vm/faultcode.h>
60 * kstat statistics for segment advise
63 kstat_named_t MADV_FREE_hit
;
64 kstat_named_t MADV_FREE_miss
;
70 typedef struct memid
{ u_longlong_t val
[2]; } memid_t
;
73 * An address space contains a set of segments, managed by drivers.
74 * Drivers support mapped devices, sharing, copy-on-write, etc.
76 * The seg structure contains a lock to prevent races, the base virtual
77 * address and size of the segment, a back pointer to the containing
78 * address space, pointers to maintain an AVL tree of segments in the
79 * same address space, and procedure and data hooks for the driver.
80 * The AVL tree of segments for the address space is sorted by
81 * ascending base addresses and overlapping segments are not allowed.
83 * After a segment is created, faults may occur on pages of the segment.
84 * When a fault occurs, the fault handling code must get the desired
85 * object and set up the hardware translation to the object. For some
86 * objects, the fault handling code also implements copy-on-write.
88 * When the hat wants to unload a translation, it can call the unload
89 * routine which is responsible for processing reference and modify bits.
91 * Each segment is protected by it's containing address space lock. To
92 * access any field in the segment structure, the "as" must be locked.
93 * If a segment field is to be modified, the address space lock must be
97 typedef struct pcache_link
{
98 struct pcache_link
*p_lnext
;
99 struct pcache_link
*p_lprev
;
103 caddr_t s_base
; /* base virtual address */
104 size_t s_size
; /* size in bytes */
105 uint_t s_szc
; /* max page size code */
106 uint_t s_flags
; /* flags for segment, see below */
107 struct as
*s_as
; /* containing address space */
108 avl_node_t s_tree
; /* AVL tree links to segs in this as */
109 const struct seg_ops
*s_ops
; /* ops vector: see below */
110 void *s_data
; /* private data for instance */
111 kmutex_t s_pmtx
; /* protects seg's pcache list */
112 pcache_link_t s_phead
; /* head of seg's pcache list */
115 #define S_PURGE (0x01) /* seg should be purged in as_gap() */
116 #define S_HOLE (0x02) /* seg represents hole in AS */
119 int (*dup
)(struct seg
*, struct seg
*);
120 int (*unmap
)(struct seg
*, caddr_t
, size_t);
121 void (*free
)(struct seg
*);
122 faultcode_t (*fault
)(struct hat
*, struct seg
*, caddr_t
, size_t,
123 enum fault_type
, enum seg_rw
);
124 faultcode_t (*faulta
)(struct seg
*, caddr_t
);
125 int (*setprot
)(struct seg
*, caddr_t
, size_t, uint_t
);
126 int (*checkprot
)(struct seg
*, caddr_t
, size_t, uint_t
);
127 int (*kluster
)(struct seg
*, caddr_t
, ssize_t
);
128 int (*sync
)(struct seg
*, caddr_t
, size_t, int, uint_t
);
129 size_t (*incore
)(struct seg
*, caddr_t
, size_t, char *);
130 int (*lockop
)(struct seg
*, caddr_t
, size_t, int, int, ulong_t
*,
132 int (*getprot
)(struct seg
*, caddr_t
, size_t, uint_t
*);
133 uoff_t (*getoffset
)(struct seg
*, caddr_t
);
134 int (*gettype
)(struct seg
*, caddr_t
);
135 int (*getvp
)(struct seg
*, caddr_t
, struct vnode
**);
136 int (*advise
)(struct seg
*, caddr_t
, size_t, uint_t
);
137 void (*dump
)(struct seg
*);
138 int (*pagelock
)(struct seg
*, caddr_t
, size_t, struct page
***,
139 enum lock_type
, enum seg_rw
);
140 int (*setpagesize
)(struct seg
*, caddr_t
, size_t, uint_t
);
141 int (*getmemid
)(struct seg
*, caddr_t
, memid_t
*);
142 struct lgrp_mem_policy_info
*(*getpolicy
)(struct seg
*, caddr_t
);
143 int (*capable
)(struct seg
*, segcapability_t
);
144 int (*inherit
)(struct seg
*, caddr_t
, size_t, uint_t
);
150 * Generic segment operations
152 extern void seg_init(void);
153 extern struct seg
*seg_alloc(struct as
*as
, caddr_t base
, size_t size
);
154 extern int seg_attach(struct as
*as
, caddr_t base
, size_t size
,
156 extern void seg_unmap(struct seg
*seg
);
157 extern void seg_free(struct seg
*seg
);
160 * functions for pagelock cache support
162 typedef int (*seg_preclaim_cbfunc_t
)(void *, caddr_t
, size_t,
163 struct page
**, enum seg_rw
, int);
165 extern struct page
**seg_plookup(struct seg
*seg
, struct anon_map
*amp
,
166 caddr_t addr
, size_t len
, enum seg_rw rw
, uint_t flags
);
167 extern void seg_pinactive(struct seg
*seg
, struct anon_map
*amp
,
168 caddr_t addr
, size_t len
, struct page
**pp
, enum seg_rw rw
,
169 uint_t flags
, seg_preclaim_cbfunc_t callback
);
171 extern void seg_ppurge(struct seg
*seg
, struct anon_map
*amp
,
173 extern void seg_ppurge_wiredpp(struct page
**pp
);
175 extern int seg_pinsert_check(struct seg
*seg
, struct anon_map
*amp
,
176 caddr_t addr
, size_t len
, uint_t flags
);
177 extern int seg_pinsert(struct seg
*seg
, struct anon_map
*amp
,
178 caddr_t addr
, size_t len
, size_t wlen
, struct page
**pp
, enum seg_rw rw
,
179 uint_t flags
, seg_preclaim_cbfunc_t callback
);
181 extern void seg_pasync_thread(void);
182 extern void seg_preap(void);
183 extern int seg_p_disable(void);
184 extern void seg_p_enable(void);
186 extern segadvstat_t segadvstat
;
189 * Flags for pagelock cache support.
190 * Flags argument is passed as uint_t to pcache routines. upper 16 bits of
191 * the flags argument are reserved for alignment page shift when SEGP_PSHIFT
194 #define SEGP_FORCE_WIRED 0x1 /* skip check against seg_pwindow */
195 #define SEGP_AMP 0x2 /* anon map's pcache entry */
196 #define SEGP_PSHIFT 0x4 /* addr pgsz shift for hash function */
199 * Return values for seg_pinsert and seg_pinsert_check functions.
201 #define SEGP_SUCCESS 0 /* seg_pinsert() succeeded */
202 #define SEGP_FAIL 1 /* seg_pinsert() failed */
204 /* Page status bits for segop_incore */
205 #define SEG_PAGE_INCORE 0x01 /* VA has a page backing it */
206 #define SEG_PAGE_LOCKED 0x02 /* VA has a page that is locked */
207 #define SEG_PAGE_HASCOW 0x04 /* VA has a page with a copy-on-write */
208 #define SEG_PAGE_SOFTLOCK 0x08 /* VA has a page with softlock held */
209 #define SEG_PAGE_VNODEBACKED 0x10 /* Segment is backed by a vnode */
210 #define SEG_PAGE_ANON 0x20 /* VA has an anonymous page */
211 #define SEG_PAGE_VNODE 0x40 /* VA has a vnode page backing it */
213 #define seg_page(seg, addr) \
214 (((uintptr_t)((addr) - (seg)->s_base)) >> PAGESHIFT)
216 #define seg_pages(seg) \
217 (((uintptr_t)((seg)->s_size + PAGEOFFSET)) >> PAGESHIFT)
219 #define IE_NOMEM -1 /* internal to seg layer */
220 #define IE_RETRY -2 /* internal to seg layer */
221 #define IE_REATTACH -3 /* internal to seg layer */
223 /* Values for segop_inherit */
224 #define SEGP_INH_ZERO 0x01
226 /* Delay/retry factors for seg_p_mem_config_pre_del */
227 #define SEGP_PREDEL_DELAY_FACTOR 4
229 * As a workaround to being unable to purge the pagelock
230 * cache during a DR delete memory operation, we use
231 * a stall threshold that is twice the maximum seen
232 * during testing. This workaround will be removed
233 * when a suitable fix is found.
235 #define SEGP_STALL_SECONDS 25
236 #define SEGP_STALL_THRESHOLD \
237 (SEGP_STALL_SECONDS * SEGP_PREDEL_DELAY_FACTOR)
241 uint_t
seg_page(struct seg
*, caddr_t
);
242 uint_t
seg_pages(struct seg
*);
246 boolean_t
seg_can_change_zones(struct seg
*);
247 size_t seg_swresv(struct seg
*);
250 extern int segop_dup(struct seg
*, struct seg
*);
251 extern int segop_unmap(struct seg
*, caddr_t
, size_t);
252 extern void segop_free(struct seg
*);
253 extern faultcode_t
segop_fault(struct hat
*, struct seg
*, caddr_t
, size_t,
254 enum fault_type
, enum seg_rw
);
255 extern faultcode_t
segop_faulta(struct seg
*, caddr_t
);
256 extern int segop_setprot(struct seg
*, caddr_t
, size_t, uint_t
);
257 extern int segop_checkprot(struct seg
*, caddr_t
, size_t, uint_t
);
258 extern int segop_kluster(struct seg
*, caddr_t
, ssize_t
);
259 extern int segop_sync(struct seg
*, caddr_t
, size_t, int, uint_t
);
260 extern size_t segop_incore(struct seg
*, caddr_t
, size_t, char *);
261 extern int segop_lockop(struct seg
*, caddr_t
, size_t, int, int, ulong_t
*,
263 extern int segop_getprot(struct seg
*, caddr_t
, size_t, uint_t
*);
264 extern uoff_t
segop_getoffset(struct seg
*, caddr_t
);
265 extern int segop_gettype(struct seg
*, caddr_t
);
266 extern int segop_getvp(struct seg
*, caddr_t
, struct vnode
**);
267 extern int segop_advise(struct seg
*, caddr_t
, size_t, uint_t
);
268 extern void segop_dump(struct seg
*);
269 extern int segop_pagelock(struct seg
*, caddr_t
, size_t, struct page
***,
270 enum lock_type
, enum seg_rw
);
271 extern int segop_setpagesize(struct seg
*, caddr_t
, size_t, uint_t
);
272 extern int segop_getmemid(struct seg
*, caddr_t
, memid_t
*);
273 extern struct lgrp_mem_policy_info
*segop_getpolicy(struct seg
*, caddr_t
);
274 extern int segop_capable(struct seg
*, segcapability_t
);
275 extern int segop_inherit(struct seg
*, caddr_t
, size_t, uint_t
);
283 #endif /* _VM_SEG_H */