1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1990 University of Utah. 3df8bae1dSRodney W. Grimes * Copyright (c) 1991, 1993 4df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 5df8bae1dSRodney W. Grimes * 6df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley by 7df8bae1dSRodney W. Grimes * the Systems Programming Group of the University of Utah Computer 8df8bae1dSRodney W. Grimes * Science Department. 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)device_pager.c 8.5 (Berkeley) 1/12/94 39df8bae1dSRodney W. Grimes */ 40df8bae1dSRodney W. Grimes 41df8bae1dSRodney W. Grimes /* 42df8bae1dSRodney W. Grimes * Page to/from special files. 43df8bae1dSRodney W. Grimes */ 44df8bae1dSRodney W. Grimes 45df8bae1dSRodney W. Grimes #include <sys/param.h> 46df8bae1dSRodney W. Grimes #include <sys/systm.h> 47df8bae1dSRodney W. Grimes #include <sys/conf.h> 48df8bae1dSRodney W. Grimes #include <sys/mman.h> 49df8bae1dSRodney W. Grimes #include <sys/malloc.h> 50df8bae1dSRodney W. Grimes 51df8bae1dSRodney W. Grimes #include <vm/vm.h> 52df8bae1dSRodney W. Grimes #include <vm/vm_kern.h> 53df8bae1dSRodney W. Grimes #include <vm/vm_page.h> 54df8bae1dSRodney W. Grimes #include <vm/device_pager.h> 55df8bae1dSRodney W. Grimes 56df8bae1dSRodney W. Grimes struct pagerlst dev_pager_list; /* list of managed devices */ 57df8bae1dSRodney W. Grimes struct pglist dev_pager_fakelist; /* list of available vm_page_t's */ 58df8bae1dSRodney W. Grimes 59df8bae1dSRodney W. Grimes #ifdef DEBUG 60df8bae1dSRodney W. Grimes int dpagerdebug = 0; 61df8bae1dSRodney W. Grimes #define DDB_FOLLOW 0x01 62df8bae1dSRodney W. Grimes #define DDB_INIT 0x02 63df8bae1dSRodney W. Grimes #define DDB_ALLOC 0x04 64df8bae1dSRodney W. Grimes #define DDB_FAIL 0x08 65df8bae1dSRodney W. Grimes #endif 66df8bae1dSRodney W. Grimes 67df8bae1dSRodney W. Grimes static vm_pager_t dev_pager_alloc 68df8bae1dSRodney W. Grimes __P((caddr_t, vm_size_t, vm_prot_t, vm_offset_t)); 69df8bae1dSRodney W. Grimes static void dev_pager_dealloc __P((vm_pager_t)); 70df8bae1dSRodney W. Grimes static int dev_pager_getpage 71df8bae1dSRodney W. Grimes __P((vm_pager_t, vm_page_t *, int, boolean_t)); 72df8bae1dSRodney W. Grimes static boolean_t dev_pager_haspage __P((vm_pager_t, vm_offset_t)); 73df8bae1dSRodney W. Grimes static void dev_pager_init __P((void)); 74df8bae1dSRodney W. Grimes static int dev_pager_putpage 75df8bae1dSRodney W. Grimes __P((vm_pager_t, vm_page_t *, int, boolean_t)); 76df8bae1dSRodney W. Grimes static vm_page_t dev_pager_getfake __P((vm_offset_t)); 77df8bae1dSRodney W. Grimes static void dev_pager_putfake __P((vm_page_t)); 78df8bae1dSRodney W. Grimes 79df8bae1dSRodney W. Grimes struct pagerops devicepagerops = { 80df8bae1dSRodney W. Grimes dev_pager_init, 81df8bae1dSRodney W. Grimes dev_pager_alloc, 82df8bae1dSRodney W. Grimes dev_pager_dealloc, 83df8bae1dSRodney W. Grimes dev_pager_getpage, 84df8bae1dSRodney W. Grimes dev_pager_putpage, 85df8bae1dSRodney W. Grimes dev_pager_haspage, 86df8bae1dSRodney W. Grimes vm_pager_clusternull 87df8bae1dSRodney W. Grimes }; 88df8bae1dSRodney W. Grimes 89df8bae1dSRodney W. Grimes static void 90df8bae1dSRodney W. Grimes dev_pager_init() 91df8bae1dSRodney W. Grimes { 92df8bae1dSRodney W. Grimes #ifdef DEBUG 93df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 94df8bae1dSRodney W. Grimes printf("dev_pager_init()\n"); 95df8bae1dSRodney W. Grimes #endif 96df8bae1dSRodney W. Grimes TAILQ_INIT(&dev_pager_list); 97df8bae1dSRodney W. Grimes TAILQ_INIT(&dev_pager_fakelist); 98df8bae1dSRodney W. Grimes } 99df8bae1dSRodney W. Grimes 100df8bae1dSRodney W. Grimes static vm_pager_t 101df8bae1dSRodney W. Grimes dev_pager_alloc(handle, size, prot, foff) 102df8bae1dSRodney W. Grimes caddr_t handle; 103df8bae1dSRodney W. Grimes vm_size_t size; 104df8bae1dSRodney W. Grimes vm_prot_t prot; 105df8bae1dSRodney W. Grimes vm_offset_t foff; 106df8bae1dSRodney W. Grimes { 107df8bae1dSRodney W. Grimes dev_t dev; 108df8bae1dSRodney W. Grimes vm_pager_t pager; 109df8bae1dSRodney W. Grimes int (*mapfunc)(); 110df8bae1dSRodney W. Grimes vm_object_t object; 111df8bae1dSRodney W. Grimes dev_pager_t devp; 112df8bae1dSRodney W. Grimes int npages, off; 113df8bae1dSRodney W. Grimes 114df8bae1dSRodney W. Grimes #ifdef DEBUG 115df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 116df8bae1dSRodney W. Grimes printf("dev_pager_alloc(%x, %x, %x, %x)\n", 117df8bae1dSRodney W. Grimes handle, size, prot, foff); 118df8bae1dSRodney W. Grimes #endif 119df8bae1dSRodney W. Grimes #ifdef DIAGNOSTIC 120df8bae1dSRodney W. Grimes /* 121df8bae1dSRodney W. Grimes * Pageout to device, should never happen. 122df8bae1dSRodney W. Grimes */ 123df8bae1dSRodney W. Grimes if (handle == NULL) 124df8bae1dSRodney W. Grimes panic("dev_pager_alloc called"); 125df8bae1dSRodney W. Grimes #endif 126df8bae1dSRodney W. Grimes 127df8bae1dSRodney W. Grimes /* 128df8bae1dSRodney W. Grimes * Make sure this device can be mapped. 129df8bae1dSRodney W. Grimes */ 130df8bae1dSRodney W. Grimes dev = (dev_t)handle; 131df8bae1dSRodney W. Grimes mapfunc = cdevsw[major(dev)].d_mmap; 132df8bae1dSRodney W. Grimes if (mapfunc == NULL || mapfunc == enodev || mapfunc == nullop) 133df8bae1dSRodney W. Grimes return(NULL); 134df8bae1dSRodney W. Grimes 135df8bae1dSRodney W. Grimes /* 136df8bae1dSRodney W. Grimes * Offset should be page aligned. 137df8bae1dSRodney W. Grimes */ 138df8bae1dSRodney W. Grimes if (foff & PAGE_MASK) 139df8bae1dSRodney W. Grimes return(NULL); 140df8bae1dSRodney W. Grimes 141df8bae1dSRodney W. Grimes /* 142df8bae1dSRodney W. Grimes * Check that the specified range of the device allows the 143df8bae1dSRodney W. Grimes * desired protection. 144df8bae1dSRodney W. Grimes * 145df8bae1dSRodney W. Grimes * XXX assumes VM_PROT_* == PROT_* 146df8bae1dSRodney W. Grimes */ 147df8bae1dSRodney W. Grimes npages = atop(round_page(size)); 148df8bae1dSRodney W. Grimes for (off = foff; npages--; off += PAGE_SIZE) 149df8bae1dSRodney W. Grimes if ((*mapfunc)(dev, off, (int)prot) == -1) 150df8bae1dSRodney W. Grimes return(NULL); 151df8bae1dSRodney W. Grimes 152df8bae1dSRodney W. Grimes /* 153df8bae1dSRodney W. Grimes * Look up pager, creating as necessary. 154df8bae1dSRodney W. Grimes */ 155df8bae1dSRodney W. Grimes top: 156df8bae1dSRodney W. Grimes pager = vm_pager_lookup(&dev_pager_list, handle); 157df8bae1dSRodney W. Grimes if (pager == NULL) { 158df8bae1dSRodney W. Grimes /* 159df8bae1dSRodney W. Grimes * Allocate and initialize pager structs 160df8bae1dSRodney W. Grimes */ 161df8bae1dSRodney W. Grimes pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, M_WAITOK); 162df8bae1dSRodney W. Grimes if (pager == NULL) 163df8bae1dSRodney W. Grimes return(NULL); 164df8bae1dSRodney W. Grimes devp = (dev_pager_t)malloc(sizeof *devp, M_VMPGDATA, M_WAITOK); 165df8bae1dSRodney W. Grimes if (devp == NULL) { 166df8bae1dSRodney W. Grimes free((caddr_t)pager, M_VMPAGER); 167df8bae1dSRodney W. Grimes return(NULL); 168df8bae1dSRodney W. Grimes } 169df8bae1dSRodney W. Grimes pager->pg_handle = handle; 170df8bae1dSRodney W. Grimes pager->pg_ops = &devicepagerops; 171df8bae1dSRodney W. Grimes pager->pg_type = PG_DEVICE; 172df8bae1dSRodney W. Grimes pager->pg_flags = 0; 173df8bae1dSRodney W. Grimes pager->pg_data = devp; 174df8bae1dSRodney W. Grimes TAILQ_INIT(&devp->devp_pglist); 175df8bae1dSRodney W. Grimes /* 176df8bae1dSRodney W. Grimes * Allocate object and associate it with the pager. 177df8bae1dSRodney W. Grimes */ 178df8bae1dSRodney W. Grimes object = devp->devp_object = vm_object_allocate(0); 179df8bae1dSRodney W. Grimes vm_object_enter(object, pager); 180df8bae1dSRodney W. Grimes vm_object_setpager(object, pager, (vm_offset_t)0, FALSE); 181df8bae1dSRodney W. Grimes /* 182df8bae1dSRodney W. Grimes * Finally, put it on the managed list so other can find it. 183df8bae1dSRodney W. Grimes * First we re-lookup in case someone else beat us to this 184df8bae1dSRodney W. Grimes * point (due to blocking in the various mallocs). If so, 185df8bae1dSRodney W. Grimes * we free everything and start over. 186df8bae1dSRodney W. Grimes */ 187df8bae1dSRodney W. Grimes if (vm_pager_lookup(&dev_pager_list, handle)) { 188df8bae1dSRodney W. Grimes free((caddr_t)devp, M_VMPGDATA); 189df8bae1dSRodney W. Grimes free((caddr_t)pager, M_VMPAGER); 190df8bae1dSRodney W. Grimes goto top; 191df8bae1dSRodney W. Grimes } 192df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&dev_pager_list, pager, pg_list); 193df8bae1dSRodney W. Grimes #ifdef DEBUG 194df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_ALLOC) { 195df8bae1dSRodney W. Grimes printf("dev_pager_alloc: pager %x devp %x object %x\n", 196df8bae1dSRodney W. Grimes pager, devp, object); 197df8bae1dSRodney W. Grimes vm_object_print(object, FALSE); 198df8bae1dSRodney W. Grimes } 199df8bae1dSRodney W. Grimes #endif 200df8bae1dSRodney W. Grimes } else { 201df8bae1dSRodney W. Grimes /* 202df8bae1dSRodney W. Grimes * vm_object_lookup() gains a reference and also 203df8bae1dSRodney W. Grimes * removes the object from the cache. 204df8bae1dSRodney W. Grimes */ 205df8bae1dSRodney W. Grimes object = vm_object_lookup(pager); 206df8bae1dSRodney W. Grimes #ifdef DIAGNOSTIC 207df8bae1dSRodney W. Grimes devp = (dev_pager_t)pager->pg_data; 208df8bae1dSRodney W. Grimes if (object != devp->devp_object) 209df8bae1dSRodney W. Grimes panic("dev_pager_setup: bad object"); 210df8bae1dSRodney W. Grimes #endif 211df8bae1dSRodney W. Grimes } 212df8bae1dSRodney W. Grimes return(pager); 213df8bae1dSRodney W. Grimes } 214df8bae1dSRodney W. Grimes 215df8bae1dSRodney W. Grimes static void 216df8bae1dSRodney W. Grimes dev_pager_dealloc(pager) 217df8bae1dSRodney W. Grimes vm_pager_t pager; 218df8bae1dSRodney W. Grimes { 219df8bae1dSRodney W. Grimes dev_pager_t devp; 220df8bae1dSRodney W. Grimes vm_object_t object; 221df8bae1dSRodney W. Grimes vm_page_t m; 222df8bae1dSRodney W. Grimes 223df8bae1dSRodney W. Grimes #ifdef DEBUG 224df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 225df8bae1dSRodney W. Grimes printf("dev_pager_dealloc(%x)\n", pager); 226df8bae1dSRodney W. Grimes #endif 227df8bae1dSRodney W. Grimes TAILQ_REMOVE(&dev_pager_list, pager, pg_list); 228df8bae1dSRodney W. Grimes /* 229df8bae1dSRodney W. Grimes * Get the object. 230df8bae1dSRodney W. Grimes * Note: cannot use vm_object_lookup since object has already 231df8bae1dSRodney W. Grimes * been removed from the hash chain. 232df8bae1dSRodney W. Grimes */ 233df8bae1dSRodney W. Grimes devp = (dev_pager_t)pager->pg_data; 234df8bae1dSRodney W. Grimes object = devp->devp_object; 235df8bae1dSRodney W. Grimes #ifdef DEBUG 236df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_ALLOC) 237df8bae1dSRodney W. Grimes printf("dev_pager_dealloc: devp %x object %x\n", devp, object); 238df8bae1dSRodney W. Grimes #endif 239df8bae1dSRodney W. Grimes /* 240df8bae1dSRodney W. Grimes * Free up our fake pages. 241df8bae1dSRodney W. Grimes */ 242df8bae1dSRodney W. Grimes while ((m = devp->devp_pglist.tqh_first) != NULL) { 243df8bae1dSRodney W. Grimes TAILQ_REMOVE(&devp->devp_pglist, m, pageq); 244df8bae1dSRodney W. Grimes dev_pager_putfake(m); 245df8bae1dSRodney W. Grimes } 246df8bae1dSRodney W. Grimes free((caddr_t)devp, M_VMPGDATA); 247df8bae1dSRodney W. Grimes free((caddr_t)pager, M_VMPAGER); 248df8bae1dSRodney W. Grimes } 249df8bae1dSRodney W. Grimes 250df8bae1dSRodney W. Grimes static int 251df8bae1dSRodney W. Grimes dev_pager_getpage(pager, mlist, npages, sync) 252df8bae1dSRodney W. Grimes vm_pager_t pager; 253df8bae1dSRodney W. Grimes vm_page_t *mlist; 254df8bae1dSRodney W. Grimes int npages; 255df8bae1dSRodney W. Grimes boolean_t sync; 256df8bae1dSRodney W. Grimes { 257df8bae1dSRodney W. Grimes register vm_object_t object; 258df8bae1dSRodney W. Grimes vm_offset_t offset, paddr; 259df8bae1dSRodney W. Grimes vm_page_t page; 260df8bae1dSRodney W. Grimes dev_t dev; 261df8bae1dSRodney W. Grimes int (*mapfunc)(), prot; 262df8bae1dSRodney W. Grimes vm_page_t m; 263df8bae1dSRodney W. Grimes 264df8bae1dSRodney W. Grimes #ifdef DEBUG 265df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 266df8bae1dSRodney W. Grimes printf("dev_pager_getpage(%x, %x, %x, %x)\n", 267df8bae1dSRodney W. Grimes pager, mlist, npages, sync); 268df8bae1dSRodney W. Grimes #endif 269df8bae1dSRodney W. Grimes 270df8bae1dSRodney W. Grimes if (npages != 1) 271df8bae1dSRodney W. Grimes panic("dev_pager_getpage: cannot handle multiple pages"); 272df8bae1dSRodney W. Grimes m = *mlist; 273df8bae1dSRodney W. Grimes 274df8bae1dSRodney W. Grimes object = m->object; 275df8bae1dSRodney W. Grimes dev = (dev_t)pager->pg_handle; 276df8bae1dSRodney W. Grimes offset = m->offset + object->paging_offset; 277df8bae1dSRodney W. Grimes prot = PROT_READ; /* XXX should pass in? */ 278df8bae1dSRodney W. Grimes mapfunc = cdevsw[major(dev)].d_mmap; 279df8bae1dSRodney W. Grimes #ifdef DIAGNOSTIC 280df8bae1dSRodney W. Grimes if (mapfunc == NULL || mapfunc == enodev || mapfunc == nullop) 281df8bae1dSRodney W. Grimes panic("dev_pager_getpage: no map function"); 282df8bae1dSRodney W. Grimes #endif 283df8bae1dSRodney W. Grimes paddr = pmap_phys_address((*mapfunc)(dev, (int)offset, prot)); 284df8bae1dSRodney W. Grimes #ifdef DIAGNOSTIC 285df8bae1dSRodney W. Grimes if (paddr == -1) 286df8bae1dSRodney W. Grimes panic("dev_pager_getpage: map function returns error"); 287df8bae1dSRodney W. Grimes #endif 288df8bae1dSRodney W. Grimes /* 289df8bae1dSRodney W. Grimes * Replace the passed in page with our own fake page and free 290df8bae1dSRodney W. Grimes * up the original. 291df8bae1dSRodney W. Grimes */ 292df8bae1dSRodney W. Grimes page = dev_pager_getfake(paddr); 293df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&((dev_pager_t)pager->pg_data)->devp_pglist, page, 294df8bae1dSRodney W. Grimes pageq); 295df8bae1dSRodney W. Grimes vm_object_lock(object); 296df8bae1dSRodney W. Grimes vm_page_lock_queues(); 297df8bae1dSRodney W. Grimes vm_page_free(m); 298df8bae1dSRodney W. Grimes vm_page_insert(page, object, offset); 299df8bae1dSRodney W. Grimes vm_page_unlock_queues(); 300df8bae1dSRodney W. Grimes PAGE_WAKEUP(m); 301df8bae1dSRodney W. Grimes if (offset + PAGE_SIZE > object->size) 302df8bae1dSRodney W. Grimes object->size = offset + PAGE_SIZE; /* XXX anal */ 303df8bae1dSRodney W. Grimes vm_object_unlock(object); 304df8bae1dSRodney W. Grimes 305df8bae1dSRodney W. Grimes return(VM_PAGER_OK); 306df8bae1dSRodney W. Grimes } 307df8bae1dSRodney W. Grimes 308df8bae1dSRodney W. Grimes static int 309df8bae1dSRodney W. Grimes dev_pager_putpage(pager, mlist, npages, sync) 310df8bae1dSRodney W. Grimes vm_pager_t pager; 311df8bae1dSRodney W. Grimes vm_page_t *mlist; 312df8bae1dSRodney W. Grimes int npages; 313df8bae1dSRodney W. Grimes boolean_t sync; 314df8bae1dSRodney W. Grimes { 315df8bae1dSRodney W. Grimes #ifdef DEBUG 316df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 317df8bae1dSRodney W. Grimes printf("dev_pager_putpage(%x, %x, %x, %x)\n", 318df8bae1dSRodney W. Grimes pager, mlist, npages, sync); 319df8bae1dSRodney W. Grimes #endif 320df8bae1dSRodney W. Grimes if (pager == NULL) 321df8bae1dSRodney W. Grimes return; 322df8bae1dSRodney W. Grimes panic("dev_pager_putpage called"); 323df8bae1dSRodney W. Grimes } 324df8bae1dSRodney W. Grimes 325df8bae1dSRodney W. Grimes static boolean_t 326df8bae1dSRodney W. Grimes dev_pager_haspage(pager, offset) 327df8bae1dSRodney W. Grimes vm_pager_t pager; 328df8bae1dSRodney W. Grimes vm_offset_t offset; 329df8bae1dSRodney W. Grimes { 330df8bae1dSRodney W. Grimes #ifdef DEBUG 331df8bae1dSRodney W. Grimes if (dpagerdebug & DDB_FOLLOW) 332df8bae1dSRodney W. Grimes printf("dev_pager_haspage(%x, %x)\n", pager, offset); 333df8bae1dSRodney W. Grimes #endif 334df8bae1dSRodney W. Grimes return(TRUE); 335df8bae1dSRodney W. Grimes } 336df8bae1dSRodney W. Grimes 337df8bae1dSRodney W. Grimes static vm_page_t 338df8bae1dSRodney W. Grimes dev_pager_getfake(paddr) 339df8bae1dSRodney W. Grimes vm_offset_t paddr; 340df8bae1dSRodney W. Grimes { 341df8bae1dSRodney W. Grimes vm_page_t m; 342df8bae1dSRodney W. Grimes int i; 343df8bae1dSRodney W. Grimes 344df8bae1dSRodney W. Grimes if (dev_pager_fakelist.tqh_first == NULL) { 345df8bae1dSRodney W. Grimes m = (vm_page_t)malloc(PAGE_SIZE, M_VMPGDATA, M_WAITOK); 346df8bae1dSRodney W. Grimes for (i = PAGE_SIZE / sizeof(*m); i > 0; i--) { 347df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&dev_pager_fakelist, m, pageq); 348df8bae1dSRodney W. Grimes m++; 349df8bae1dSRodney W. Grimes } 350df8bae1dSRodney W. Grimes } 351df8bae1dSRodney W. Grimes m = dev_pager_fakelist.tqh_first; 352df8bae1dSRodney W. Grimes TAILQ_REMOVE(&dev_pager_fakelist, m, pageq); 353df8bae1dSRodney W. Grimes m->flags = PG_BUSY | PG_CLEAN | PG_FAKE | PG_FICTITIOUS; 354df8bae1dSRodney W. Grimes m->phys_addr = paddr; 355df8bae1dSRodney W. Grimes m->wire_count = 1; 356df8bae1dSRodney W. Grimes return(m); 357df8bae1dSRodney W. Grimes } 358df8bae1dSRodney W. Grimes 359df8bae1dSRodney W. Grimes static void 360df8bae1dSRodney W. Grimes dev_pager_putfake(m) 361df8bae1dSRodney W. Grimes vm_page_t m; 362df8bae1dSRodney W. Grimes { 363df8bae1dSRodney W. Grimes #ifdef DIAGNOSTIC 364df8bae1dSRodney W. Grimes if (!(m->flags & PG_FICTITIOUS)) 365df8bae1dSRodney W. Grimes panic("dev_pager_putfake: bad page"); 366df8bae1dSRodney W. Grimes #endif 367df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&dev_pager_fakelist, m, pageq); 368df8bae1dSRodney W. Grimes } 369