Module Name: src Committed By: uebayasi Date: Tue Feb 23 07:44:25 UTC 2010
Modified Files: src/sys/uvm [uebayasi-xip]: uvm_extern.h uvm_page.c uvm_page.h Log Message: Introduce uvm_page_physload_device(). This registers a physical address range of a device, similar to uvm_page_physload() for memories. For now, this is supposed to be called by MD code. We have to consider the design when we'll manage mmap'able character devices. Expose paddr_t -> struct vm_page * conversion function for device pages, uvm_phys_to_vm_page_device(). This will be called by XIP vnode pager. Because it knows if a given vnode is a device page (and its physical address base) or not. Don't look up device segments, but directly make a cookie. To generate a diff of this commit: cvs rdiff -u -r1.161 -r1.161.2.1 src/sys/uvm/uvm_extern.h cvs rdiff -u -r1.153.2.12 -r1.153.2.13 src/sys/uvm/uvm_page.c cvs rdiff -u -r1.59.2.12 -r1.59.2.13 src/sys/uvm/uvm_page.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_extern.h diff -u src/sys/uvm/uvm_extern.h:1.161 src/sys/uvm/uvm_extern.h:1.161.2.1 --- src/sys/uvm/uvm_extern.h:1.161 Sat Nov 21 17:45:02 2009 +++ src/sys/uvm/uvm_extern.h Tue Feb 23 07:44:25 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_extern.h,v 1.161 2009/11/21 17:45:02 rmind Exp $ */ +/* $NetBSD: uvm_extern.h,v 1.161.2.1 2010/02/23 07:44:25 uebayasi Exp $ */ /* * @@ -721,8 +721,10 @@ void uvm_pagerealloc(struct vm_page *, struct uvm_object *, voff_t); /* Actually, uvm_page_physload takes PF#s which need their own type */ -void uvm_page_physload(paddr_t, paddr_t, paddr_t, - paddr_t, int); +void uvm_page_physload(paddr_t, paddr_t, + paddr_t, paddr_t, int); +void uvm_page_physload_device(paddr_t, paddr_t, + paddr_t, paddr_t, int); void uvm_setpagesize(void); /* uvm_pager.c */ Index: src/sys/uvm/uvm_page.c diff -u src/sys/uvm/uvm_page.c:1.153.2.12 src/sys/uvm/uvm_page.c:1.153.2.13 --- src/sys/uvm/uvm_page.c:1.153.2.12 Fri Feb 12 04:33:05 2010 +++ src/sys/uvm/uvm_page.c Tue Feb 23 07:44:25 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.c,v 1.153.2.12 2010/02/12 04:33:05 uebayasi Exp $ */ +/* $NetBSD: uvm_page.c,v 1.153.2.13 2010/02/23 07:44:25 uebayasi Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.12 2010/02/12 04:33:05 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.13 2010/02/23 07:44:25 uebayasi Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -165,6 +165,10 @@ static void uvm_pageinsert(struct uvm_object *, struct vm_page *); static void uvm_pageremove(struct uvm_object *, struct vm_page *); +static void vm_page_device_mdpage_insert(paddr_t); +#if 0 +static void vm_page_device_mdpage_remove(paddr_t); +#endif /* * per-object tree of pages @@ -449,7 +453,7 @@ paddr = ptoa(vm_physmem[lcv].start); for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) { #ifdef __HAVE_VM_PAGE_MD - VM_MDPAGE_INIT(&vm_physmem[lcv].pgs[i]); + VM_MDPAGE_INIT(&vm_physmem[lcv].pgs[i].mdpage, paddr); #endif if (atop(paddr) >= vm_physmem[lcv].avail_start && atop(paddr) <= vm_physmem[lcv].avail_end) { @@ -738,10 +742,38 @@ * => we are limited to VM_PHYSSEG_MAX physical memory segments */ +static void +uvm_page_physload_common(struct vm_physseg * const, const int, + const paddr_t, const paddr_t, const paddr_t, const paddr_t, const int); + void uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, paddr_t avail_end, int free_list) { + + uvm_page_physload_common(vm_physmem, vm_nphysmem, start, end, + avail_start, avail_end, free_list); + vm_nphysmem++; +} + +void +uvm_page_physload_device(paddr_t start, paddr_t end, paddr_t avail_start, + paddr_t avail_end, int free_list) +{ + + uvm_page_physload_common(vm_physdev, vm_nphysdev, start, end, + avail_start, avail_end, free_list); + vm_nphysdev++; + + for (paddr_t pf = start; pf < end; pf++) + vm_page_device_mdpage_insert(pf); +} + +static void +uvm_page_physload_common(struct vm_physseg * const segs, const int nsegs, + const paddr_t start, const paddr_t end, + const paddr_t avail_start, const paddr_t avail_end, const int free_list) +{ int preload, lcv; psize_t npages; struct vm_page *pgs; @@ -758,7 +790,7 @@ * do we have room? */ - if (vm_nphysmem == VM_PHYSSEG_MAX) { + if (nsegs == VM_PHYSSEG_MAX) { printf("uvm_page_physload: unable to load physical memory " "segment\n"); printf("\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n", @@ -767,20 +799,26 @@ return; } + if (segs == vm_physdev) { + preload = false; + goto uvm_page_physload_common_insert; + } + /* * check to see if this is a "preload" (i.e. uvm_mem_init hasn't been * called yet, so malloc is not available). */ - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { - if (vm_physmem[lcv].pgs) + for (lcv = 0 ; lcv < nsegs ; lcv++) { + if (segs[lcv].pgs) break; } - preload = (lcv == vm_nphysmem); + preload = (lcv == nsegs); /* * if VM is already running, attempt to malloc() vm_page structures */ + /* XXXUEBS this is super ugly */ if (!preload) { #if defined(VM_PHYSSEG_NOADD) @@ -814,39 +852,40 @@ npages = 0; } +uvm_page_physload_common_insert: /* - * now insert us in the proper place in vm_physmem[] + * now insert us in the proper place in segs[] */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) /* random: put it at the end (easy!) */ - ps = &vm_physmem[vm_nphysmem]; + ps = &segs[nsegs]; #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) { int x; /* sort by address for binary search */ - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) - if (start < vm_physmem[lcv].start) + for (lcv = 0 ; lcv < nsegs ; lcv++) + if (start < segs[lcv].start) break; - ps = &vm_physmem[lcv]; + ps = &segs[lcv]; /* move back other entries, if necessary ... */ - for (x = vm_nphysmem ; x > lcv ; x--) + for (x = nsegs ; x > lcv ; x--) /* structure copy */ - vm_physmem[x] = vm_physmem[x - 1]; + segs[x] = segs[x - 1]; } #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) { int x; /* sort by largest segment first */ - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) + for (lcv = 0 ; lcv < nsegs ; lcv++) if ((end - start) > - (vm_physmem[lcv].end - vm_physmem[lcv].start)) + (segs[lcv].end - segs[lcv].start)) break; - ps = &vm_physmem[lcv]; + ps = &segs[lcv]; /* move back other entries, if necessary ... */ - for (x = vm_nphysmem ; x > lcv ; x--) + for (x = nsegs ; x > lcv ; x--) /* structure copy */ - vm_physmem[x] = vm_physmem[x - 1]; + segs[x] = segs[x - 1]; } #else panic("uvm_page_physload: unknown physseg strategy selected!"); @@ -854,16 +893,16 @@ ps->start = start; ps->end = end; + + if (segs == vm_physdev) + return; + + /* XXXUEBS ugly */ ps->avail_start = avail_start; ps->avail_end = avail_end; - if (preload) { - ps->pgs = NULL; - } else { - ps->pgs = pgs; - ps->endpg = pgs + npages; - } + ps->pgs = pgs; + ps->endpg = pgs + npages; ps->free_list = free_list; - vm_nphysmem++; if (!preload) { uvmpdpol_reinit(); @@ -1052,8 +1091,8 @@ #define VM_PAGE_DEVICE_MAGIC_MASK 0x3 #define VM_PAGE_DEVICE_MAGIC_SHIFT 2 -static inline struct vm_page * -PHYS_TO_VM_PAGE_DEVICE(paddr_t pa) +struct vm_page * +uvm_phys_to_vm_page_device(paddr_t pa) { paddr_t pf = pa >> PAGE_SHIFT; uintptr_t cookie = pf << VM_PAGE_DEVICE_MAGIC_SHIFT; @@ -1092,7 +1131,7 @@ #ifdef DEVICE_PAGE psi = vm_physseg_find_device(pf, &off); if (psi != -1) - return(PHYS_TO_VM_PAGE_DEVICE(pa)); + return(uvm_phys_to_vm_page_device(pa)); #endif psi = vm_physseg_find(pf, &off); if (psi != -1) @@ -1155,13 +1194,6 @@ /* Global for now. Consider to make this per-vm_physseg. */ struct vm_page_device_mdpage vm_page_device_mdpage; -static u_int -vm_page_device_mdpage_hash(struct vm_page *pg) -{ - - return VM_PAGE_DEVICE_TO_PHYS(pg); -} - static struct vm_page_device_mdpage_head * vm_page_device_mdpage_head(u_int hash) { @@ -1177,14 +1209,15 @@ } void -vm_page_device_mdpage_insert(struct vm_page *pg) +vm_page_device_mdpage_insert(paddr_t pf) { - paddr_t pf = VM_PAGE_DEVICE_TO_PHYS(pg); - u_int hash = vm_page_device_mdpage_hash(pg); + u_int hash = (u_int)pf; kmutex_t *lock = vm_page_device_mdpage_lock(hash); struct vm_page_device_mdpage_head *head = vm_page_device_mdpage_head(hash); struct vm_page_device_mdpage_entry *mde = kmem_zalloc(sizeof(*mde), KM_SLEEP); + + VM_MDPAGE_INIT(&mde->mde_mdpage, pf << PAGE_SHIFT); mde->mde_pf = pf; mutex_spin_enter(lock); @@ -1192,11 +1225,11 @@ mutex_spin_exit(lock); } +#if 0 void -vm_page_device_mdpage_remove(struct vm_page *pg) +vm_page_device_mdpage_remove(paddr_t pf) { - paddr_t pf = VM_PAGE_DEVICE_TO_PHYS(pg); - u_int hash = vm_page_device_mdpage_hash(pg); + u_int hash = (u_int)pf; kmutex_t *lock = vm_page_device_mdpage_lock(hash); struct vm_page_device_mdpage_head *head = vm_page_device_mdpage_head(hash); @@ -1219,16 +1252,17 @@ KASSERT(mde != NULL); kmem_free(mde, sizeof(*mde)); } +#endif struct vm_page_md * vm_page_device_mdpage_lookup(struct vm_page *pg) { - paddr_t pf = VM_PAGE_DEVICE_TO_PHYS(pg); - u_int hash = vm_page_device_mdpage_hash(pg); + paddr_t pf = VM_PAGE_DEVICE_TO_PHYS(pg) >> PAGE_SHIFT; + u_int hash = (u_int)pf; kmutex_t *lock = vm_page_device_mdpage_lock(hash); struct vm_page_device_mdpage_head *head = vm_page_device_mdpage_head(hash); - struct vm_page_device_mdpage_entry *mde; + struct vm_page_device_mdpage_entry *mde = NULL; mutex_spin_enter(lock); SLIST_FOREACH(mde, &head->list, mde_hash) Index: src/sys/uvm/uvm_page.h diff -u src/sys/uvm/uvm_page.h:1.59.2.12 src/sys/uvm/uvm_page.h:1.59.2.13 --- src/sys/uvm/uvm_page.h:1.59.2.12 Fri Feb 12 13:40:00 2010 +++ src/sys/uvm/uvm_page.h Tue Feb 23 07:44:25 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.h,v 1.59.2.12 2010/02/12 13:40:00 uebayasi Exp $ */ +/* $NetBSD: uvm_page.h,v 1.59.2.13 2010/02/23 07:44:25 uebayasi Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -304,13 +304,11 @@ paddr_t uvm_vm_page_to_phys(const struct vm_page *); #ifdef XIP int vm_physseg_find_device(paddr_t, int *); -struct vm_page *uvm_phys_to_vm_page_device(paddr_t); paddr_t uvm_vm_page_to_phys_device(const struct vm_page *); +struct vm_page *uvm_phys_to_vm_page_device(paddr_t); #endif #ifdef XIP -void vm_page_device_mdpage_insert(struct vm_page *); -void vm_page_device_mdpage_remove(struct vm_page *); struct vm_page_md *vm_page_device_mdpage_lookup(struct vm_page *); #endif