1 /* $OpenBSD: uvm_page.h,v 1.62 2016/09/16 02:35:42 dlg Exp $ */ 2 /* $NetBSD: uvm_page.h,v 1.19 2000/12/28 08:24:55 chs Exp $ */ 3 4 /* 5 * Copyright (c) 1997 Charles D. Cranor and Washington University. 6 * Copyright (c) 1991, 1993, The Regents of the University of California. 7 * 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * The Mach Operating System project at Carnegie-Mellon University. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)vm_page.h 7.3 (Berkeley) 4/21/91 38 * from: Id: uvm_page.h,v 1.1.2.6 1998/02/04 02:31:42 chuck Exp 39 * 40 * 41 * Copyright (c) 1987, 1990 Carnegie-Mellon University. 42 * All rights reserved. 43 * 44 * Permission to use, copy, modify and distribute this software and 45 * its documentation is hereby granted, provided that both the copyright 46 * notice and this permission notice appear in all copies of the 47 * software, derivative works or modified versions, and any portions 48 * thereof, and that both notices appear in supporting documentation. 49 * 50 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 51 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 52 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 53 * 54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 */ 64 65 #ifndef _UVM_UVM_PAGE_H_ 66 #define _UVM_UVM_PAGE_H_ 67 68 /* 69 * uvm_page.h 70 */ 71 72 /* 73 * Resident memory system definitions. 74 */ 75 76 /* 77 * Management of resident (logical) pages. 78 * 79 * A small structure is kept for each resident 80 * page, indexed by page number. Each structure 81 * contains a list used for manipulating pages, and 82 * a tree structure for in object/offset lookups 83 * 84 * In addition, the structure contains the object 85 * and offset to which this page belongs (for pageout), 86 * and sundry status bits. 87 * 88 * Fields in this structure are possibly locked by the lock on the page 89 * queues (P). 90 */ 91 92 TAILQ_HEAD(pglist, vm_page); 93 94 struct vm_page { 95 TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO 96 * queue or free list (P) */ 97 RBT_ENTRY(vm_page) objt; /* object tree */ 98 99 struct vm_anon *uanon; /* anon (P) */ 100 struct uvm_object *uobject; /* object (P) */ 101 voff_t offset; /* offset into object (P) */ 102 103 u_int pg_flags; /* object flags [P] */ 104 105 u_int pg_version; /* version count */ 106 u_int wire_count; /* wired down map refs [P] */ 107 108 paddr_t phys_addr; /* physical address of page */ 109 psize_t fpgsz; /* free page range size */ 110 111 struct vm_page_md mdpage; /* pmap-specific data */ 112 113 #if defined(UVM_PAGE_TRKOWN) 114 /* debugging fields to track page ownership */ 115 pid_t owner; /* proc that set PG_BUSY */ 116 char *owner_tag; /* why it was set busy */ 117 #endif 118 }; 119 120 /* 121 * These are the flags defined for vm_page. 122 * 123 * Note: PG_FILLED and PG_DIRTY are added for the filesystems. 124 */ 125 126 /* 127 * locking rules: 128 * PQ_ ==> lock by page queue lock 129 * PQ_FREE is locked by free queue lock and is mutex with all other PQs 130 * pg_flags may only be changed using the atomic operations. 131 * 132 * PG_ZERO is used to indicate that a page has been pre-zero'd. This flag 133 * is only set when the page is on no queues, and is cleared when the page 134 * is placed on the free list. 135 */ 136 137 #define PG_BUSY 0x00000001 /* page is locked */ 138 #define PG_WANTED 0x00000002 /* someone is waiting for page */ 139 #define PG_TABLED 0x00000004 /* page is in VP table */ 140 #define PG_CLEAN 0x00000008 /* page has not been modified */ 141 #define PG_CLEANCHK 0x00000010 /* clean bit has been checked */ 142 #define PG_RELEASED 0x00000020 /* page released while paging */ 143 #define PG_FAKE 0x00000040 /* page is not yet initialized */ 144 #define PG_RDONLY 0x00000080 /* page must be mapped read-only */ 145 #define PG_ZERO 0x00000100 /* page is pre-zero'd */ 146 #define PG_DEV 0x00000200 /* page is in device space, lay off */ 147 148 #define PG_PAGER1 0x00001000 /* pager-specific flag */ 149 #define PG_MASK 0x0000ffff 150 151 #define PQ_FREE 0x00010000 /* page is on free list */ 152 #define PQ_INACTIVE 0x00020000 /* page is in inactive list */ 153 #define PQ_ACTIVE 0x00040000 /* page is in active list */ 154 #define PQ_ANON 0x00100000 /* page is part of an anon, rather 155 than an uvm_object */ 156 #define PQ_AOBJ 0x00200000 /* page is part of an anonymous 157 uvm_object */ 158 #define PQ_SWAPBACKED (PQ_ANON|PQ_AOBJ) 159 #define PQ_ENCRYPT 0x00400000 /* page needs {en,de}cryption */ 160 #define PQ_MASK 0x00ff0000 161 162 #define PG_PMAP0 0x01000000 /* Used by some pmaps. */ 163 #define PG_PMAP1 0x02000000 /* Used by some pmaps. */ 164 #define PG_PMAP2 0x04000000 /* Used by some pmaps. */ 165 #define PG_PMAP3 0x08000000 /* Used by some pmaps. */ 166 #define PG_PMAP4 0x10000000 /* Used by some pmaps. */ 167 #define PG_PMAP5 0x20000000 /* Used by some pmaps. */ 168 #define PG_PMAPMASK 0x3f000000 169 170 /* 171 * physical memory layout structure 172 * 173 * MD vmparam.h must #define: 174 * VM_PHYSEG_MAX = max number of physical memory segments we support 175 * (if this is "1" then we revert to a "contig" case) 176 * VM_PHYSSEG_STRAT: memory sort/search options (for VM_PHYSEG_MAX > 1) 177 * - VM_PSTRAT_RANDOM: linear search (random order) 178 * - VM_PSTRAT_BSEARCH: binary search (sorted by address) 179 * - VM_PSTRAT_BIGFIRST: linear search (sorted by largest segment first) 180 * - others? 181 * XXXCDC: eventually we should purge all left-over global variables... 182 */ 183 #define VM_PSTRAT_RANDOM 1 184 #define VM_PSTRAT_BSEARCH 2 185 #define VM_PSTRAT_BIGFIRST 3 186 187 /* 188 * vm_physmemseg: describes one segment of physical memory 189 */ 190 struct vm_physseg { 191 paddr_t start; /* PF# of first page in segment */ 192 paddr_t end; /* (PF# of last page in segment) + 1 */ 193 paddr_t avail_start; /* PF# of first free page in segment */ 194 paddr_t avail_end; /* (PF# of last free page in segment) +1 */ 195 struct vm_page *pgs; /* vm_page structures (from start) */ 196 struct vm_page *lastpg; /* vm_page structure for end */ 197 }; 198 199 #ifdef _KERNEL 200 201 /* 202 * globals 203 */ 204 205 extern boolean_t vm_page_zero_enable; 206 207 /* 208 * physical memory config is stored in vm_physmem. 209 */ 210 211 extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; 212 extern int vm_nphysseg; 213 214 /* 215 * prototypes: the following prototypes define the interface to pages 216 */ 217 218 void uvm_page_init(vaddr_t *, vaddr_t *); 219 #if defined(UVM_PAGE_TRKOWN) 220 void uvm_page_own(struct vm_page *, char *); 221 #endif 222 #if !defined(PMAP_STEAL_MEMORY) 223 boolean_t uvm_page_physget(paddr_t *); 224 #endif 225 226 void uvm_pageactivate(struct vm_page *); 227 vaddr_t uvm_pageboot_alloc(vsize_t); 228 void uvm_pagecopy(struct vm_page *, struct vm_page *); 229 void uvm_pagedeactivate(struct vm_page *); 230 void uvm_pagefree(struct vm_page *); 231 void uvm_page_unbusy(struct vm_page **, int); 232 struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t); 233 void uvm_pageunwire(struct vm_page *); 234 void uvm_pagewait(struct vm_page *, int); 235 void uvm_pagewake(struct vm_page *); 236 void uvm_pagewire(struct vm_page *); 237 void uvm_pagezero(struct vm_page *); 238 void uvm_pagealloc_pg(struct vm_page *, struct uvm_object *, 239 voff_t, struct vm_anon *); 240 241 struct uvm_constraint_range; /* XXX move to uvm_extern.h? */ 242 psize_t uvm_pagecount(struct uvm_constraint_range*); 243 244 #if VM_PHYSSEG_MAX == 1 245 /* 246 * Inline functions for archs where function calls are expensive. 247 */ 248 /* 249 * vm_physseg_find: find vm_physseg structure that belongs to a PA 250 */ 251 static __inline int 252 vm_physseg_find(paddr_t pframe, int *offp) 253 { 254 /* 'contig' case */ 255 if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) { 256 if (offp) 257 *offp = pframe - vm_physmem[0].start; 258 return(0); 259 } 260 return(-1); 261 } 262 263 /* 264 * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages 265 * back from an I/O mapping (ugh!). used in some MD code as well. 266 */ 267 static __inline struct vm_page * 268 PHYS_TO_VM_PAGE(paddr_t pa) 269 { 270 paddr_t pf = atop(pa); 271 int off; 272 int psi; 273 274 psi = vm_physseg_find(pf, &off); 275 276 return ((psi == -1) ? NULL : &vm_physmem[psi].pgs[off]); 277 } 278 #else 279 /* if VM_PHYSSEG_MAX > 1 they're not inline, they're in uvm_page.c. */ 280 struct vm_page *PHYS_TO_VM_PAGE(paddr_t); 281 int vm_physseg_find(paddr_t, int *); 282 #endif 283 284 /* 285 * macros 286 */ 287 288 #define uvm_lock_pageq() mtx_enter(&uvm.pageqlock) 289 #define uvm_unlock_pageq() mtx_leave(&uvm.pageqlock) 290 #define uvm_lock_fpageq() mtx_enter(&uvm.fpageqlock) 291 #define uvm_unlock_fpageq() mtx_leave(&uvm.fpageqlock) 292 293 #define UVM_PAGEZERO_TARGET (uvmexp.free / 8) 294 295 #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) 296 297 #define VM_PAGE_IS_FREE(entry) ((entry)->pg_flags & PQ_FREE) 298 299 #define PADDR_IS_DMA_REACHABLE(paddr) \ 300 (dma_constraint.ucr_low <= paddr && dma_constraint.ucr_high > paddr) 301 302 #endif /* _KERNEL */ 303 304 #endif /* _UVM_UVM_PAGE_H_ */ 305