1/* $OpenBSD: uvm_page.h,v 1.71 2024/05/13 01:15:53 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 92TAILQ_HEAD(pglist, vm_page); 93 94struct 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; /* thread 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_PHYSSEG_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_PHYSSEG_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 */ 190struct 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 * physical memory config is stored in vm_physmem. 203 */ 204 205extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; 206extern int vm_nphysseg; 207 208/* 209 * prototypes: the following prototypes define the interface to pages 210 */ 211 212void uvm_page_init(vaddr_t *, vaddr_t *); 213#if defined(UVM_PAGE_TRKOWN) 214void uvm_page_own(struct vm_page *, char *); 215#endif 216#if !defined(PMAP_STEAL_MEMORY) 217boolean_t uvm_page_physget(paddr_t *); 218#endif 219 220void uvm_pageactivate(struct vm_page *); 221void uvm_pagedequeue(struct vm_page *); 222vaddr_t uvm_pageboot_alloc(vsize_t); 223void uvm_pagecopy(struct vm_page *, struct vm_page *); 224void uvm_pagedeactivate(struct vm_page *); 225void uvm_pageclean(struct vm_page *); 226void uvm_pagefree(struct vm_page *); 227void uvm_page_unbusy(struct vm_page **, int); 228struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t); 229void uvm_pageunwire(struct vm_page *); 230void uvm_pagewait(struct vm_page *, struct rwlock *, const char *); 231void uvm_pagewire(struct vm_page *); 232void uvm_pagezero(struct vm_page *); 233void uvm_pagealloc_pg(struct vm_page *, struct uvm_object *, 234 voff_t, struct vm_anon *); 235 236struct uvm_constraint_range; /* XXX move to uvm_extern.h? */ 237psize_t uvm_pagecount(struct uvm_constraint_range*); 238 239#if VM_PHYSSEG_MAX == 1 240/* 241 * Inline functions for archs where function calls are expensive. 242 */ 243/* 244 * vm_physseg_find: find vm_physseg structure that belongs to a PA 245 */ 246static inline int 247vm_physseg_find(paddr_t pframe, int *offp) 248{ 249 /* 'contig' case */ 250 if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) { 251 if (offp) 252 *offp = pframe - vm_physmem[0].start; 253 return 0; 254 } 255 return -1; 256} 257 258/* 259 * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages 260 * back from an I/O mapping (ugh!). used in some MD code as well. 261 */ 262static inline struct vm_page * 263PHYS_TO_VM_PAGE(paddr_t pa) 264{ 265 paddr_t pf = atop(pa); 266 int off; 267 int psi; 268 269 psi = vm_physseg_find(pf, &off); 270 271 return ((psi == -1) ? NULL : &vm_physmem[psi].pgs[off]); 272} 273#else 274/* if VM_PHYSSEG_MAX > 1 they're not inline, they're in uvm_page.c. */ 275struct vm_page *PHYS_TO_VM_PAGE(paddr_t); 276int vm_physseg_find(paddr_t, int *); 277#endif 278 279/* 280 * macros 281 */ 282 283#define uvm_lock_pageq() mtx_enter(&uvm.pageqlock) 284#define uvm_unlock_pageq() mtx_leave(&uvm.pageqlock) 285#define uvm_lock_fpageq() mtx_enter(&uvm.fpageqlock) 286#define uvm_unlock_fpageq() mtx_leave(&uvm.fpageqlock) 287 288#define UVM_PAGEZERO_TARGET (uvmexp.free / 8) 289 290#define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) 291 292#define VM_PAGE_IS_FREE(entry) ((entry)->pg_flags & PQ_FREE) 293 294#define PADDR_IS_DMA_REACHABLE(paddr) \ 295 (dma_constraint.ucr_low <= paddr && dma_constraint.ucr_high > paddr) 296 297#endif /* _KERNEL */ 298 299#endif /* _UVM_UVM_PAGE_H_ */ 300