1 /* $OpenBSD: uvm_page.h,v 1.54 2014/07/11 16:35:40 jsg 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 #include <uvm/uvm_extern.h> 93 94 TAILQ_HEAD(pglist, vm_page); 95 96 struct vm_page { 97 TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO 98 * queue or free list (P) */ 99 RB_ENTRY(vm_page) objt; /* object tree */ 100 101 struct vm_anon *uanon; /* anon (P) */ 102 struct uvm_object *uobject; /* object (P) */ 103 voff_t offset; /* offset into object (P) */ 104 105 u_int pg_flags; /* object flags [P] */ 106 107 u_int pg_version; /* version count */ 108 u_int wire_count; /* wired down map refs [P] */ 109 110 u_int loan_count; /* number of active loans 111 * to read: [P] 112 * to modify: [P] */ 113 paddr_t phys_addr; /* physical address of page */ 114 psize_t fpgsz; /* free page range size */ 115 116 struct vm_page_md mdpage; /* pmap-specific data */ 117 118 #if defined(UVM_PAGE_TRKOWN) 119 /* debugging fields to track page ownership */ 120 pid_t owner; /* proc that set PG_BUSY */ 121 char *owner_tag; /* why it was set busy */ 122 #endif 123 }; 124 125 /* 126 * These are the flags defined for vm_page. 127 * 128 * Note: PG_FILLED and PG_DIRTY are added for the filesystems. 129 */ 130 131 /* 132 * locking rules: 133 * PQ_ ==> lock by page queue lock 134 * PQ_FREE is locked by free queue lock and is mutex with all other PQs 135 * pg_flags may only be changed using the atomic operations. 136 * 137 * PG_ZERO is used to indicate that a page has been pre-zero'd. This flag 138 * is only set when the page is on no queues, and is cleared when the page 139 * is placed on the free list. 140 */ 141 142 #define PG_BUSY 0x00000001 /* page is locked */ 143 #define PG_WANTED 0x00000002 /* someone is waiting for page */ 144 #define PG_TABLED 0x00000004 /* page is in VP table */ 145 #define PG_CLEAN 0x00000008 /* page has not been modified */ 146 #define PG_CLEANCHK 0x00000010 /* clean bit has been checked */ 147 #define PG_RELEASED 0x00000020 /* page released while paging */ 148 #define PG_FAKE 0x00000040 /* page is not yet initialized */ 149 #define PG_RDONLY 0x00000080 /* page must be mapped read-only */ 150 #define PG_ZERO 0x00000100 /* page is pre-zero'd */ 151 #define PG_DEV 0x00000200 /* page is in device space, lay off */ 152 153 #define PG_PAGER1 0x00001000 /* pager-specific flag */ 154 #define PG_MASK 0x0000ffff 155 156 #define PQ_FREE 0x00010000 /* page is on free list */ 157 #define PQ_INACTIVE 0x00020000 /* page is in inactive list */ 158 #define PQ_ACTIVE 0x00040000 /* page is in active list */ 159 #define PQ_ANON 0x00100000 /* page is part of an anon, rather 160 than an uvm_object */ 161 #define PQ_AOBJ 0x00200000 /* page is part of an anonymous 162 uvm_object */ 163 #define PQ_SWAPBACKED (PQ_ANON|PQ_AOBJ) 164 #define PQ_ENCRYPT 0x00400000 /* page needs {en,de}cryption */ 165 #define PQ_MASK 0x00ff0000 166 167 #define PG_PMAP0 0x01000000 /* Used by some pmaps. */ 168 #define PG_PMAP1 0x02000000 /* Used by some pmaps. */ 169 #define PG_PMAP2 0x04000000 /* Used by some pmaps. */ 170 #define PG_PMAP3 0x08000000 /* Used by some pmaps. */ 171 #define PG_PMAP4 0x10000000 /* Used by some pmaps. */ 172 #define PG_PMAP5 0x20000000 /* Used by some pmaps. */ 173 #define PG_PMAPMASK 0x3f000000 174 175 /* 176 * physical memory layout structure 177 * 178 * MD vmparam.h must #define: 179 * VM_PHYSEG_MAX = max number of physical memory segments we support 180 * (if this is "1" then we revert to a "contig" case) 181 * VM_PHYSSEG_STRAT: memory sort/search options (for VM_PHYSEG_MAX > 1) 182 * - VM_PSTRAT_RANDOM: linear search (random order) 183 * - VM_PSTRAT_BSEARCH: binary search (sorted by address) 184 * - VM_PSTRAT_BIGFIRST: linear search (sorted by largest segment first) 185 * - others? 186 * XXXCDC: eventually we should purge all left-over global variables... 187 */ 188 #define VM_PSTRAT_RANDOM 1 189 #define VM_PSTRAT_BSEARCH 2 190 #define VM_PSTRAT_BIGFIRST 3 191 192 /* 193 * vm_physmemseg: describes one segment of physical memory 194 */ 195 struct vm_physseg { 196 paddr_t start; /* PF# of first page in segment */ 197 paddr_t end; /* (PF# of last page in segment) + 1 */ 198 paddr_t avail_start; /* PF# of first free page in segment */ 199 paddr_t avail_end; /* (PF# of last free page in segment) +1 */ 200 struct vm_page *pgs; /* vm_page structures (from start) */ 201 struct vm_page *lastpg; /* vm_page structure for end */ 202 }; 203 204 #ifdef _KERNEL 205 206 /* 207 * globals 208 */ 209 210 extern boolean_t vm_page_zero_enable; 211 212 /* 213 * physical memory config is stored in vm_physmem. 214 */ 215 216 extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; 217 extern int vm_nphysseg; 218 219 /* 220 * prototypes: the following prototypes define the interface to pages 221 */ 222 223 void uvm_page_init(vaddr_t *, vaddr_t *); 224 #if defined(UVM_PAGE_TRKOWN) 225 void uvm_page_own(struct vm_page *, char *); 226 #endif 227 #if !defined(PMAP_STEAL_MEMORY) 228 boolean_t uvm_page_physget(paddr_t *); 229 #endif 230 void uvm_pageidlezero(void); 231 232 void uvm_pageactivate(struct vm_page *); 233 vaddr_t uvm_pageboot_alloc(vsize_t); 234 void uvm_pagecopy(struct vm_page *, struct vm_page *); 235 void uvm_pagedeactivate(struct vm_page *); 236 void uvm_pagefree(struct vm_page *); 237 void uvm_page_unbusy(struct vm_page **, int); 238 struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t); 239 void uvm_pageunwire(struct vm_page *); 240 void uvm_pagewait(struct vm_page *, int); 241 void uvm_pagewake(struct vm_page *); 242 void uvm_pagewire(struct vm_page *); 243 void uvm_pagezero(struct vm_page *); 244 void uvm_pagealloc_pg(struct vm_page *, struct uvm_object *, 245 voff_t, struct vm_anon *); 246 247 struct uvm_constraint_range; /* XXX move to uvm_extern.h? */ 248 psize_t uvm_pagecount(struct uvm_constraint_range*); 249 250 #if VM_PHYSSEG_MAX == 1 251 /* 252 * Inline functions for archs like the vax where function calls are expensive. 253 */ 254 /* 255 * vm_physseg_find: find vm_physseg structure that belongs to a PA 256 */ 257 static __inline int 258 vm_physseg_find(paddr_t pframe, int *offp) 259 { 260 /* 'contig' case */ 261 if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) { 262 if (offp) 263 *offp = pframe - vm_physmem[0].start; 264 return(0); 265 } 266 return(-1); 267 } 268 269 /* 270 * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages 271 * back from an I/O mapping (ugh!). used in some MD code as well. 272 */ 273 static __inline struct vm_page * 274 PHYS_TO_VM_PAGE(paddr_t pa) 275 { 276 paddr_t pf = atop(pa); 277 int off; 278 int psi; 279 280 psi = vm_physseg_find(pf, &off); 281 282 return ((psi == -1) ? NULL : &vm_physmem[psi].pgs[off]); 283 } 284 #else 285 /* if VM_PHYSSEG_MAX > 1 they're not inline, they're in uvm_page.c. */ 286 struct vm_page *PHYS_TO_VM_PAGE(paddr_t); 287 int vm_physseg_find(paddr_t, int *); 288 #endif 289 290 /* 291 * macros 292 */ 293 294 #define uvm_lock_pageq() /* lock */ 295 #define uvm_unlock_pageq() /* unlock */ 296 #define uvm_lock_fpageq() mtx_enter(&uvm.fpageqlock); 297 #define uvm_unlock_fpageq() mtx_leave(&uvm.fpageqlock); 298 299 #define UVM_PAGEZERO_TARGET (uvmexp.free) 300 301 #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) 302 303 #define VM_PAGE_IS_FREE(entry) ((entry)->pg_flags & PQ_FREE) 304 305 #define PADDR_IS_DMA_REACHABLE(paddr) \ 306 (dma_constraint.ucr_low <= paddr && dma_constraint.ucr_high > paddr) 307 308 #endif /* _KERNEL */ 309 310 #endif /* _UVM_UVM_PAGE_H_ */ 311