1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #ifndef _VM_SEG_H 40 #define _VM_SEG_H 41 42 #pragma ident "%Z%%M% %I% %E% SMI" 43 44 #include <sys/vnode.h> 45 #include <sys/avl.h> 46 #include <vm/seg_enum.h> 47 #include <vm/faultcode.h> 48 #include <vm/hat.h> 49 50 #ifdef __cplusplus 51 extern "C" { 52 #endif 53 54 /* 55 * VM - Segments. 56 */ 57 58 /* 59 * kstat statistics for segment advise 60 */ 61 typedef struct { 62 kstat_named_t MADV_FREE_hit; 63 kstat_named_t MADV_FREE_miss; 64 } segadvstat_t; 65 66 /* 67 * memory object ids 68 */ 69 typedef struct memid { u_longlong_t val[2]; } memid_t; 70 71 /* 72 * An address space contains a set of segments, managed by drivers. 73 * Drivers support mapped devices, sharing, copy-on-write, etc. 74 * 75 * The seg structure contains a lock to prevent races, the base virtual 76 * address and size of the segment, a back pointer to the containing 77 * address space, pointers to maintain an AVL tree of segments in the 78 * same address space, and procedure and data hooks for the driver. 79 * The AVL tree of segments for the address space is sorted by 80 * ascending base addresses and overlapping segments are not allowed. 81 * 82 * After a segment is created, faults may occur on pages of the segment. 83 * When a fault occurs, the fault handling code must get the desired 84 * object and set up the hardware translation to the object. For some 85 * objects, the fault handling code also implements copy-on-write. 86 * 87 * When the hat wants to unload a translation, it can call the unload 88 * routine which is responsible for processing reference and modify bits. 89 * 90 * Each segment is protected by it's containing address space lock. To 91 * access any field in the segment structure, the "as" must be locked. 92 * If a segment field is to be modified, the address space lock must be 93 * write locked. 94 */ 95 96 struct seg { 97 caddr_t s_base; /* base virtual address */ 98 size_t s_size; /* size in bytes */ 99 uint_t s_szc; /* max page size code */ 100 uint_t s_flags; /* flags for segment, see below */ 101 struct as *s_as; /* containing address space */ 102 avl_node_t s_tree; /* AVL tree links to segs in this as */ 103 struct seg_ops *s_ops; /* ops vector: see below */ 104 void *s_data; /* private data for instance */ 105 }; 106 107 #define S_PURGE (0x01) /* seg should be purged in as_gap() */ 108 109 struct seg_ops { 110 int (*dup)(struct seg *, struct seg *); 111 int (*unmap)(struct seg *, caddr_t, size_t); 112 void (*free)(struct seg *); 113 faultcode_t (*fault)(struct hat *, struct seg *, caddr_t, size_t, 114 enum fault_type, enum seg_rw); 115 faultcode_t (*faulta)(struct seg *, caddr_t); 116 int (*setprot)(struct seg *, caddr_t, size_t, uint_t); 117 int (*checkprot)(struct seg *, caddr_t, size_t, uint_t); 118 int (*kluster)(struct seg *, caddr_t, ssize_t); 119 size_t (*swapout)(struct seg *); 120 int (*sync)(struct seg *, caddr_t, size_t, int, uint_t); 121 size_t (*incore)(struct seg *, caddr_t, size_t, char *); 122 int (*lockop)(struct seg *, caddr_t, size_t, int, int, ulong_t *, 123 size_t); 124 int (*getprot)(struct seg *, caddr_t, size_t, uint_t *); 125 u_offset_t (*getoffset)(struct seg *, caddr_t); 126 int (*gettype)(struct seg *, caddr_t); 127 int (*getvp)(struct seg *, caddr_t, struct vnode **); 128 int (*advise)(struct seg *, caddr_t, size_t, uint_t); 129 void (*dump)(struct seg *); 130 int (*pagelock)(struct seg *, caddr_t, size_t, struct page ***, 131 enum lock_type, enum seg_rw); 132 int (*setpagesize)(struct seg *, caddr_t, size_t, uint_t); 133 int (*getmemid)(struct seg *, caddr_t, memid_t *); 134 struct lgrp_mem_policy_info *(*getpolicy)(struct seg *, caddr_t); 135 int (*capable)(struct seg *, segcapability_t); 136 }; 137 138 #ifdef _KERNEL 139 /* 140 * Generic segment operations 141 */ 142 extern void seg_init(void); 143 extern struct seg *seg_alloc(struct as *as, caddr_t base, size_t size); 144 extern int seg_attach(struct as *as, caddr_t base, size_t size, 145 struct seg *seg); 146 extern void seg_unmap(struct seg *seg); 147 extern void seg_free(struct seg *seg); 148 149 /* 150 * functions for pagelock cache support 151 */ 152 extern void seg_ppurge(struct seg *seg); 153 extern void seg_ppurge_seg(int (*callback)()); 154 extern void seg_pinactive(struct seg *seg, caddr_t addr, size_t len, 155 struct page **pp, enum seg_rw rw, int (*callback)()); 156 extern int seg_pinsert_check(struct seg *seg, size_t len, uint_t flags); 157 extern int seg_pinsert(struct seg *seg, caddr_t addr, size_t len, 158 struct page **pp, enum seg_rw rw, uint_t flags, 159 int (*callback)()); 160 extern struct page **seg_plookup(struct seg *seg, caddr_t addr, 161 size_t len, enum seg_rw rw); 162 extern void seg_pasync_thread(void); 163 extern void seg_preap(void); 164 extern int seg_p_disable(void); 165 extern void seg_p_enable(void); 166 167 extern int seg_preapahead; 168 extern segadvstat_t segadvstat; 169 /* 170 * Flags for pagelock cache support 171 */ 172 #define SEGP_ASYNC_FLUSH 0x1 /* flushed by async thread */ 173 #define SEGP_FORCE_WIRED 0x2 /* skip check against seg_pwindow */ 174 175 /* 176 * Return values for seg_pinsert and seg_pinsert_check functions. 177 */ 178 #define SEGP_SUCCESS 0 /* seg_pinsert() succeeded */ 179 #define SEGP_FAIL 1 /* seg_pinsert() failed */ 180 181 /* Page status bits for segop_incore */ 182 #define SEG_PAGE_INCORE 0x01 /* VA has a page backing it */ 183 #define SEG_PAGE_LOCKED 0x02 /* VA has a page that is locked */ 184 #define SEG_PAGE_HASCOW 0x04 /* VA has a page with a copy-on-write */ 185 #define SEG_PAGE_SOFTLOCK 0x08 /* VA has a page with softlock held */ 186 #define SEG_PAGE_VNODEBACKED 0x10 /* Segment is backed by a vnode */ 187 #define SEG_PAGE_ANON 0x20 /* VA has an anonymous page */ 188 #define SEG_PAGE_VNODE 0x40 /* VA has a vnode page backing it */ 189 190 #define SEGOP_DUP(s, n) (*(s)->s_ops->dup)((s), (n)) 191 #define SEGOP_UNMAP(s, a, l) (*(s)->s_ops->unmap)((s), (a), (l)) 192 #define SEGOP_FREE(s) (*(s)->s_ops->free)((s)) 193 #define SEGOP_FAULT(h, s, a, l, t, rw) \ 194 (*(s)->s_ops->fault)((h), (s), (a), (l), (t), (rw)) 195 #define SEGOP_FAULTA(s, a) (*(s)->s_ops->faulta)((s), (a)) 196 #define SEGOP_SETPROT(s, a, l, p) (*(s)->s_ops->setprot)((s), (a), (l), (p)) 197 #define SEGOP_CHECKPROT(s, a, l, p) (*(s)->s_ops->checkprot)((s), (a), (l), (p)) 198 #define SEGOP_KLUSTER(s, a, d) (*(s)->s_ops->kluster)((s), (a), (d)) 199 #define SEGOP_SWAPOUT(s) (*(s)->s_ops->swapout)((s)) 200 #define SEGOP_SYNC(s, a, l, atr, f) \ 201 (*(s)->s_ops->sync)((s), (a), (l), (atr), (f)) 202 #define SEGOP_INCORE(s, a, l, v) (*(s)->s_ops->incore)((s), (a), (l), (v)) 203 #define SEGOP_LOCKOP(s, a, l, atr, op, b, p) \ 204 (*(s)->s_ops->lockop)((s), (a), (l), (atr), (op), (b), (p)) 205 #define SEGOP_GETPROT(s, a, l, p) (*(s)->s_ops->getprot)((s), (a), (l), (p)) 206 #define SEGOP_GETOFFSET(s, a) (*(s)->s_ops->getoffset)((s), (a)) 207 #define SEGOP_GETTYPE(s, a) (*(s)->s_ops->gettype)((s), (a)) 208 #define SEGOP_GETVP(s, a, vpp) (*(s)->s_ops->getvp)((s), (a), (vpp)) 209 #define SEGOP_ADVISE(s, a, l, b) (*(s)->s_ops->advise)((s), (a), (l), (b)) 210 #define SEGOP_DUMP(s) (*(s)->s_ops->dump)((s)) 211 #define SEGOP_PAGELOCK(s, a, l, p, t, rw) \ 212 (*(s)->s_ops->pagelock)((s), (a), (l), (p), (t), (rw)) 213 #define SEGOP_SETPAGESIZE(s, a, l, szc) \ 214 (*(s)->s_ops->setpagesize)((s), (a), (l), (szc)) 215 #define SEGOP_GETMEMID(s, a, mp) (*(s)->s_ops->getmemid)((s), (a), (mp)) 216 #define SEGOP_GETPOLICY(s, a) (*(s)->s_ops->getpolicy)((s), (a)) 217 #define SEGOP_CAPABLE(s, c) (*(s)->s_ops->capable)((s), (c)) 218 219 #define seg_page(seg, addr) \ 220 (((uintptr_t)((addr) - (seg)->s_base)) >> PAGESHIFT) 221 222 #define seg_pages(seg) \ 223 (((uintptr_t)((seg)->s_size + PAGEOFFSET)) >> PAGESHIFT) 224 225 #define IE_NOMEM -1 /* internal to seg layer */ 226 #define IE_RETRY -2 /* internal to seg layer */ 227 #define IE_REATTACH -3 /* internal to seg layer */ 228 229 /* Delay/retry factors for seg_p_mem_config_pre_del */ 230 #define SEGP_PREDEL_DELAY_FACTOR 4 231 /* 232 * As a workaround to being unable to purge the pagelock 233 * cache during a DR delete memory operation, we use 234 * a stall threshold that is twice the maximum seen 235 * during testing. This workaround will be removed 236 * when a suitable fix is found. 237 */ 238 #define SEGP_STALL_SECONDS 25 239 #define SEGP_STALL_THRESHOLD \ 240 (SEGP_STALL_SECONDS * SEGP_PREDEL_DELAY_FACTOR) 241 242 #ifdef VMDEBUG 243 244 uint_t seg_page(struct seg *, caddr_t); 245 uint_t seg_pages(struct seg *); 246 247 #endif /* VMDEBUG */ 248 249 boolean_t seg_can_change_zones(struct seg *); 250 size_t seg_swresv(struct seg *); 251 252 #endif /* _KERNEL */ 253 254 #ifdef __cplusplus 255 } 256 #endif 257 258 #endif /* _VM_SEG_H */ 259