diff options
| author | Peter Wemm <peter@FreeBSD.org> | 2000-05-21 13:41:29 +0000 |
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 2000-05-21 13:41:29 +0000 |
| commit | 249645144d24e86f021b30c8637a8e900076f1c0 (patch) | |
| tree | e937b0df83fae1dc6c60d88c8591fb644368c3a5 | |
| parent | bb7df05f675ed5ab631ec099135435de79f5f676 (diff) | |
Notes
| -rw-r--r-- | sys/conf/files | 1 | ||||
| -rw-r--r-- | sys/vm/phys_pager.c | 222 | ||||
| -rw-r--r-- | sys/vm/vm_mmap.c | 2 | ||||
| -rw-r--r-- | sys/vm/vm_object.h | 12 | ||||
| -rw-r--r-- | sys/vm/vm_pageout.c | 2 | ||||
| -rw-r--r-- | sys/vm/vm_pager.c | 2 |
6 files changed, 238 insertions, 3 deletions
diff --git a/sys/conf/files b/sys/conf/files index e1e062a8162d..ba8c672f1f51 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -880,6 +880,7 @@ ufs/ufs/ufs_vfsops.c standard ufs/ufs/ufs_vnops.c standard vm/default_pager.c standard vm/device_pager.c standard +vm/phys_pager.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c new file mode 100644 index 000000000000..a48126c1a622 --- /dev/null +++ b/sys/vm/phys_pager.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2000 Peter Wemm + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/linker_set.h> +#include <sys/conf.h> +#include <sys/mman.h> +#include <sys/sysctl.h> + +#include <vm/vm.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_pager.h> +#include <vm/vm_zone.h> + +static void phys_pager_init __P((void)); +static vm_object_t phys_pager_alloc __P((void *, vm_ooffset_t, vm_prot_t, + vm_ooffset_t)); +static void phys_pager_dealloc __P((vm_object_t)); +static int phys_pager_getpages __P((vm_object_t, vm_page_t *, int, int)); +static void phys_pager_putpages __P((vm_object_t, vm_page_t *, int, + boolean_t, int *)); +static boolean_t phys_pager_haspage __P((vm_object_t, vm_pindex_t, int *, + int *)); + +/* list of device pager objects */ +static struct pagerlst phys_pager_object_list; + +static int phys_pager_alloc_lock, phys_pager_alloc_lock_want; + +struct pagerops physpagerops = { + phys_pager_init, + phys_pager_alloc, + phys_pager_dealloc, + phys_pager_getpages, + phys_pager_putpages, + phys_pager_haspage, + NULL +}; + +static void +phys_pager_init() +{ + TAILQ_INIT(&phys_pager_object_list); +} + +static vm_object_t +phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff) +{ + vm_object_t object; + + /* + * Offset should be page aligned. + */ + if (foff & PAGE_MASK) + return (NULL); + + size = round_page(size); + + /* + * Lock to prevent object creation race condition. + */ + while (phys_pager_alloc_lock) { + phys_pager_alloc_lock_want++; + tsleep(&phys_pager_alloc_lock, PVM, "ppall", 0); + phys_pager_alloc_lock_want--; + } + phys_pager_alloc_lock = 1; + + /* + * Look up pager, creating as necessary. + */ + object = vm_pager_object_lookup(&phys_pager_object_list, handle); + if (object == NULL) { + /* + * Allocate object and associate it with the pager. + */ + object = vm_object_allocate(OBJT_PHYS, + OFF_TO_IDX(foff + size)); + object->handle = handle; + TAILQ_INIT(&object->un_pager.physp.physp_pglist); + TAILQ_INSERT_TAIL(&phys_pager_object_list, object, + pager_object_list); + } else { + /* + * Gain a reference to the object. + */ + vm_object_reference(object); + if (OFF_TO_IDX(foff + size) > object->size) + object->size = OFF_TO_IDX(foff + size); + } + + phys_pager_alloc_lock = 0; + if (phys_pager_alloc_lock_want) + wakeup(&phys_pager_alloc_lock); + + return (object); +} + +static void +phys_pager_dealloc(object) + vm_object_t object; +{ + vm_page_t m; + int s; + + TAILQ_REMOVE(&phys_pager_object_list, object, pager_object_list); + /* + * Free up our fake pages. + */ + s = splvm(); + while ((m = TAILQ_FIRST(&object->un_pager.physp.physp_pglist)) != 0) { + TAILQ_REMOVE(&object->un_pager.physp.physp_pglist, m, pageq); + /* return the page back to normal */ + m->flags &= ~PG_FICTITIOUS; + m->dirty = 0; + vm_page_unwire(m, 0); + vm_page_flag_clear(m, PG_ZERO); + vm_page_free(m); + } + splx(s); +} + +static int +phys_pager_getpages(object, m, count, reqpage) + vm_object_t object; + vm_page_t *m; + int count; + int reqpage; +{ + int i, s; + + s = splvm(); + /* + * Fill as many pages as vm_fault has allocated for us. + */ + for (i = 0; i < count; i++) { + if ((m[i]->flags & PG_ZERO) == 0) + vm_page_zero_fill(m[i]); + vm_page_flag_set(m[i], PG_ZERO); + /* Switch off pv_entries */ + vm_page_wire(m[i]); + vm_page_flag_set(m[i], PG_FICTITIOUS); + m[i]->valid = VM_PAGE_BITS_ALL; + m[i]->dirty = 0; + /* The requested page must remain busy, the others not. */ + if (reqpage != i) { + vm_page_flag_clear(m[i], PG_BUSY); + m[i]->busy = 0; + } + TAILQ_INSERT_TAIL(&object->un_pager.physp.physp_pglist, m[i], + pageq); + } + splx(s); + + return (VM_PAGER_OK); +} + +static void +phys_pager_putpages(object, m, count, sync, rtvals) + vm_object_t object; + vm_page_t *m; + int count; + boolean_t sync; + int *rtvals; +{ + panic("phys_pager_putpage called"); +} + +/* + * Implement a pretty aggressive clustered getpages strategy. Hint that + * everything in an entire 4MB window should be prefaulted at once. + * + * XXX 4MB (1024 slots per page table page) is convenient for x86, + * but may not be for other arches. + */ +#ifndef PHYSCLUSTER +#define PHYSCLUSTER 1024 +#endif +static boolean_t +phys_pager_haspage(object, pindex, before, after) + vm_object_t object; + vm_pindex_t pindex; + int *before; + int *after; +{ + vm_pindex_t base, end; + + base = pindex & (~(PHYSCLUSTER - 1)); + end = base + (PHYSCLUSTER - 1); + if (before != NULL) + *before = pindex - base; + if (after != NULL) + *after = end - pindex; + return (TRUE); +} diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index d5cc69d394bb..922234ad15eb 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -1096,7 +1096,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, /* * Force device mappings to be shared. */ - if (type == OBJT_DEVICE) { + if (type == OBJT_DEVICE || type == OBJT_PHYS) { flags &= ~(MAP_PRIVATE|MAP_COPY); flags |= MAP_SHARED; } diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 5fb2e6945232..62a3bbe24168 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -74,7 +74,8 @@ #include <sys/queue.h> #include <machine/atomic.h> -enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_DEAD }; +enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_PHYS, + OBJT_DEAD }; typedef u_char objtype_t; /* @@ -123,6 +124,15 @@ struct vm_object { } devp; /* + * Physmem pager + * + * physp_pglist - list of allocated pages + */ + struct { + TAILQ_HEAD(, vm_page) physp_pglist; + } physp; + + /* * Swap pager * * swp_bcount - number of swap 'swblock' metablocks, each diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index d1fe8e16c87a..9c09a8bf9c58 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -448,7 +448,7 @@ vm_pageout_object_deactivate_pages(map, object, desired, map_remove_only) int remove_mode; int s; - if (object->type == OBJT_DEVICE) + if (object->type == OBJT_DEVICE || object->type == OBJT_PHYS) return; while (object) { diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index 7c08a3a131f9..a251b97cdcba 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -92,6 +92,7 @@ extern struct pagerops defaultpagerops; extern struct pagerops swappagerops; extern struct pagerops vnodepagerops; extern struct pagerops devicepagerops; +extern struct pagerops physpagerops; int cluster_pbuf_freecnt = -1; /* unlimited to begin with */ @@ -173,6 +174,7 @@ struct pagerops *pagertab[] = { &swappagerops, /* OBJT_SWAP */ &vnodepagerops, /* OBJT_VNODE */ &devicepagerops, /* OBJT_DEVICE */ + &physpagerops, /* OBJT_PHYS */ &deadpagerops /* OBJT_DEAD */ }; |
