phys_pager.c revision 118466
151973Smsmith/* 251973Smsmith * Copyright (c) 2000 Peter Wemm 351973Smsmith * 451973Smsmith * Redistribution and use in source and binary forms, with or without 551973Smsmith * modification, are permitted provided that the following conditions 651973Smsmith * are met: 751973Smsmith * 1. Redistributions of source code must retain the above copyright 851973Smsmith * notice, this list of conditions and the following disclaimer. 951973Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1051973Smsmith * notice, this list of conditions and the following disclaimer in the 1151973Smsmith * documentation and/or other materials provided with the distribution. 1251973Smsmith * 1351973Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1451973Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1551973Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1651973Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 1751973Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1851973Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1951973Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2051973Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2151973Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2251973Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2351973Smsmith * SUCH DAMAGE. 2451973Smsmith */ 2551973Smsmith 2651973Smsmith#include <sys/cdefs.h> 2751973Smsmith__FBSDID("$FreeBSD: head/sys/vm/phys_pager.c 118466 2003-08-05 06:51:26Z phk $"); 2851973Smsmith 2951973Smsmith#include <sys/param.h> 3058188Smsmith#include <sys/systm.h> 3158188Smsmith#include <sys/linker_set.h> 3258188Smsmith#include <sys/conf.h> 3358188Smsmith#include <sys/kernel.h> 3458188Smsmith#include <sys/lock.h> 3558188Smsmith#include <sys/proc.h> 3687599Sobrien#include <sys/mutex.h> 3787599Sobrien#include <sys/mman.h> 3858188Smsmith#include <sys/sysctl.h> 3958188Smsmith 4058188Smsmith#include <vm/vm.h> 4158188Smsmith#include <vm/vm_object.h> 4258188Smsmith#include <vm/vm_page.h> 4358188Smsmith#include <vm/vm_pager.h> 4460074Smsmith 4560074Smsmith/* prevent concurrant creation races */ 4660074Smsmithstatic int phys_pager_alloc_lock; 4760074Smsmith/* list of device pager objects */ 4860074Smsmithstatic struct pagerlst phys_pager_object_list; 4951973Smsmith/* protect access to phys_pager_object_list */ 50238997Sdelphijstatic struct mtx phys_pager_mtx; 5160074Smsmith 5260074Smsmithstatic void 5351973Smsmithphys_pager_init(void) 5451973Smsmith{ 5558188Smsmith 5651973Smsmith TAILQ_INIT(&phys_pager_object_list); 5751973Smsmith mtx_init(&phys_pager_mtx, "phys_pager list", NULL, MTX_DEF); 5851973Smsmith} 5951973Smsmith 6051973Smsmith/* 6151973Smsmith * MPSAFE 6251973Smsmith */ 6351973Smsmithstatic vm_object_t 6451973Smsmithphys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, 6551973Smsmith vm_ooffset_t foff) 6651973Smsmith{ 6751973Smsmith vm_object_t object; 6851973Smsmith 6951973Smsmith /* 7051973Smsmith * Offset should be page aligned. 7151973Smsmith */ 7251973Smsmith if (foff & PAGE_MASK) 7351973Smsmith return (NULL); 7451973Smsmith 7551973Smsmith size = round_page(size); 7651973Smsmith 7751973Smsmith if (handle != NULL) { 7851973Smsmith mtx_lock(&Giant); 7951973Smsmith /* 8051973Smsmith * Lock to prevent object creation race condition. 8160938Sjake */ 8251973Smsmith while (phys_pager_alloc_lock) { 8351973Smsmith phys_pager_alloc_lock = -1; 8451973Smsmith tsleep(&phys_pager_alloc_lock, PVM, "swpalc", 0); 8551973Smsmith } 8654419Smsmith phys_pager_alloc_lock = 1; 8751973Smsmith 8851973Smsmith /* 8951973Smsmith * Look up pager, creating as necessary. 9051973Smsmith */ 9151973Smsmith object = vm_pager_object_lookup(&phys_pager_object_list, handle); 9251973Smsmith if (object == NULL) { 9351973Smsmith /* 9451973Smsmith * Allocate object and associate it with the pager. 9551973Smsmith */ 9651973Smsmith object = vm_object_allocate(OBJT_PHYS, 9751973Smsmith OFF_TO_IDX(foff + size)); 9851973Smsmith object->handle = handle; 9951973Smsmith mtx_lock(&phys_pager_mtx); 10051973Smsmith TAILQ_INSERT_TAIL(&phys_pager_object_list, object, 10151973Smsmith pager_object_list); 102119665Sscottl mtx_unlock(&phys_pager_mtx); 10351973Smsmith } else { 10451973Smsmith /* 10551973Smsmith * Gain a reference to the object. 10651973Smsmith */ 10751973Smsmith vm_object_reference(object); 10851973Smsmith if (OFF_TO_IDX(foff + size) > object->size) 10951973Smsmith object->size = OFF_TO_IDX(foff + size); 11051973Smsmith } 11151973Smsmith if (phys_pager_alloc_lock == -1) 112130585Sphk wakeup(&phys_pager_alloc_lock); 11351973Smsmith phys_pager_alloc_lock = 0; 11469292Smdodd mtx_unlock(&Giant); 11569292Smdodd } else { 11651973Smsmith object = vm_object_allocate(OBJT_PHYS, 11751973Smsmith OFF_TO_IDX(foff + size)); 11851973Smsmith } 11951973Smsmith 12051973Smsmith return (object); 12151973Smsmith} 12251973Smsmith 12351973Smsmith/* 12451973Smsmith * MPSAFE 12551973Smsmith */ 12651973Smsmithstatic void 12751973Smsmithphys_pager_dealloc(vm_object_t object) 12854979Smsmith{ 12951973Smsmith 13051973Smsmith if (object->handle != NULL) { 13151973Smsmith mtx_lock(&phys_pager_mtx); 13251973Smsmith TAILQ_REMOVE(&phys_pager_object_list, object, pager_object_list); 13360938Sjake mtx_unlock(&phys_pager_mtx); 13460938Sjake } 13551973Smsmith} 13651973Smsmith 13751973Smsmithstatic int 138240963Sjhbphys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) 13951973Smsmith{ 14051973Smsmith int i, s; 14151973Smsmith 14251973Smsmith s = splvm(); 14351973Smsmith vm_page_lock_queues(); 14451973Smsmith /* 14551973Smsmith * Fill as many pages as vm_fault has allocated for us. 14651973Smsmith */ 14751973Smsmith for (i = 0; i < count; i++) { 14851973Smsmith if ((m[i]->flags & PG_ZERO) == 0) { 14951973Smsmith vm_page_unlock_queues(); 150240608Sjhb pmap_zero_page(m[i]); 151240608Sjhb vm_page_lock_queues(); 152240608Sjhb } 153240608Sjhb vm_page_flag_set(m[i], PG_ZERO); 15451973Smsmith /* Switch off pv_entries */ 15559136Smsmith vm_page_unmanage(m[i]); 15654979Smsmith m[i]->valid = VM_PAGE_BITS_ALL; 15759136Smsmith m[i]->dirty = 0; 15859136Smsmith /* The requested page must remain busy, the others not. */ 15959136Smsmith if (reqpage != i) { 16059136Smsmith vm_page_flag_clear(m[i], PG_BUSY); 16159136Smsmith m[i]->busy = 0; 16251973Smsmith } 16351973Smsmith } 16458188Smsmith vm_page_unlock_queues(); 16558188Smsmith splx(s); 16659447Smsmith 16754419Smsmith return (VM_PAGER_OK); 16851973Smsmith} 16951973Smsmith 17058188Smsmithstatic void 17151973Smsmithphys_pager_putpages(vm_object_t object, vm_page_t *m, int count, boolean_t sync, 17251973Smsmith int *rtvals) 17351973Smsmith{ 17451973Smsmith 17551973Smsmith panic("phys_pager_putpage called"); 17651973Smsmith} 177240608Sjhb 17851973Smsmith/* 17951973Smsmith * Implement a pretty aggressive clustered getpages strategy. Hint that 18051973Smsmith * everything in an entire 4MB window should be prefaulted at once. 18151973Smsmith * 182240608Sjhb * XXX 4MB (1024 slots per page table page) is convenient for x86, 183240608Sjhb * but may not be for other arches. 184240608Sjhb */ 185240608Sjhb#ifndef PHYSCLUSTER 186240608Sjhb#define PHYSCLUSTER 1024 187240608Sjhb#endif 18854419Smsmithstatic boolean_t 18954419Smsmithphys_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, 19051973Smsmith int *after) 19151973Smsmith{ 19251973Smsmith vm_pindex_t base, end; 19351973Smsmith 19451973Smsmith base = pindex & (~(PHYSCLUSTER - 1)); 19551973Smsmith end = base + (PHYSCLUSTER - 1); 19651973Smsmith if (before != NULL) 19751973Smsmith *before = pindex - base; 19851973Smsmith if (after != NULL) 19951973Smsmith *after = end - pindex; 20051973Smsmith return (TRUE); 20151973Smsmith} 20251973Smsmith 20351973Smsmithstruct pagerops physpagerops = { 20451973Smsmith .pgo_init = phys_pager_init, 20559136Smsmith .pgo_alloc = phys_pager_alloc, 20651973Smsmith .pgo_dealloc = phys_pager_dealloc, 20751973Smsmith .pgo_getpages = phys_pager_getpages, 20851973Smsmith .pgo_putpages = phys_pager_putpages, 20951973Smsmith .pgo_haspage = phys_pager_haspage, 21051973Smsmith}; 21151973Smsmith