head 1.9; access; symbols; locks cherry:1.9; strict; comment @# @; 1.9 date 2016.12.13.12.56.39; author cherry; state Exp; branches; next 1.8; 1.8 date 2016.11.20.11.11.46; author cherry; state Exp; branches; next 1.7; 1.7 date 2016.11.20.11.08.57; author cherry; state Exp; branches; next 1.6; 1.6 date 2016.11.17.15.45.02; author cherry; state Exp; branches; next 1.5; 1.5 date 2016.11.13.11.23.05; author cherry; state Exp; branches; next 1.4; 1.4 date 2016.10.30.17.28.09; author cherry; state Exp; branches; next 1.3; 1.3 date 2016.10.28.08.32.31; author cherry; state Exp; branches; next 1.2; 1.2 date 2016.10.28.08.27.28; author cherry; state Exp; branches; next 1.1; 1.1 date 2016.10.20.14.29.09; author cherry; state Exp; branches; next ; desc @Initial version for fox review @ 1.9 log @s/physmem/physseg// remove rump testing and dependency for tests @ text @Index: sys/uvm/Makefile =================================================================== RCS file: /cvsroot/src/sys/uvm/Makefile,v retrieving revision 1.9 diff -p -u -r1.9 Makefile --- sys/uvm/Makefile 11 Feb 2006 12:45:07 -0000 1.9 +++ sys/uvm/Makefile 13 Dec 2016 12:44:34 -0000 @@@@ -5,7 +5,7 @@@@ INCSDIR= /usr/include/uvm INCS= uvm.h uvm_amap.h uvm_anon.h uvm_aobj.h uvm_device.h \ uvm_extern.h uvm_fault.h uvm_fault_i.h uvm_glue.h \ uvm_km.h uvm_loan.h \ - uvm_map.h uvm_object.h uvm_page.h \ + uvm_map.h uvm_object.h uvm_page.h uvm_physseg.h \ uvm_pager.h uvm_param.h uvm_pdaemon.h uvm_pglist.h \ uvm_pmap.h uvm_prot.h uvm_stat.h \ uvm_swap.h Index: sys/uvm/files.uvm =================================================================== RCS file: /cvsroot/src/sys/uvm/files.uvm,v retrieving revision 1.27 diff -p -u -r1.27 files.uvm --- sys/uvm/files.uvm 1 Dec 2016 02:09:03 -0000 1.27 +++ sys/uvm/files.uvm 13 Dec 2016 12:44:34 -0000 @@@@ -15,6 +15,7 @@@@ defparam opt_pagermap.h PAGER_MAP_SIZE defflag PDPOLICY_CLOCKPRO defparam USER_VA0_DISABLE_DEFAULT defflag opt_uvm_page_trkown.h UVM_PAGE_TRKOWN +defflag opt_uvm_hotplug.h UVM_HOTPLUG define uvm defflag opt_uvm.h UVM @@@@ -42,6 +43,7 @@@@ file uvm/uvm_pdaemon.c uvm file uvm/uvm_pdpolicy_clock.c !pdpolicy_clockpro file uvm/uvm_pdpolicy_clockpro.c pdpolicy_clockpro file uvm/uvm_pglist.c uvm +file uvm/uvm_physseg.c uvm file uvm/uvm_readahead.c uvm file uvm/uvm_stat.c uvm file uvm/uvm_swap.c vmswap Index: sys/uvm/uvm.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm.h,v retrieving revision 1.66 diff -p -u -r1.66 uvm.h --- sys/uvm/uvm.h 13 Apr 2015 22:04:44 -0000 1.66 +++ sys/uvm/uvm.h 13 Dec 2016 12:44:34 -0000 @@@@ -57,6 +57,7 @@@@ #include #include #include +#include #include #include Index: sys/uvm/uvm_extern.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_extern.h,v retrieving revision 1.198 diff -p -u -r1.198 uvm_extern.h --- sys/uvm/uvm_extern.h 20 Jul 2016 12:38:43 -0000 1.198 +++ sys/uvm/uvm_extern.h 13 Dec 2016 12:44:34 -0000 @@@@ -708,9 +708,6 @@@@ void uvm_pagereplace(struct vm_page *, struct vm_page *); 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_setpagesize(void); /* uvm_pager.c */ Index: sys/uvm/uvm_page.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_page.c,v retrieving revision 1.187 diff -p -u -r1.187 uvm_page.c --- sys/uvm/uvm_page.c 11 Apr 2015 19:24:13 -0000 1.187 +++ sys/uvm/uvm_page.c 13 Dec 2016 12:44:35 -0000 @@@@ -81,24 +81,13 @@@@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v #include #include #include +#include #include #include #include /* - * global vars... XXXCDC: move to uvm. structure. - */ - -/* - * physical memory config is stored in vm_physmem. - */ - -struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ -int vm_nphysseg = 0; /* XXXCDC: uvm.nphysseg */ -#define vm_nphysmem vm_nphysseg - -/* * Some supported CPUs in a given architecture don't support all * of the things necessary to do idle page zero'ing efficiently. * We therefore provide a way to enable it from machdep code here. @@@@ -116,7 +105,7 @@@@ int vm_page_reserve_kernel = UVM_RESERVE /* * physical memory size; */ -int physmem; +psize_t physmem; /* * local variables @@@@ -146,6 +135,18 @@@@ vaddr_t uvm_zerocheckkva; #endif /* DEBUG */ /* + * These functions are reserved for uvm(9) internal use and are not + * exported in the header file uvm_physseg.h + * + * Thus they are redefined here. + */ +void uvm_physseg_init_seg(uvm_physseg_t, struct vm_page *); +void uvm_physseg_seg_chomp_slab(uvm_physseg_t, struct vm_page *, size_t); + +/* returns a pgs array */ +struct vm_page *uvm_physseg_seg_alloc_from_slab(uvm_physseg_t, size_t); + +/* * local prototypes */ @@@@ -337,11 +338,9 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr static struct uvm_cpu boot_cpu; psize_t freepages, pagecount, bucketcount, n; struct pgflbucket *bucketarray, *cpuarray; - struct vm_physseg *seg; struct vm_page *pagearray; + uvm_physseg_t bank; int lcv; - u_int i; - paddr_t paddr; KASSERT(ncpu <= 1); CTASSERT(sizeof(pagearray->offset) >= sizeof(struct uvm_cpu *)); @@@@ -369,7 +368,7 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr * now is to allocate vm_page structures for this memory. */ - if (vm_nphysmem == 0) + if (uvm_physseg_get_last() == UVM_PHYSSEG_TYPE_INVALID) panic("uvm_page_bootstrap: no memory pre-allocated"); /* @@@@ -381,9 +380,11 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr */ freepages = 0; - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { - seg = VM_PHYSMEM_PTR(lcv); - freepages += (seg->end - seg->start); + + for (bank = uvm_physseg_get_first(); + uvm_physseg_valid(bank) ; + bank = uvm_physseg_get_next(bank)) { + freepages += (uvm_physseg_get_end(bank) - uvm_physseg_get_start(bank)); } /* @@@@ -428,31 +429,20 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr /* * init the vm_page structures and put them in the correct place. */ + /* First init the extent */ - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { - seg = VM_PHYSMEM_PTR(lcv); - n = seg->end - seg->start; + for (bank = uvm_physseg_get_first(), + uvm_physseg_seg_chomp_slab(bank, pagearray, pagecount); + uvm_physseg_valid(bank); + bank = uvm_physseg_get_next(bank)) { + + n = uvm_physseg_get_end(bank) - uvm_physseg_get_start(bank); + uvm_physseg_seg_alloc_from_slab(bank, n); + uvm_physseg_init_seg(bank, pagearray); /* set up page array pointers */ - seg->pgs = pagearray; pagearray += n; pagecount -= n; - seg->lastpg = seg->pgs + n; - - /* init and free vm_pages (we've already zeroed them) */ - paddr = ctob(seg->start); - for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) { - seg->pgs[i].phys_addr = paddr; -#ifdef __HAVE_VM_PAGE_MD - VM_MDPAGE_INIT(&seg->pgs[i]); -#endif - if (atop(paddr) >= seg->avail_start && - atop(paddr) < seg->avail_end) { - uvmexp.npages++; - /* add page to free pool */ - uvm_pagefree(&seg->pgs[i]); - } - } } /* @@@@ -625,92 +615,42 @@@@ static bool uvm_page_physget_freelist(pa static bool uvm_page_physget_freelist(paddr_t *paddrp, int freelist) { - struct vm_physseg *seg; - int lcv, x; + uvm_physseg_t lcv; /* pass 1: try allocating from a matching end */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (lcv = vm_nphysmem - 1 ; lcv >= 0 ; lcv--) + for (lcv = uvm_physseg_get_last() ; uvm_physseg_valid(lcv) ; lcv = uvm_physseg_get_prev(lcv)) #else - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) + for (lcv = uvm_physseg_get_first() ; uvm_physseg_valid(lcv) ; lcv = uvm_physseg_get_next(lcv)) #endif { - seg = VM_PHYSMEM_PTR(lcv); - if (uvm.page_init_done == true) panic("uvm_page_physget: called _after_ bootstrap"); - if (seg->free_list != freelist) - continue; + /* Try to match at front or back on unused segment */ + if (uvm_page_physunload(lcv, freelist, paddrp) == false) { + if (paddrp == NULL) /* freelist fail, try next */ + continue; + } else + return true; - /* try from front */ - if (seg->avail_start == seg->start && - seg->avail_start < seg->avail_end) { - *paddrp = ctob(seg->avail_start); - seg->avail_start++; - seg->start++; - /* nothing left? nuke it */ - if (seg->avail_start == seg->end) { - if (vm_nphysmem == 1) - panic("uvm_page_physget: out of memory!"); - vm_nphysmem--; - for (x = lcv ; x < vm_nphysmem ; x++) - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x + 1); - } - return (true); - } - - /* try from rear */ - if (seg->avail_end == seg->end && - seg->avail_start < seg->avail_end) { - *paddrp = ctob(seg->avail_end - 1); - seg->avail_end--; - seg->end--; - /* nothing left? nuke it */ - if (seg->avail_end == seg->start) { - if (vm_nphysmem == 1) - panic("uvm_page_physget: out of memory!"); - vm_nphysmem--; - for (x = lcv ; x < vm_nphysmem ; x++) - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x + 1); - } - return (true); - } - } /* pass2: forget about matching ends, just allocate something */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (lcv = vm_nphysmem - 1 ; lcv >= 0 ; lcv--) + for (lcv = uvm_physseg_get_last() ; uvm_physseg_valid(lcv); lcv = uvm_physseg_get_prev(lcv)) #else - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) + for (lcv = uvm_physseg_get_first() ; uvm_physseg_valid(lcv) ; lcv = uvm_physseg_get_next(lcv)) #endif { - seg = VM_PHYSMEM_PTR(lcv); - - /* any room in this bank? */ - if (seg->avail_start >= seg->avail_end) - continue; /* nope */ - - *paddrp = ctob(seg->avail_start); - seg->avail_start++; - /* truncate! */ - seg->start = seg->avail_start; - - /* nothing left? nuke it */ - if (seg->avail_start == seg->end) { - if (vm_nphysmem == 1) - panic("uvm_page_physget: out of memory!"); - vm_nphysmem--; - for (x = lcv ; x < vm_nphysmem ; x++) - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x + 1); - } - return (true); + /* Try the front regardless. */ + if (uvm_page_physunload_force(lcv, freelist, paddrp) == false) { + if (paddrp == NULL) /* freelist fail, try next */ + continue; + } else + return true; } - - return (false); /* whoops! */ + } + return false; } bool @@@@ -727,228 +667,6 @@@@ uvm_page_physget(paddr_t *paddrp) #endif /* PMAP_STEAL_MEMORY */ /* - * uvm_page_physload: load physical memory into VM system - * - * => all args are PFs - * => all pages in start/end get vm_page structures - * => areas marked by avail_start/avail_end get added to the free page pool - * => we are limited to VM_PHYSSEG_MAX physical memory segments - */ - -void -uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, - paddr_t avail_end, int free_list) -{ - int preload, lcv; - psize_t npages; - struct vm_page *pgs; - struct vm_physseg *ps; - - if (uvmexp.pagesize == 0) - panic("uvm_page_physload: page size not set!"); - if (free_list >= VM_NFREELIST || free_list < VM_FREELIST_DEFAULT) - panic("uvm_page_physload: bad free list %d", free_list); - if (start >= end) - panic("uvm_page_physload: start >= end"); - - /* - * do we have room? - */ - - if (vm_nphysmem == 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", - VM_PHYSSEG_MAX, (long long)start, (long long)end); - printf("\tincrease VM_PHYSSEG_MAX\n"); - return; - } - - /* - * check to see if this is a "preload" (i.e. uvm_page_init hasn't been - * called yet, so kmem is not available). - */ - - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { - if (VM_PHYSMEM_PTR(lcv)->pgs) - break; - } - preload = (lcv == vm_nphysmem); - - /* - * if VM is already running, attempt to kmem_alloc vm_page structures - */ - - if (!preload) { - panic("uvm_page_physload: tried to add RAM after vm_mem_init"); - } else { - pgs = NULL; - npages = 0; - } - - /* - * now insert us in the proper place in vm_physmem[] - */ - -#if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) - /* random: put it at the end (easy!) */ - ps = VM_PHYSMEM_PTR(vm_nphysmem); -#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_PTR(lcv)->start) - break; - ps = VM_PHYSMEM_PTR(lcv); - /* move back other entries, if necessary ... */ - for (x = vm_nphysmem ; x > lcv ; x--) - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x - 1); - } -#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - { - int x; - /* sort by largest segment first */ - for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) - if ((end - start) > - (VM_PHYSMEM_PTR(lcv)->end - VM_PHYSMEM_PTR(lcv)->start)) - break; - ps = VM_PHYSMEM_PTR(lcv); - /* move back other entries, if necessary ... */ - for (x = vm_nphysmem ; x > lcv ; x--) - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x - 1); - } -#else - panic("uvm_page_physload: unknown physseg strategy selected!"); -#endif - - ps->start = start; - ps->end = end; - ps->avail_start = avail_start; - ps->avail_end = avail_end; - if (preload) { - ps->pgs = NULL; - } else { - ps->pgs = pgs; - ps->lastpg = pgs + npages; - } - ps->free_list = free_list; - vm_nphysmem++; - - if (!preload) { - uvmpdpol_reinit(); - } -} - -/* - * when VM_PHYSSEG_MAX is 1, we can simplify these functions - */ - -#if VM_PHYSSEG_MAX == 1 -static inline int vm_physseg_find_contig(struct vm_physseg *, int, paddr_t, int *); -#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) -static inline int vm_physseg_find_bsearch(struct vm_physseg *, int, paddr_t, int *); -#else -static inline int vm_physseg_find_linear(struct vm_physseg *, int, paddr_t, int *); -#endif - -/* - * vm_physseg_find: find vm_physseg structure that belongs to a PA - */ -int -vm_physseg_find(paddr_t pframe, int *offp) -{ - -#if VM_PHYSSEG_MAX == 1 - return vm_physseg_find_contig(vm_physmem, vm_nphysseg, pframe, offp); -#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) - return vm_physseg_find_bsearch(vm_physmem, vm_nphysseg, pframe, offp); -#else - return vm_physseg_find_linear(vm_physmem, vm_nphysseg, pframe, offp); -#endif -} - -#if VM_PHYSSEG_MAX == 1 -static inline int -vm_physseg_find_contig(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp) -{ - - /* 'contig' case */ - if (pframe >= segs[0].start && pframe < segs[0].end) { - if (offp) - *offp = pframe - segs[0].start; - return(0); - } - return(-1); -} - -#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) - -static inline int -vm_physseg_find_bsearch(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp) -{ - /* binary search for it */ - u_int start, len, guess; - - /* - * if try is too large (thus target is less than try) we reduce - * the length to trunc(len/2) [i.e. everything smaller than "try"] - * - * if the try is too small (thus target is greater than try) then - * we set the new start to be (try + 1). this means we need to - * reduce the length to (round(len/2) - 1). - * - * note "adjust" below which takes advantage of the fact that - * (round(len/2) - 1) == trunc((len - 1) / 2) - * for any value of len we may have - */ - - for (start = 0, len = nsegs ; len != 0 ; len = len / 2) { - guess = start + (len / 2); /* try in the middle */ - - /* start past our try? */ - if (pframe >= segs[guess].start) { - /* was try correct? */ - if (pframe < segs[guess].end) { - if (offp) - *offp = pframe - segs[guess].start; - return guess; /* got it */ - } - start = guess + 1; /* next time, start here */ - len--; /* "adjust" */ - } else { - /* - * pframe before try, just reduce length of - * region, done in "for" loop - */ - } - } - return(-1); -} - -#else - -static inline int -vm_physseg_find_linear(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp) -{ - /* linear search for it */ - int lcv; - - for (lcv = 0; lcv < nsegs; lcv++) { - if (pframe >= segs[lcv].start && - pframe < segs[lcv].end) { - if (offp) - *offp = pframe - segs[lcv].start; - return(lcv); /* got it */ - } - } - return(-1); -} -#endif - -/* * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages * back from an I/O mapping (ugh!). used in some MD code as well. */ @@@@ -956,12 +674,12 @@@@ struct vm_page * uvm_phys_to_vm_page(paddr_t pa) { paddr_t pf = atop(pa); - int off; - int psi; + paddr_t off; + uvm_physseg_t upm; - psi = vm_physseg_find(pf, &off); - if (psi != -1) - return(&VM_PHYSMEM_PTR(psi)->pgs[off]); + upm = uvm_physseg_find(pf, &off); + if (upm != UVM_PHYSSEG_TYPE_INVALID) + return uvm_physseg_get_pg(upm, off); return(NULL); } @@@@ -985,7 +703,8 @@@@ uvm_page_recolor(int newncolors) struct vm_page *pg; vsize_t bucketcount; size_t bucketmemsize, oldbucketmemsize; - int lcv, color, i, ocolors; + int color, i, ocolors; + int lcv; struct uvm_cpu *ucpu; KASSERT(((newncolors - 1) & newncolors) == 0); @@@@ -1094,6 +813,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) uvm.cpus[cpu_index(ci)] = ucpu; ci->ci_data.cpu_uvm = ucpu; for (lcv = 0; lcv < VM_NFREELIST; lcv++) { + pgfl.pgfl_buckets = (bucketarray + (lcv * uvmexp.ncolors)); uvm_page_init_buckets(&pgfl); ucpu->page_free[lcv].pgfl_buckets = pgfl.pgfl_buckets; @@@@ -1219,7 +939,8 @@@@ struct vm_page * uvm_pagealloc_strat(struct uvm_object *obj, voff_t off, struct vm_anon *anon, int flags, int strat, int free_list) { - int lcv, try1, try2, zeroit = 0, color; + int try1, try2, zeroit = 0, color; + int lcv; struct uvm_cpu *ucpu; struct vm_page *pg; lwp_t *l; @@@@ -2005,7 +1726,7 @@@@ bool uvm_pageismanaged(paddr_t pa) { - return (vm_physseg_find(atop(pa), NULL) != -1); + return (uvm_physseg_find(atop(pa), NULL) != UVM_PHYSSEG_TYPE_INVALID); } /* @@@@ -2015,11 +1736,11 @@@@ uvm_pageismanaged(paddr_t pa) int uvm_page_lookup_freelist(struct vm_page *pg) { - int lcv; + uvm_physseg_t upm; - lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); - KASSERT(lcv != -1); - return (VM_PHYSMEM_PTR(lcv)->free_list); + upm = uvm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); + KASSERT(upm != UVM_PHYSSEG_TYPE_INVALID); + return uvm_physseg_get_free_list(upm); } /* @@@@ -2135,7 +1856,8 @@@@ uvm_page_printit(struct vm_page *pg, boo void uvm_page_printall(void (*pr)(const char *, ...)) { - unsigned i; + uvm_physseg_t i; + paddr_t pfn; struct vm_page *pg; (*pr)("%18s %4s %4s %18s %18s" @@@@ -2143,8 +1865,14 @@@@ uvm_page_printall(void (*pr)(const char " OWNER" #endif "\n", "PAGE", "FLAG", "PQ", "UOBJECT", "UANON"); - for (i = 0; i < vm_nphysmem; i++) { - for (pg = VM_PHYSMEM_PTR(i)->pgs; pg < VM_PHYSMEM_PTR(i)->lastpg; pg++) { + for (i = uvm_physseg_get_first(); + uvm_physseg_valid(i); + i = uvm_physseg_get_next(i)) { + for (pfn = uvm_physseg_get_start(i); + pfn <= uvm_physseg_get_end(i); + pfn++) { + pg = PHYS_TO_VM_PAGE(ptoa(pfn)); + (*pr)("%18p %04x %04x %18p %18p", pg, pg->flags, pg->pqflags, pg->uobject, pg->uanon); Index: sys/uvm/uvm_page.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_page.h,v retrieving revision 1.80 diff -p -u -r1.80 uvm_page.h --- sys/uvm/uvm_page.h 23 Mar 2015 07:59:12 -0000 1.80 +++ sys/uvm/uvm_page.h 13 Dec 2016 12:44:35 -0000 @@@@ -294,24 +294,6 @@@@ struct vm_page { #define VM_PSTRAT_BSEARCH 2 #define VM_PSTRAT_BIGFIRST 3 -/* - * vm_physseg: describes one segment of physical memory - */ -struct vm_physseg { - paddr_t start; /* PF# of first page in segment */ - paddr_t end; /* (PF# of last page in segment) + 1 */ - paddr_t avail_start; /* PF# of first free page in segment */ - paddr_t avail_end; /* (PF# of last free page in segment) +1 */ - struct vm_page *pgs; /* vm_page structures (from start) */ - struct vm_page *lastpg; /* vm_page structure for end */ - int free_list; /* which free list they belong on */ - u_int start_hint; /* start looking for free pages here */ - /* protected by uvm_fpageqlock */ -#ifdef __HAVE_PMAP_PHYSSEG - struct pmap_physseg pmseg; /* pmap specific (MD) data */ -#endif -}; - #ifdef _KERNEL /* @@@@ -321,21 +303,6 @@@@ struct vm_physseg { extern bool vm_page_zero_enable; /* - * physical memory config is stored in vm_physmem. - */ - -#define VM_PHYSMEM_PTR(i) (&vm_physmem[i]) -#if VM_PHYSSEG_MAX == 1 -#define VM_PHYSMEM_PTR_SWAP(i, j) /* impossible */ -#else -#define VM_PHYSMEM_PTR_SWAP(i, j) \ - do { vm_physmem[(i)] = vm_physmem[(j)]; } while (0) -#endif - -extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; -extern int vm_nphysseg; - -/* * prototypes: the following prototypes define the interface to pages */ @@@@ -366,10 +333,13 @@@@ bool uvm_page_locked_p(struct vm_page *) int uvm_page_lookup_freelist(struct vm_page *); -int vm_physseg_find(paddr_t, int *); struct vm_page *uvm_phys_to_vm_page(paddr_t); paddr_t uvm_vm_page_to_phys(const struct vm_page *); +#if !defined(PMAP_STEAL_MEMORY) +bool uvm_page_physget(paddr_t *); +#endif + /* * macros */ Index: sys/uvm/uvm_pglist.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_pglist.c,v retrieving revision 1.67 diff -p -u -r1.67 uvm_pglist.c --- sys/uvm/uvm_pglist.c 26 Oct 2014 01:42:07 -0000 1.67 +++ sys/uvm/uvm_pglist.c 13 Dec 2016 12:44:35 -0000 @@@@ -116,16 +116,15 @@@@ uvm_pglist_add(struct vm_page *pg, struc } static int -uvm_pglistalloc_c_ps(struct vm_physseg *ps, int num, paddr_t low, paddr_t high, +uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, struct pglist *rlist) { signed int candidate, limit, candidateidx, end, idx, skip; - struct vm_page *pgs; int pagemask; bool second_pass; #ifdef DEBUG paddr_t idxpa, lastidxpa; - int cidx = 0; /* XXX: GCC */ + paddr_t cidx = 0; /* XXX: GCC */ #endif #ifdef PGALLOC_VERBOSE printf("pgalloc: contig %d pgs from psi %zd\n", num, ps - vm_physmem); @@@@ -140,26 +139,26 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * /* * Make sure that physseg falls within with range to be allocated from. */ - if (high <= ps->avail_start || low >= ps->avail_end) + if (high <= uvm_physseg_get_avail_start(psi) || low >= uvm_physseg_get_avail_end(psi)) return 0; /* * We start our search at the just after where the last allocation * succeeded. */ - candidate = roundup2(max(low, ps->avail_start + ps->start_hint), alignment); - limit = min(high, ps->avail_end); + candidate = roundup2(max(low, uvm_physseg_get_avail_start(psi) + + uvm_physseg_get_start_hint(psi)), alignment); + limit = min(high, uvm_physseg_get_avail_end(psi)); pagemask = ~((boundary >> PAGE_SHIFT) - 1); skip = 0; second_pass = false; - pgs = ps->pgs; for (;;) { bool ok = true; signed int cnt; if (candidate + num > limit) { - if (ps->start_hint == 0 || second_pass) { + if (uvm_physseg_get_start_hint(psi) == 0 || second_pass) { /* * We've run past the allowable range. */ @@@@ -171,8 +170,9 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * * is were we started. */ second_pass = true; - candidate = roundup2(max(low, ps->avail_start), alignment); - limit = min(limit, ps->avail_start + ps->start_hint); + candidate = roundup2(max(low, uvm_physseg_get_avail_start(psi)), alignment); + limit = min(limit, uvm_physseg_get_avail_start(psi) + + uvm_physseg_get_start_hint(psi)); skip = 0; continue; } @@@@ -192,16 +192,16 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * * Make sure this is a managed physical page. */ - if (vm_physseg_find(candidate, &cidx) != ps - vm_physmem) + if (uvm_physseg_find(candidate, &cidx) != psi) panic("pgalloc contig: botch1"); - if (cidx != candidate - ps->start) + if (cidx != candidate - uvm_physseg_get_start(psi)) panic("pgalloc contig: botch2"); - if (vm_physseg_find(candidate + num - 1, &cidx) != ps - vm_physmem) + if (uvm_physseg_find(candidate + num - 1, &cidx) != psi) panic("pgalloc contig: botch3"); - if (cidx != candidate - ps->start + num - 1) + if (cidx != candidate - uvm_physseg_get_start(psi) + num - 1) panic("pgalloc contig: botch4"); #endif - candidateidx = candidate - ps->start; + candidateidx = candidate - uvm_physseg_get_start(psi); end = candidateidx + num; /* @@@@ -220,15 +220,15 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * * testing most of those pages again in the next pass. */ for (idx = end - 1; idx >= candidateidx + skip; idx--) { - if (VM_PAGE_IS_FREE(&pgs[idx]) == 0) { + if (VM_PAGE_IS_FREE(uvm_physseg_get_pg(psi, idx)) == 0) { ok = false; break; } #ifdef DEBUG if (idx > candidateidx) { - idxpa = VM_PAGE_TO_PHYS(&pgs[idx]); - lastidxpa = VM_PAGE_TO_PHYS(&pgs[idx - 1]); + idxpa = VM_PAGE_TO_PHYS(uvm_physseg_get_pg(psi, idx)); + lastidxpa = VM_PAGE_TO_PHYS(uvm_physseg_get_pg(psi, idx)); if ((lastidxpa + PAGE_SIZE) != idxpa) { /* * Region not contiguous. @@@@ -249,7 +249,7 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * if (ok) { while (skip-- > 0) { - KDASSERT(VM_PAGE_IS_FREE(&pgs[candidateidx + skip])); + KDASSERT(VM_PAGE_IS_FREE(uvm_physseg_get_pg(psi, candidateidx + skip))); } #ifdef PGALLOC_VERBOSE printf(": ok\n"); @@@@ -280,19 +280,22 @@@@ uvm_pglistalloc_c_ps(struct vm_physseg * /* * we have a chunk of memory that conforms to the requested constraints. */ - for (idx = candidateidx, pgs += idx; idx < end; idx++, pgs++) - uvm_pglist_add(pgs, rlist); + for (idx = candidateidx; idx < end; idx++) + uvm_pglist_add(uvm_physseg_get_pg(psi, idx), rlist); /* * the next time we need to search this segment, start after this * chunk of pages we just allocated. */ - ps->start_hint = candidate + num - ps->avail_start; - KASSERTMSG(ps->start_hint <= ps->avail_end - ps->avail_start, + uvm_physseg_set_start_hint(psi, candidate + num - + uvm_physseg_get_avail_start(psi)); + KASSERTMSG(uvm_physseg_get_start_hint(psi) <= + uvm_physseg_get_avail_end(psi) - uvm_physseg_get_avail_start(psi), "%x %u (%#x) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", candidate + num, - ps->start_hint, ps->start_hint, ps->avail_end, ps->avail_start, - ps->avail_end - ps->avail_start); + uvm_physseg_get_start_hint(psi), uvm_physseg_get_start_hint(psi), + uvm_physseg_get_avail_end(psi), uvm_physseg_get_avail_start(psi), + uvm_physseg_get_avail_end(psi) - uvm_physseg_get_avail_start(psi)); #ifdef PGALLOC_VERBOSE printf("got %d pgs\n", num); @@@@ -304,10 +307,10 @@@@ static int uvm_pglistalloc_contig(int num, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, struct pglist *rlist) { - int fl, psi; - struct vm_physseg *ps; + int fl; int error; + uvm_physseg_t psi; /* Default to "lose". */ error = ENOMEM; @@@@ -322,17 +325,16 @@@@ uvm_pglistalloc_contig(int num, paddr_t for (fl = 0; fl < VM_NFREELIST; fl++) { #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--) + for (psi = uvm_physseg_get_last(); uvm_physseg_valid(psi); psi = uvm_physseg_get_prev(psi)) + #else - for (psi = 0 ; psi < vm_nphysseg ; psi++) + for (psi = uvm_physseg_get_first(); uvm_physseg_valid(psi); psi = uvm_physseg_get_next(psi)) #endif { - ps = &vm_physmem[psi]; - - if (ps->free_list != fl) + if (uvm_physseg_get_free_list(psi) != fl) continue; - num -= uvm_pglistalloc_c_ps(ps, num, low, high, + num -= uvm_pglistalloc_c_ps(psi, num, low, high, alignment, boundary, rlist); if (num == 0) { #ifdef PGALLOC_VERBOSE @@@@ -358,59 +360,62 @@@@ out: } static int -uvm_pglistalloc_s_ps(struct vm_physseg *ps, int num, paddr_t low, paddr_t high, +uvm_pglistalloc_s_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, struct pglist *rlist) { int todo, limit, candidate; struct vm_page *pg; bool second_pass; #ifdef PGALLOC_VERBOSE - printf("pgalloc: simple %d pgs from psi %zd\n", num, ps - vm_physmem); + printf("pgalloc: simple %d pgs from psi %zd\n", num, psi); #endif KASSERT(mutex_owned(&uvm_fpageqlock)); - KASSERT(ps->start <= ps->avail_start); - KASSERT(ps->start <= ps->avail_end); - KASSERT(ps->avail_start <= ps->end); - KASSERT(ps->avail_end <= ps->end); + KASSERT(uvm_physseg_get_start(psi) <= uvm_physseg_get_avail_start(psi)); + KASSERT(uvm_physseg_get_start(psi) <= uvm_physseg_get_avail_end(psi)); + KASSERT(uvm_physseg_get_avail_start(psi) <= uvm_physseg_get_end(psi)); + KASSERT(uvm_physseg_get_avail_end(psi) <= uvm_physseg_get_end(psi)); low = atop(low); high = atop(high); todo = num; - candidate = max(low, ps->avail_start + ps->start_hint); - limit = min(high, ps->avail_end); - pg = &ps->pgs[candidate - ps->start]; + candidate = max(low, uvm_physseg_get_avail_start(psi) + + uvm_physseg_get_start_hint(psi)); + limit = min(high, uvm_physseg_get_avail_end(psi)); + pg = uvm_physseg_get_pg(psi, candidate - uvm_physseg_get_start(psi)); second_pass = false; /* * Make sure that physseg falls within with range to be allocated from. */ - if (high <= ps->avail_start || low >= ps->avail_end) + if (high <= uvm_physseg_get_avail_start(psi) || + low >= uvm_physseg_get_avail_end(psi)) return 0; again: for (;; candidate++, pg++) { if (candidate >= limit) { - if (ps->start_hint == 0 || second_pass) { + if (uvm_physseg_get_start_hint(psi) == 0 || second_pass) { candidate = limit - 1; break; } second_pass = true; - candidate = max(low, ps->avail_start); - limit = min(limit, ps->avail_start + ps->start_hint); - pg = &ps->pgs[candidate - ps->start]; + candidate = max(low, uvm_physseg_get_avail_start(psi)); + limit = min(limit, uvm_physseg_get_avail_start(psi) + + uvm_physseg_get_start_hint(psi)); + pg = uvm_physseg_get_pg(psi, candidate - uvm_physseg_get_start(psi)); goto again; } #if defined(DEBUG) { - int cidx = 0; - const int bank = vm_physseg_find(candidate, &cidx); - KDASSERTMSG(bank == ps - vm_physmem, - "vm_physseg_find(%#x) (%d) != ps %zd", - candidate, bank, ps - vm_physmem); - KDASSERTMSG(cidx == candidate - ps->start, - "vm_physseg_find(%#x): %#x != off %"PRIxPADDR, - candidate, cidx, candidate - ps->start); + paddr_t cidx = 0; + const uvm_physseg_t bank = uvm_physseg_find(candidate, &cidx); + KDASSERTMSG(bank == psi, + "uvm_physseg_find(%#x) (%"PRIxPHYSMEM ") != psi %"PRIxPHYSMEM, + candidate, bank, psi); + KDASSERTMSG(cidx == candidate - uvm_physseg_get_start(psi), + "uvm_physseg_find(%#x): %#"PRIxPADDR" != off %"PRIxPADDR, + candidate, cidx, candidate - uvm_physseg_get_start(psi)); } #endif if (VM_PAGE_IS_FREE(pg) == 0) @@@@ -426,12 +431,16 @@@@ again: * The next time we need to search this segment, * start just after the pages we just allocated. */ - ps->start_hint = candidate + 1 - ps->avail_start; - KASSERTMSG(ps->start_hint <= ps->avail_end - ps->avail_start, + uvm_physseg_set_start_hint(psi, candidate + 1 - uvm_physseg_get_avail_start(psi)); + KASSERTMSG(uvm_physseg_get_start_hint(psi) <= uvm_physseg_get_avail_end(psi) - + uvm_physseg_get_avail_start(psi), "%#x %u (%#x) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", candidate + 1, - ps->start_hint, ps->start_hint, ps->avail_end, ps->avail_start, - ps->avail_end - ps->avail_start); + uvm_physseg_get_start_hint(psi), + uvm_physseg_get_start_hint(psi), + uvm_physseg_get_avail_end(psi), + uvm_physseg_get_avail_start(psi), + uvm_physseg_get_avail_end(psi) - uvm_physseg_get_avail_start(psi)); #ifdef PGALLOC_VERBOSE printf("got %d pgs\n", num - todo); @@@@ -443,9 +452,10 @@@@ static int uvm_pglistalloc_simple(int num, paddr_t low, paddr_t high, struct pglist *rlist, int waitok) { - int fl, psi, error; - struct vm_physseg *ps; + int fl, error; + uvm_physseg_t psi; + /* Default to "lose". */ error = ENOMEM; @@@@ -461,17 +471,16 @@@@ again: for (fl = 0; fl < VM_NFREELIST; fl++) { #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--) + for (psi = uvm_physseg_get_last(); uvm_physseg_valid(psi); psi = uvm_physseg_get_prev(psi)) + #else - for (psi = 0 ; psi < vm_nphysseg ; psi++) + for (psi = uvm_physseg_get_first(); uvm_physseg_valid(psi); psi = uvm_physseg_get_next(psi)) #endif { - ps = &vm_physmem[psi]; - - if (ps->free_list != fl) + if (uvm_physseg_get_free_list(psi) != fl) continue; - num -= uvm_pglistalloc_s_ps(ps, num, low, high, rlist); + num -= uvm_pglistalloc_s_ps(psi, num, low, high, rlist); if (num == 0) { error = 0; goto out; Index: sys/uvm/uvm_physseg.c =================================================================== RCS file: sys/uvm/uvm_physseg.c diff -N sys/uvm/uvm_physseg.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/uvm/uvm_physseg.c 13 Dec 2016 12:44:35 -0000 @@@@ -0,0 +1,1351 @@@@ +/* $NetBSD$ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * Copyright (c) 1991, 1993, The Regents of the University of California. + * + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @@(#)vm_page.h 7.3 (Berkeley) 4/21/91 + * from: Id: uvm_page.h,v 1.1.2.6 1998/02/04 02:31:42 chuck Exp + * + * + * Copyright (c) 1987, 1990 Carnegie-Mellon University. + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Consolidated API from uvm_page.c and others. + * Consolidated and designed by Cherry G. Mathew + * rbtree(3) backing implementation by: + * Santhosh N. Raju + */ + +#ifdef _KERNEL_OPT +#include "opt_uvm.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * vm_physseg: describes one segment of physical memory + */ +struct uvm_physseg { + struct rb_node rb_node; /* tree information */ + paddr_t start; /* PF# of first page in segment */ + paddr_t end; /* (PF# of last page in segment) + 1 */ + paddr_t avail_start; /* PF# of first free page in segment */ + paddr_t avail_end; /* (PF# of last free page in segment) +1 */ + struct vm_page *pgs; /* vm_page structures (from start) */ + struct extent *ext; /* extent(9) structure to manage pgs[] */ + int free_list; /* which free list they belong on */ + u_int start_hint; /* start looking for free pages here */ + /* protected by uvm_fpageqlock */ +#ifdef __HAVE_PMAP_PHYSSEG + struct pmap_physseg pmseg; /* pmap specific (MD) data */ +#endif +}; + +/* + * These functions are reserved for uvm(9) internal use and are not + * exported in the header file uvm_physseg.h + * + * Thus they are redefined here. + */ +void uvm_physseg_init_seg(uvm_physseg_t, struct vm_page *); +void uvm_physseg_seg_chomp_slab(uvm_physseg_t, struct vm_page *, size_t); + +/* returns a pgs array */ +struct vm_page *uvm_physseg_seg_alloc_from_slab(uvm_physseg_t, size_t); + +#if defined(UVM_HOTPLUG) /* rbtree impementation */ + +#define HANDLE_TO_PHYSSEG_NODE(h) ((struct uvm_physseg *)(h)) +#define PHYSSEG_NODE_TO_HANDLE(u) ((uvm_physseg_t)(u)) + + +struct uvm_physseg_graph { + struct rb_tree rb_tree; /* Tree for entries */ + int nentries; /* Number of entries */ +}; + +static struct uvm_physseg_graph uvm_physseg_graph; + +/* + * Note on kmem(9) allocator usage: + * We take the conservative approach that plug/unplug are allowed to + * fail in high memory stress situations. + * + * We want to avoid re-entrant situations in which one plug/unplug + * operation is waiting on a previous one to complete, since this + * makes the design more complicated than necessary. + * + * We may review this and change its behaviour, once the use cases + * become more obvious. + */ + +/* + * Special alloc()/free() functions for boot time support: + * We assume that alloc() at boot time is only for new 'vm_physseg's + * This allows us to use a static array for memory allocation at boot + * time. Thus we avoid using kmem(9) which is not ready at this point + * in boot. + * + * After kmem(9) is ready, we use it. We currently discard any free()s + * to this static array, since the size is small enough to be a + * trivial waste on all architectures we run on. + * + */ + +static size_t nseg = 0; +static struct uvm_physseg uvm_physseg[VM_PHYSSEG_MAX]; + +static void * +uvm_physseg_alloc(size_t sz) +{ + /* + * During boot time, we only support allocating vm_physseg + * entries from the static array. + * We need to assert for this. + */ + + if (__predict_false(uvm.page_init_done == false)) { + if (sz % sizeof(struct uvm_physseg)) + panic("%s: tried to alloc size other than multiple" + "of struct uvm_physseg at boot\n", __func__); + + size_t n = sz / sizeof(struct uvm_physseg); + nseg += n; + + KASSERT(nseg > 0 && nseg <= VM_PHYSSEG_MAX); + + return &uvm_physseg[nseg - n]; + } + + return kmem_zalloc(sz, KM_NOSLEEP); +} + +static void +uvm_physseg_free(void *p, size_t sz) +{ + /* + * This is a bit tricky. We do allow simulation of free() + * during boot (for eg: when MD code is "steal"ing memory, + * and the segment has been exhausted (and thus needs to be + * free() - ed. + * free() also complicates things because we leak the + * free(). Therefore calling code can't assume that free()-ed + * memory is available for alloc() again, at boot time. + * + * Thus we can't explicitly disallow free()s during + * boot time. However, the same restriction for alloc() + * applies to free(). We only allow vm_physseg related free()s + * via this function during boot time. + */ + + if (__predict_false(uvm.page_init_done == false)) { + if (sz % sizeof(struct uvm_physseg)) + panic("%s: tried to free size other than struct uvm_physseg" + "at boot\n", __func__); + + } + + /* + * Could have been in a single if(){} block - split for + * clarity + */ + + if ((struct uvm_physseg *)p >= uvm_physseg && + (struct uvm_physseg *)p < (uvm_physseg + VM_PHYSSEG_MAX)) { + if (sz % sizeof(struct uvm_physseg)) + panic("%s: tried to free() other than struct uvm_physseg" + "from static array\n", __func__); + + if ((sz / sizeof(struct uvm_physseg)) >= VM_PHYSSEG_MAX) + panic("%s: tried to free() the entire static array!", __func__); + return; /* Nothing to free */ + } + + kmem_free(p, sz); +} + +/* XXX: Multi page size */ +bool +uvm_physseg_plug(paddr_t pfn, size_t pages, uvm_physseg_t *psp) +{ + int preload; + size_t slabpages; + struct uvm_physseg *ps, *current_ps = NULL; + struct vm_page *slab = NULL, *pgs = NULL; + +#ifdef DEBUG + paddr_t off; + uvm_physseg_t upm; + upm = uvm_physseg_find(pfn, &off); + + ps = HANDLE_TO_PHYSSEG_NODE(upm); + + if (ps != NULL) /* XXX; do we allow "update" plugs ? */ + return false; +#endif + + /* + * do we have room? + */ + + ps = uvm_physseg_alloc(sizeof (struct uvm_physseg)); + if (ps == NULL) { + printf("uvm_page_physload: unable to load physical memory " + "segment\n"); + printf("\t%d segments allocated, ignoring 0x%"PRIxPADDR" -> 0x%"PRIxPADDR"\n", + VM_PHYSSEG_MAX, pfn, pfn + pages + 1); + printf("\tincrease VM_PHYSSEG_MAX\n"); + return false; + } + + /* span init */ + ps->start = pfn; + ps->end = pfn + pages; + + /* + * XXX: Ugly hack because uvmexp.npages accounts for only + * those pages in the segment included below as well - this + * should be legacy and removed. + */ + + ps->avail_start = ps->start; + ps->avail_end = ps->end; + + /* + * check to see if this is a "preload" (i.e. uvm_page_init hasn't been + * called yet, so kmem is not available). + */ + + preload = 1; /* We are going to assume it is a preload */ + + RB_TREE_FOREACH(current_ps, &(uvm_physseg_graph.rb_tree)) { + /* If there are non NULL pages then we are not in a preload */ + if (current_ps->pgs != NULL) { + preload = 0; + /* Try to scavenge from earlier unplug()s. */ + pgs = uvm_physseg_seg_alloc_from_slab(current_ps, pages); + + if (pgs != NULL) { + break; + } + } + } + + + /* + * if VM is already running, attempt to kmem_alloc vm_page structures + */ + + if (!preload) { + if (pgs == NULL) { /* Brand new */ + /* Iteratively try alloc down from uvmexp.npages */ + for (slabpages = (size_t) uvmexp.npages; slabpages >= pages; slabpages--) { + slab = kmem_zalloc(sizeof *pgs * (long unsigned int)slabpages, KM_NOSLEEP); + if (slab != NULL) + break; + } + + if (slab == NULL) { + uvm_physseg_free(ps, sizeof(struct uvm_physseg)); + return false; + } + + uvm_physseg_seg_chomp_slab(ps, slab, (size_t) slabpages); + /* We allocate enough for this plug */ + pgs = uvm_physseg_seg_alloc_from_slab(ps, pages); + + if (pgs == NULL) { + printf("unable to uvm_physseg_seg_alloc_from_slab() from backend\n"); + return false; + } + } else { + /* Reuse scavenged extent */ + ps->ext = current_ps->ext; + } + + physmem += pages; + uvmpdpol_reinit(); + } else { /* Boot time - see uvm_page.c:uvm_page_init() */ + pgs = NULL; + ps->pgs = pgs; + } + + /* + * now insert us in the proper place in uvm_physseg_graph.rb_tree + */ + + current_ps = rb_tree_insert_node(&(uvm_physseg_graph.rb_tree), ps); + if (current_ps != ps) { + panic("uvm_page_physload: Duplicate address range detected!"); + } + uvm_physseg_graph.nentries++; + + /* + * uvm_pagefree() requires the PHYS_TO_VM_PAGE(pgs[i]) on the + * newly allocated pgs[] to return the correct value. This is + * a bit of a chicken and egg problem, since it needs + * uvm_physseg_find() to succeed. For this, the node needs to + * be inserted *before* uvm_physseg_init_seg() happens. + * + * During boot, this happens anyway, since + * uvm_physseg_init_seg() is called later on and separately + * from uvm_page.c:uvm_page_init(). + * In the case of hotplug we need to ensure this. + */ + + if (__predict_true(!preload)) + uvm_physseg_init_seg(ps, pgs); + + if (psp != NULL) + *psp = ps; + + return true; +} + +static int +uvm_physseg_compare_nodes(void *ctx, const void *nnode1, const void *nnode2) +{ + const struct uvm_physseg *enode1 = nnode1; + const struct uvm_physseg *enode2 = nnode2; + + KASSERT(enode1->start < enode2->start || enode1->start >= enode2->end); + KASSERT(enode2->start < enode1->start || enode2->start >= enode1->end); + + if (enode1->start < enode2->start) + return -1; + if (enode1->start >= enode2->end) + return 1; + return 0; +} + +static int +uvm_physseg_compare_key(void *ctx, const void *nnode, const void *pkey) +{ + const struct uvm_physseg *enode = nnode; + const paddr_t pa = *(const paddr_t *) pkey; + + if(enode->start <= pa && pa < enode->end) + return 0; + if (enode->start < pa) + return -1; + if (enode->end > pa) + return 1; + + return 0; +} + +static const rb_tree_ops_t uvm_physseg_tree_ops = { + .rbto_compare_nodes = uvm_physseg_compare_nodes, + .rbto_compare_key = uvm_physseg_compare_key, + .rbto_node_offset = offsetof(struct uvm_physseg, rb_node), + .rbto_context = NULL +}; + +/* + * uvm_physseg_init: init the physmem + * + * => physmem unit should not be in use at this point + */ + +void +uvm_physseg_init(void) { + rb_tree_init(&(uvm_physseg_graph.rb_tree), &uvm_physseg_tree_ops); + uvm_physseg_graph.nentries = 0; +} + +uvm_physseg_t +uvm_physseg_get_next(uvm_physseg_t upm) +{ + return (uvm_physseg_t) rb_tree_iterate(&(uvm_physseg_graph.rb_tree), upm, + RB_DIR_RIGHT); +} + +uvm_physseg_t +uvm_physseg_get_prev(uvm_physseg_t upm) +{ + return (uvm_physseg_t) rb_tree_iterate(&(uvm_physseg_graph.rb_tree), upm, + RB_DIR_LEFT); +} + +uvm_physseg_t +uvm_physseg_get_last(void) +{ + return (uvm_physseg_t) RB_TREE_MAX(&(uvm_physseg_graph.rb_tree)); +} + +uvm_physseg_t +uvm_physseg_get_first(void) +{ + return (uvm_physseg_t) RB_TREE_MIN(&(uvm_physseg_graph.rb_tree)); +} + +paddr_t +uvm_physseg_get_highest_frame(void) +{ + struct uvm_physseg *ps = + (uvm_physseg_t) RB_TREE_MAX(&(uvm_physseg_graph.rb_tree)); + + return ps->end - 1; +} + +/* + * uvm_page_physunload: unload physical memory and return it to + * caller. + */ +bool +uvm_page_physunload(uvm_physseg_t upm, int freelist, paddr_t *paddrp) +{ + struct uvm_physseg *seg; + + seg = HANDLE_TO_PHYSSEG_NODE(upm); + + if (seg->free_list != freelist) { + paddrp = NULL; + return false; + } + + /* + * During cold boot, what we're about to unplug hasn't been + * put on the uvm freelist, nor has uvmexp.npages been + * updated. (This happens in uvm_page.c:uvm_page_init()) + * + * For hotplug, we assume here that the pages being unloaded + * here are completely out of sight of uvm (ie; not on any uvm + * lists), and that uvmexp.npages has been suitably + * decremented before we're called. + * + * XXX: will avail_end == start if avail_start < avail_end? + */ + + /* try from front */ + if (seg->avail_start == seg->start && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_start); + return uvm_physseg_unplug(seg->avail_start, 1); + } + + /* try from rear */ + if (seg->avail_end == seg->end && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_end - 1); + return uvm_physseg_unplug(seg->avail_end - 1, 1); + } + + return false; +} + +bool +uvm_page_physunload_force(uvm_physseg_t upm, int freelist, paddr_t *paddrp) +{ + struct uvm_physseg *seg; + + seg = HANDLE_TO_PHYSSEG_NODE(upm); + + /* any room in this bank? */ + if (seg->avail_start >= seg->avail_end) { + paddrp = NULL; + return false; /* nope */ + } + + *paddrp = ctob(seg->avail_start); + + /* Always unplug from front */ + return uvm_physseg_unplug(seg->avail_start, 1); +} + + +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ +uvm_physseg_t +uvm_physseg_find(paddr_t pframe, psize_t *offp) +{ + struct uvm_physseg * ps = NULL; + + ps = rb_tree_find_node(&(uvm_physseg_graph.rb_tree), &pframe); + + if(ps != NULL && offp != NULL) + *offp = pframe - ps->start; + + return ps; +} + +#if defined(PMAP_STEAL_MEMORY) +void +uvm_physseg_set_avail_start(uvm_physseg_t upm, paddr_t avail_start) +{ + struct uvm_physseg *ps = HANDLE_TO_PHYSSEG_NODE(upm); + +#if defined(DIAGNOSTIC) + paddr_t avail_end; + avail_end = uvm_physseg_get_avail_end(upm); +#endif + KASSERT(avail_start < avail_end && avail_start >= ps->start); + ps->avail_start = avail_start; +} +void uvm_physseg_set_avail_end(uvm_physseg_t upm, paddr_t avail_end) +{ + struct uvm_physseg *ps = HANDLE_TO_PHYSSEG_NODE(upm); + +#if defined(DIAGNOSTIC) + paddr_t avail_start; + avail_start = uvm_physseg_get_avail_start(upm); +#endif + + KASSERT(avail_end > avail_start && avail_end <= ps->end); + + ps->avail_end = avail_end; +} + +#endif /* PMAP_STEAL_MEMORY */ +#else /* UVM_HOTPLUG */ + +/* + * physical memory config is stored in vm_physmem. + */ + +#define VM_PHYSMEM_PTR(i) (&vm_physmem[i]) +#if VM_PHYSSEG_MAX == 1 +#define VM_PHYSMEM_PTR_SWAP(i, j) /* impossible */ +#else +#define VM_PHYSMEM_PTR_SWAP(i, j) \ + do { vm_physmem[(i)] = vm_physmem[(j)]; } while (0) +#endif + +#define HANDLE_TO_PHYSSEG_NODE(h) (VM_PHYSMEM_PTR((int)h)) +#define PHYSSEG_NODE_TO_HANDLE(u) ((int)((vsize_t) (u - vm_physmem) / sizeof(struct uvm_physseg))) + +static struct uvm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ +static int vm_nphysseg = 0; /* XXXCDC: uvm.nphysseg */ +#define vm_nphysmem vm_nphysseg + +void +uvm_physseg_init(void) { + /* XXX: Provisioning for rb_tree related init(s) */ + return; +} + +int +uvm_physseg_get_next(uvm_physseg_t lcv) +{ + return (lcv + 1); +} + +int +uvm_physseg_get_prev(uvm_physseg_t lcv) +{ + return (lcv - 1); +} + +int +uvm_physseg_get_last(void) +{ + return (vm_nphysseg - 1); +} + +int +uvm_physseg_get_first(void) +{ + return 0; +} + +paddr_t +uvm_physseg_get_highest_frame(void) +{ + int lcv; + paddr_t last = 0; + struct uvm_physseg *ps; + + for (lcv = 0; lcv < vm_nphysseg; lcv++) { + ps = VM_PHYSMEM_PTR(lcv); + if (last < ps->end) + last = ps->end; + } + + return last; +} + +/* + * uvm_page_physunload: unload physical memory and return it to + * caller. + */ +bool +uvm_page_physunload(uvm_physseg_t psi, int freelist, paddr_t *paddrp) +{ + int x; + struct uvm_physseg *seg; + + seg = VM_PHYSMEM_PTR(psi); + + if (seg->free_list != freelist) { + paddrp = NULL; + return false; + } + + /* try from front */ + if (seg->avail_start == seg->start && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_start); + seg->avail_start++; + seg->start++; + /* nothing left? nuke it */ + if (seg->avail_start == seg->end) { + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); + } + return (true); + } + + /* try from rear */ + if (seg->avail_end == seg->end && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_end - 1); + seg->avail_end--; + seg->end--; + /* nothing left? nuke it */ + if (seg->avail_end == seg->start) { + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); + } + return (true); + } + + return false; +} + +bool +uvm_page_physunload_force(uvm_physseg_t psi, int freelist, paddr_t *paddrp) +{ + int x; + struct uvm_physseg *seg; + + seg = VM_PHYSMEM_PTR(psi); + + /* any room in this bank? */ + if (seg->avail_start >= seg->avail_end) { + paddrp = NULL; + return false; /* nope */ + } + + *paddrp = ctob(seg->avail_start); + seg->avail_start++; + /* truncate! */ + seg->start = seg->avail_start; + + /* nothing left? nuke it */ + if (seg->avail_start == seg->end) { + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); + } + return (true); +} + +bool +uvm_physseg_plug(paddr_t pfn, size_t pages, uvm_physseg_t *psp) +{ + int preload, lcv; + struct vm_page *pgs; + struct uvm_physseg *ps; + +#ifdef DEBUG + paddr_t off; + uvm_physseg_t upm; + upm = uvm_physseg_find(pfn, &off); + + if (uvm_physseg_valid(upm)) /* XXX; do we allow "update" plugs ? */ + return false; +#endif + + paddr_t start = pfn; + paddr_t end = pfn + pages; + paddr_t avail_start = start; + paddr_t avail_end = end; + + if (uvmexp.pagesize == 0) + panic("uvm_page_physload: page size not set!"); + + /* + * do we have room? + */ + + if (vm_nphysmem == 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", + VM_PHYSSEG_MAX, (long long)start, (long long)end); + printf("\tincrease VM_PHYSSEG_MAX\n"); + if (psp != NULL) + *psp = UVM_PHYSSEG_TYPE_INVALID_OVERFLOW; + return false; + } + + /* + * check to see if this is a "preload" (i.e. uvm_page_init hasn't been + * called yet, so kmem is not available). + */ + + for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { + if (VM_PHYSMEM_PTR(lcv)->pgs) + break; + } + preload = (lcv == vm_nphysmem); + + /* + * if VM is already running, attempt to kmem_alloc vm_page structures + */ + + if (!preload) { + panic("uvm_page_physload: tried to add RAM after vm_mem_init"); + } else { + pgs = NULL; + } + + /* + * now insert us in the proper place in vm_physmem[] + */ + +#if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) + /* random: put it at the end (easy!) */ + ps = VM_PHYSMEM_PTR(vm_nphysmem); +#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_PTR(lcv)->start) + break; + ps = VM_PHYSMEM_PTR(lcv); + /* move back other entries, if necessary ... */ + for (x = vm_nphysmem ; x > lcv ; x--) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x - 1); + } +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) + { + int x; + /* sort by largest segment first */ + for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) + if ((end - start) > + (VM_PHYSMEM_PTR(lcv)->end - VM_PHYSMEM_PTR(lcv)->start)) + break; + ps = VM_PHYSMEM_PTR(lcv); + /* move back other entries, if necessary ... */ + for (x = vm_nphysmem ; x > lcv ; x--) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x - 1); + } +#else + panic("uvm_page_physload: unknown physseg strategy selected!"); +#endif + + ps->start = start; + ps->end = end; + ps->avail_start = avail_start; + ps->avail_end = avail_end; + + ps->pgs = pgs; + + vm_nphysmem++; + + if (psp != NULL) + *psp = lcv; + + return true; +} + +/* + * when VM_PHYSSEG_MAX is 1, we can simplify these functions + */ + +#if VM_PHYSSEG_MAX == 1 +static inline int vm_physseg_find_contig(struct uvm_physseg *, int, paddr_t, psize_t *); +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) +static inline int vm_physseg_find_bsearch(struct uvm_physseg *, int, paddr_t, psize_t *); +#else +static inline int vm_physseg_find_linear(struct uvm_physseg *, int, paddr_t, psize_t *); +#endif + +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ +int +uvm_physseg_find(paddr_t pframe, psize_t *offp) +{ + +#if VM_PHYSSEG_MAX == 1 + return vm_physseg_find_contig(vm_physmem, vm_nphysseg, pframe, offp); +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) + return vm_physseg_find_bsearch(vm_physmem, vm_nphysseg, pframe, offp); +#else + return vm_physseg_find_linear(vm_physmem, vm_nphysseg, pframe, offp); +#endif +} + +#if VM_PHYSSEG_MAX == 1 +static inline int +vm_physseg_find_contig(struct uvm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ + + /* 'contig' case */ + if (pframe >= segs[0].start && pframe < segs[0].end) { + if (offp) + *offp = pframe - segs[0].start; + return(0); + } + return(-1); +} + +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) + +static inline int +vm_physseg_find_bsearch(struct uvm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ + /* binary search for it */ + int start, len, guess; + + /* + * if try is too large (thus target is less than try) we reduce + * the length to trunc(len/2) [i.e. everything smaller than "try"] + * + * if the try is too small (thus target is greater than try) then + * we set the new start to be (try + 1). this means we need to + * reduce the length to (round(len/2) - 1). + * + * note "adjust" below which takes advantage of the fact that + * (round(len/2) - 1) == trunc((len - 1) / 2) + * for any value of len we may have + */ + + for (start = 0, len = nsegs ; len != 0 ; len = len / 2) { + guess = start + (len / 2); /* try in the middle */ + + /* start past our try? */ + if (pframe >= segs[guess].start) { + /* was try correct? */ + if (pframe < segs[guess].end) { + if (offp) + *offp = pframe - segs[guess].start; + return guess; /* got it */ + } + start = guess + 1; /* next time, start here */ + len--; /* "adjust" */ + } else { + /* + * pframe before try, just reduce length of + * region, done in "for" loop + */ + } + } + return(-1); +} + +#else + +static inline int +vm_physseg_find_linear(struct uvm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ + /* linear search for it */ + int lcv; + + for (lcv = 0; lcv < nsegs; lcv++) { + if (pframe >= segs[lcv].start && + pframe < segs[lcv].end) { + if (offp) + *offp = pframe - segs[lcv].start; + return(lcv); /* got it */ + } + } + return(-1); +} +#endif +#endif /* UVM_HOTPLUG */ + +bool +uvm_physseg_valid(uvm_physseg_t upm) +{ + struct uvm_physseg *ps; + + if (upm == UVM_PHYSSEG_TYPE_INVALID || + upm == UVM_PHYSSEG_TYPE_INVALID_EMPTY || + upm == UVM_PHYSSEG_TYPE_INVALID_OVERFLOW) + return false; + + /* + * This is the delicate init dance - + * needs to go with the dance. + */ + if (uvm.page_init_done != true) + return true; + + ps = HANDLE_TO_PHYSSEG_NODE(upm); + + /* Extra checks needed only post uvm_page_init() */ + if (ps->pgs == NULL) + return false; + + /* XXX: etc. */ + + return true; + +} + +/* + * Boot protocol dictates that these must be able to return partially + * initialised segments. + */ +paddr_t +uvm_physseg_get_start(uvm_physseg_t upm) +{ + if (uvm_physseg_valid(upm) == false) + return (paddr_t) -1; + + return HANDLE_TO_PHYSSEG_NODE(upm)->start; +} + +paddr_t +uvm_physseg_get_end(uvm_physseg_t upm) +{ + if (uvm_physseg_valid(upm) == false) + return (paddr_t) -1; + + return HANDLE_TO_PHYSSEG_NODE(upm)->end; +} + +paddr_t +uvm_physseg_get_avail_start(uvm_physseg_t upm) +{ + if (uvm_physseg_valid(upm) == false) + return (paddr_t) -1; + + return HANDLE_TO_PHYSSEG_NODE(upm)->avail_start; +} + +paddr_t +uvm_physseg_get_avail_end(uvm_physseg_t upm) +{ + if (uvm_physseg_valid(upm) == false) + return (paddr_t) -1; + + return HANDLE_TO_PHYSSEG_NODE(upm)->avail_end; +} + +struct vm_page * +uvm_physseg_get_pg(uvm_physseg_t upm, paddr_t idx) +{ + /* XXX: uvm_physseg_valid() */ + return &HANDLE_TO_PHYSSEG_NODE(upm)->pgs[idx]; +} + +#ifdef __HAVE_PMAP_PHYSSEG +struct pmap_physseg * +uvm_physseg_get_pmseg(uvm_physseg_t upm) +{ + /* XXX: uvm_physseg_valid() */ + return &(HANDLE_TO_PHYSSEG_NODE(upm)->pmseg); +} +#endif + +int +uvm_physseg_get_free_list(uvm_physseg_t upm) +{ + return HANDLE_TO_PHYSSEG_NODE(upm)->free_list; +} + +u_int +uvm_physseg_get_start_hint(uvm_physseg_t upm) +{ + return HANDLE_TO_PHYSSEG_NODE(upm)->start_hint; +} + +bool +uvm_physseg_set_start_hint(uvm_physseg_t upm, u_int start_hint) +{ + if (uvm_physseg_valid(upm) == false) + return false; + + HANDLE_TO_PHYSSEG_NODE(upm)->start_hint = start_hint; + return true; +} + +void +uvm_physseg_init_seg(uvm_physseg_t upm, struct vm_page *pgs) +{ + psize_t i; + psize_t n; + paddr_t paddr; + struct uvm_physseg *seg; + + KASSERT(upm != UVM_PHYSSEG_TYPE_INVALID && pgs != NULL); + + seg = HANDLE_TO_PHYSSEG_NODE(upm); + KASSERT(seg != NULL); + KASSERT(seg->pgs == NULL); + + n = seg->end - seg->start; + seg->pgs = pgs; + + /* init and free vm_pages (we've already zeroed them) */ + paddr = ctob(seg->start); + for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) { + seg->pgs[i].phys_addr = paddr; +#ifdef __HAVE_VM_PAGE_MD + VM_MDPAGE_INIT(&seg->pgs[i]); +#endif + if (atop(paddr) >= seg->avail_start && + atop(paddr) < seg->avail_end) { + uvmexp.npages++; + mutex_enter(&uvm_pageqlock); + /* add page to free pool */ + uvm_pagefree(&seg->pgs[i]); + mutex_exit(&uvm_pageqlock); + } + } +} + +void +uvm_physseg_seg_chomp_slab(uvm_physseg_t upm, struct vm_page *pgs, size_t n) +{ + struct uvm_physseg *seg = HANDLE_TO_PHYSSEG_NODE(upm); + + /* One per segment at boot */ +#define UVM_PHYSSEG_BOOT_UNPLUG_MAX VM_PHYSSEG_MAX /* max number of pre-boot unplug()s allowed */ + static struct extent_region erboot[UVM_PHYSSEG_BOOT_UNPLUG_MAX]; + + if (__predict_false(uvm.page_init_done == false)) { + seg->ext = extent_create("Boot time slab", (u_long) pgs, (u_long) (pgs + n), erboot, sizeof(erboot), 0); + } else { + seg->ext = extent_create("Hotplug slab", (u_long) pgs, (u_long) (pgs + n), NULL, 0, 0); + } + + KASSERT(seg->ext != NULL); + +} + +struct vm_page * +uvm_physseg_seg_alloc_from_slab(uvm_physseg_t upm, size_t pages) +{ + int err; + struct uvm_physseg *seg; + struct vm_page *pgs = NULL; + + seg = HANDLE_TO_PHYSSEG_NODE(upm); + + KASSERT(pages > 0); + + if (__predict_false(seg->ext == NULL)) { + /* + * This is a situation unique to boot time. + * It shouldn't happen at any point other than from + * the first uvm_page.c:uvm_page_init() call + * Since we're in a loop, we can get away with the + * below. + */ + KASSERT(uvm.page_init_done != true); + + seg->ext = HANDLE_TO_PHYSSEG_NODE(uvm_physseg_get_prev(upm))->ext; + + KASSERT(seg->ext != NULL); + } + + /* We allocate enough for this segment */ + err = extent_alloc(seg->ext, sizeof(*pgs) * pages, 1, 0, EX_BOUNDZERO, (u_long *)&pgs); + + if (err != 0) { +#ifdef DEBUG + printf("%s: extent_alloc failed with error: %d \n", + __func__, err); +#endif + } + + return pgs; +} + +/* + * uvm_page_physload: load physical memory into VM system + * + * => all args are PFs + * => all pages in start/end get vm_page structures + * => areas marked by avail_start/avail_end get added to the free page pool + * => we are limited to VM_PHYSSEG_MAX physical memory segments + */ + +uvm_physseg_t +uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, + paddr_t avail_end, int free_list) +{ + struct uvm_physseg *ps; + uvm_physseg_t upm; + + if (uvmexp.pagesize == 0) + panic("uvm_page_physload: page size not set!"); + if (free_list >= VM_NFREELIST || free_list < VM_FREELIST_DEFAULT) + panic("uvm_page_physload: bad free list %d", free_list); + if (start >= end) + panic("uvm_page_physload: start >= end"); + + if (uvm_physseg_plug(start, end - start, &upm) == false) { + panic("uvm_physseg_plug() failed at boot."); + /* NOTREACHED */ + return UVM_PHYSSEG_TYPE_INVALID; /* XXX: correct type */ + } + + ps = HANDLE_TO_PHYSSEG_NODE(upm); + + /* Legacy */ + ps->avail_start = avail_start; + ps->avail_end = avail_end; + + ps->free_list = free_list; /* XXX: */ + + + return upm; +} + +bool +uvm_physseg_unplug(paddr_t pfn, size_t pages) +{ + uvm_physseg_t upm; + paddr_t off = 0, start, end; + struct uvm_physseg *seg; + + upm = uvm_physseg_find(pfn, &off); + + if (!uvm_physseg_valid(upm)) { + printf("%s: Tried to unplug from unknown offset\n", __func__); + return false; + } + + seg = HANDLE_TO_PHYSSEG_NODE(upm); + + start = uvm_physseg_get_start(upm); + end = uvm_physseg_get_end(upm); + + if (end < (pfn + pages)) { + printf("%s: Tried to unplug oversized span \n", __func__); + return false; + } + +#ifndef DIAGNOSTIC + (void) start; +#endif + KASSERT(pfn == start + off); /* sanity */ + + if (__predict_true(uvm.page_init_done == true)) { + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + if (extent_free(seg->ext, (u_long)(seg->pgs + off), sizeof(struct vm_page) * pages, EX_MALLOCOK | EX_NOWAIT) != 0) + return false; + } + + if (off == 0 && (pfn + pages) == end) { +#if defined(UVM_HOTPLUG) /* rbtree implementation */ + int segcount = 0; + struct uvm_physseg *current_ps; + /* Complete segment */ + if (uvm_physseg_graph.nentries == 1) + panic("%s: out of memory!", __func__); + + if (__predict_true(uvm.page_init_done == true)) { + RB_TREE_FOREACH(current_ps, &(uvm_physseg_graph.rb_tree)) { + if (seg->ext == current_ps->ext) + segcount++; + } + KASSERT(segcount > 0); + + if (segcount == 1) { + extent_destroy(seg->ext); + } + + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + rb_tree_remove_node(&(uvm_physseg_graph.rb_tree), upm); + memset(seg, 0, sizeof(struct uvm_physseg)); + uvm_physseg_free(seg, sizeof(struct uvm_physseg)); + uvm_physseg_graph.nentries--; +#else /* UVM_HOTPLUG */ + int x; + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = upm ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); +#endif /* UVM_HOTPLUG */ + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + return true; + } + + if (off > 0 && + (pfn + pages) < end) { +#if defined(UVM_HOTPLUG) /* rbtree implementation */ + /* middle chunk - need a new segment */ + struct uvm_physseg *ps, *current_ps; + ps = uvm_physseg_alloc(sizeof (struct uvm_physseg)); + if (ps == NULL) { + printf("%s: Unable to allocated new fragment vm_physseg \n", + __func__); + return false; + } + + /* Remove middle chunk */ + if (__predict_true(uvm.page_init_done == true)) { + KASSERT(seg->ext != NULL); + ps->ext = seg->ext; + + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + ps->start = pfn + pages; + ps->avail_start = ps->start; /* XXX: Legacy */ + + ps->end = seg->end; + ps->avail_end = ps->end; /* XXX: Legacy */ + + seg->end = pfn; + seg->avail_end = seg->end; /* XXX: Legacy */ + + + /* + * The new pgs array points to the beginning of the + * tail fragment. + */ + if (__predict_true(uvm.page_init_done == true)) + ps->pgs = seg->pgs + off + pages; + + current_ps = rb_tree_insert_node(&(uvm_physseg_graph.rb_tree), ps); + if (current_ps != ps) { + panic("uvm_page_physload: Duplicate address range detected!"); + } + uvm_physseg_graph.nentries++; +#else /* UVM_HOTPLUG */ + panic("%s: can't unplug() from the middle of a segment without" + "UVM_HOTPLUG\n", __func__); + /* NOTREACHED */ +#endif /* UVM_HOTPLUG */ + return true; + } + + if (off == 0 && (pfn + pages) < end) { + /* Remove front chunk */ + if (__predict_true(uvm.page_init_done == true)) { + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + /* Truncate */ + seg->start = pfn + pages; + seg->avail_start = seg->start; /* XXX: Legacy */ + + /* + * Move the pgs array start to the beginning of the + * tail end. + */ + if (__predict_true(uvm.page_init_done == true)) + seg->pgs += pages; + + return true; + } + + if (off > 0 && (pfn + pages) == end) { + /* back chunk */ + + + /* Truncate! */ + seg->end = pfn; + seg->avail_end = seg->end; /* XXX: Legacy */ + + uvmexp.npages -= (int) pages; + + return true; + } + + printf("%s: Tried to unplug unknown range \n", __func__); + + return false; +} Index: sys/uvm/uvm_physseg.h =================================================================== RCS file: sys/uvm/uvm_physseg.h diff -N sys/uvm/uvm_physseg.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/uvm/uvm_physseg.h 13 Dec 2016 12:44:35 -0000 @@@@ -0,0 +1,118 @@@@ +/* $NetBSD$ */ + +/* + * Consolidated API from uvm_page.c and others. + * Consolidated and designed by Cherry G. Mathew + */ + +#ifndef _UVM_UVM_PHYSSEG_H_ +#define _UVM_UVM_PHYSSEG_H_ + +#if defined(_KERNEL_OPT) +#include "opt_uvm_hotplug.h" +#endif + +#include +#include +#include + +/* + * No APIs are explicitly #included in uvm_physseg.c + */ + +#if defined(UVM_HOTPLUG) /* rbtree impementation */ +#define PRIxPHYSSEG "p" + +/* + * These are specific values of invalid constants for uvm_physseg_t. + * uvm_physseg_valid() == false on any of the below constants. + * + * Specific invalid constants encapsulate specific explicit failure + * scenarios (see the comments next to them) + */ + +#define UVM_PHYSSEG_TYPE_INVALID NULL /* Generic invalid value */ +#define UVM_PHYSSEG_TYPE_INVALID_EMPTY NULL /* empty segment access */ +#define UVM_PHYSSEG_TYPE_INVALID_OVERFLOW NULL /* ran off the end of the last segment */ + +typedef struct uvm_physseg * uvm_physseg_t; + +#else /* UVM_HOTPLUG */ + +#define PRIxPHYSSEG "d" + +/* + * These are specific values of invalid constants for uvm_physseg_t. + * uvm_physseg_valid() == false on any of the below constants. + * + * Specific invalid constants encapsulate specific explicit failure + * scenarios (see the comments next to them) + */ + +#define UVM_PHYSSEG_TYPE_INVALID -1 /* Generic invalid value */ +#define UVM_PHYSSEG_TYPE_INVALID_EMPTY -1 /* empty segment access */ +#define UVM_PHYSSEG_TYPE_INVALID_OVERFLOW (uvm_physseg_get_last() + 1) /* ran off the end of the last segment */ + +typedef int uvm_physseg_t; +#endif /* UVM_HOTPLUG */ + +void uvm_physseg_init(void); + +bool uvm_physseg_valid(uvm_physseg_t); + +/* + * Return start/end pfn of given segment + * Returns: -1 if the segment number is invalid + */ +paddr_t uvm_physseg_get_start(uvm_physseg_t); +paddr_t uvm_physseg_get_end(uvm_physseg_t); + +paddr_t uvm_physseg_get_avail_start(uvm_physseg_t); +paddr_t uvm_physseg_get_avail_end(uvm_physseg_t); + +struct vm_page * uvm_physseg_get_pg(uvm_physseg_t, paddr_t); + +#ifdef __HAVE_PMAP_PHYSSEG +struct pmap_physseg * uvm_physseg_get_pmseg(uvm_physseg_t); +#endif + +int uvm_physseg_get_free_list(uvm_physseg_t); +u_int uvm_physseg_get_start_hint(uvm_physseg_t); +bool uvm_physseg_set_start_hint(uvm_physseg_t, u_int); + +/* + * Functions to help walk the list of segments. + * Returns: NULL if the segment number is invalid + */ +uvm_physseg_t uvm_physseg_get_next(uvm_physseg_t); +uvm_physseg_t uvm_physseg_get_prev(uvm_physseg_t); +uvm_physseg_t uvm_physseg_get_first(void); +uvm_physseg_t uvm_physseg_get_last(void); + + +/* Return the frame number of the highest registered physical page frame */ +paddr_t uvm_physseg_get_highest_frame(void); + +/* Actually, uvm_page_physload takes PF#s which need their own type */ +uvm_physseg_t uvm_page_physload(paddr_t, paddr_t, paddr_t, + paddr_t, int); + +bool uvm_page_physunload(uvm_physseg_t, int, paddr_t *); +bool uvm_page_physunload_force(uvm_physseg_t, int, paddr_t *); + +uvm_physseg_t uvm_physseg_find(paddr_t, psize_t *); + +bool uvm_physseg_plug(paddr_t, size_t, uvm_physseg_t *); +bool uvm_physseg_unplug(paddr_t, size_t); + +#if defined(PMAP_STEAL_MEMORY) +/* + * XXX: Legacy: This needs to be upgraded to a full pa management + * layer. + */ +void uvm_physseg_set_avail_start(uvm_physseg_t, paddr_t); +void uvm_physseg_set_avail_end(uvm_physseg_t, paddr_t); +#endif /* PMAP_STEAL_MEMORY */ + +#endif /* _UVM_UVM_PHYSSEG_H_ */ + Index: sys/uvm/pmap/pmap.c =================================================================== RCS file: /cvsroot/src/sys/uvm/pmap/pmap.c,v retrieving revision 1.25 diff -p -u -r1.25 pmap.c --- sys/uvm/pmap/pmap.c 1 Dec 2016 02:15:08 -0000 1.25 +++ sys/uvm/pmap/pmap.c 13 Dec 2016 12:44:35 -0000 @@@@ -112,6 +112,7 @@@@ __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.2 #include #include +#include #if defined(MULTIPROCESSOR) && defined(PMAP_VIRTUAL_CACHE_ALIASES) \ && !defined(PMAP_NO_PV_UNCACHED) @@@@ -452,37 +453,39 @@@@ pmap_steal_memory(vsize_t size, vaddr_t size_t npgs; paddr_t pa; vaddr_t va; - struct vm_physseg *maybe_seg = NULL; - u_int maybe_bank = vm_nphysseg; + + uvm_physseg_t maybe_bank = UVM_PHYSMEM_TYPE_INVALID; size = round_page(size); npgs = atop(size); aprint_debug("%s: need %zu pages\n", __func__, npgs); - for (u_int bank = 0; bank < vm_nphysseg; bank++) { - struct vm_physseg * const seg = VM_PHYSMEM_PTR(bank); + for (uvm_physseg_t bank = uvm_physseg_get_first(); + uvm_physseg_valid(bank); + bank = uvm_physseg_get_next(bank)) { + if (uvm.page_init_done == true) panic("pmap_steal_memory: called _after_ bootstrap"); - aprint_debug("%s: seg %u: %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR"\n", + aprint_debug("%s: seg %"PRIxPHYSMEM": %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR"\n", __func__, bank, - seg->avail_start, seg->start, - seg->avail_end, seg->end); + uvm_physseg_get_avail_start(bank), uvm_physseg_get_start(bank), + uvm_physseg_get_avail_end(bank), uvm_physseg_get_end(bank)); - if (seg->avail_start != seg->start - || seg->avail_start >= seg->avail_end) { - aprint_debug("%s: seg %u: bad start\n", __func__, bank); + if (uvm_physseg_get_avail_start(bank) != uvm_physseg_get_start(bank) + || uvm_physseg_get_avail_start(bank) >= uvm_physseg_get_avail_end(bank)) { + aprint_debug("%s: seg %"PRIxPHYSMEM": bad start\n", __func__, bank); continue; } - if (seg->avail_end - seg->avail_start < npgs) { - aprint_debug("%s: seg %u: too small for %zu pages\n", + if (uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank) < npgs) { + aprint_debug("%s: seg %"PRIxPHYSMEM": too small for %zu pages\n", __func__, bank, npgs); continue; } - if (!pmap_md_ok_to_steal_p(seg, npgs)) { + if (!pmap_md_ok_to_steal_p(bank, npgs)) { continue; } @@@@ -490,44 +493,24 @@@@ pmap_steal_memory(vsize_t size, vaddr_t * Always try to allocate from the segment with the least * amount of space left. */ -#define VM_PHYSMEM_SPACE(s) ((s)->avail_end - (s)->avail_start) - if (maybe_seg == NULL - || VM_PHYSMEM_SPACE(seg) < VM_PHYSMEM_SPACE(maybe_seg)) { - maybe_seg = seg; +#define VM_PHYSMEM_SPACE(b) ((uvm_physseg_get_avail_end(b)) - (uvm_physseg_get_avail_start(b))) + if (uvm_physseg_valid(maybe_bank) == false + || VM_PHYSMEM_SPACE(bank) < VM_PHYSMEM_SPACE(maybe_bank)) { maybe_bank = bank; } } - if (maybe_seg) { - struct vm_physseg * const seg = maybe_seg; - u_int bank = maybe_bank; - + if (uvm_physseg_valid(maybe_bank)) { + const uvm_physseg_t bank = maybe_bank; + /* * There are enough pages here; steal them! */ - pa = ptoa(seg->avail_start); - seg->avail_start += npgs; - seg->start += npgs; - - /* - * Have we used up this segment? - */ - if (seg->avail_start == seg->end) { - if (vm_nphysseg == 1) - panic("pmap_steal_memory: out of memory!"); + pa = ptoa(uvm_physseg_get_start(bank)); + uvm_physseg_unplug(atop(pa), npgs); - aprint_debug("%s: seg %u: %zu pages stolen (removed)\n", - __func__, bank, npgs); - /* Remove this segment from the list. */ - vm_nphysseg--; - for (u_int x = bank; x < vm_nphysseg; x++) { - /* structure copy */ - VM_PHYSMEM_PTR_SWAP(x, x + 1); - } - } else { - aprint_debug("%s: seg %u: %zu pages stolen (%#"PRIxPADDR" left)\n", - __func__, bank, npgs, VM_PHYSMEM_SPACE(seg)); - } + aprint_debug("%s: seg %"PRIxPHYSMEM": %zu pages stolen (%#"PRIxPADDR" left)\n", + __func__, bank, npgs, VM_PHYSMEM_SPACE(bank)); va = pmap_md_map_poolpage(pa, size); memset((void *)va, 0, size); @ 1.8 log @Remove leading untracked file mess in the diff @ text @d7 1 a7 1 +++ sys/uvm/Makefile 20 Nov 2016 07:20:20 -0000 d13 1 a13 1 + uvm_map.h uvm_object.h uvm_page.h uvm_physmem.h \ d20 5 a24 5 retrieving revision 1.26 diff -p -u -r1.26 files.uvm --- sys/uvm/files.uvm 12 Aug 2016 13:40:21 -0000 1.26 +++ sys/uvm/files.uvm 20 Nov 2016 07:20:20 -0000 @@@@ -14,6 +14,7 @@@@ defparam opt_pagermap.h PAGER_MAP_SIZE d32 1 a32 1 @@@@ -41,6 +42,7 @@@@ file uvm/uvm_pdaemon.c uvm d36 1 a36 1 +file uvm/uvm_physmem.c uvm d46 1 a46 1 +++ sys/uvm/uvm.h 20 Nov 2016 07:20:20 -0000 d51 1 a51 1 +#include d61 1 a61 1 +++ sys/uvm/uvm_extern.h 20 Nov 2016 07:20:22 -0000 d78 1 a78 1 +++ sys/uvm/uvm_page.c 20 Nov 2016 07:20:24 -0000 d114 20 a133 1 @@@@ -337,11 +326,9 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d139 1 a139 1 + uvm_physmem_t bank; d146 1 a146 1 @@@@ -369,7 +356,7 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d151 1 a151 1 + if (uvm_physmem_get_last() == UVM_PHYSMEM_TYPE_INVALID) d155 1 a155 1 @@@@ -381,9 +368,11 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d163 4 a166 4 + for (bank = uvm_physmem_get_first(); + uvm_physmem_valid(bank) ; + bank = uvm_physmem_get_next(bank)) { + freepages += (uvm_physmem_get_end(bank) - uvm_physmem_get_start(bank)); d170 1 a170 1 @@@@ -428,31 +417,20 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d179 9 a187 10 - + for (bank = uvm_physmem_get_first(), + uvm_physmem_seg_chomp_slab(bank, pagearray, pagecount); + uvm_physmem_valid(bank); + bank = uvm_physmem_get_next(bank)) { + + n = uvm_physmem_get_end(bank) - uvm_physmem_get_start(bank); + uvm_physmem_seg_slab_alloc(bank, n); + uvm_physmem_init_seg(bank, pagearray); + d211 1 a211 1 @@@@ -625,92 +603,42 @@@@ static bool uvm_page_physget_freelist(pa d217 1 a217 1 + uvm_physmem_t lcv; d222 1 a222 1 + for (lcv = uvm_physmem_get_last() ; uvm_physmem_valid(lcv) ; lcv = uvm_physmem_get_prev(lcv)) d225 1 a225 1 + for (lcv = uvm_physmem_get_first() ; uvm_physmem_valid(lcv) ; lcv = uvm_physmem_get_next(lcv)) d282 1 a282 1 + for (lcv = uvm_physmem_get_last() ; uvm_physmem_valid(lcv); lcv = uvm_physmem_get_prev(lcv)) d285 1 a285 1 + for (lcv = uvm_physmem_get_first() ; uvm_physmem_valid(lcv) ; lcv = uvm_physmem_get_next(lcv)) d323 1 a323 1 @@@@ -727,228 +655,6 @@@@ uvm_page_physget(paddr_t *paddrp) d552 1 a552 1 @@@@ -956,12 +662,12 @@@@ struct vm_page * d559 1 a559 1 + uvm_physmem_t upm; d564 3 a566 3 + upm = vm_physseg_find(pf, &off); + if (upm != UVM_PHYSMEM_TYPE_INVALID) + return uvm_physmem_get_pg(upm, off); d570 1 a570 1 @@@@ -985,7 +691,8 @@@@ uvm_page_recolor(int newncolors) d580 1 a580 1 @@@@ -1094,6 +801,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) d588 1 a588 1 @@@@ -1219,7 +927,8 @@@@ struct vm_page * d598 1 a598 1 @@@@ -2005,7 +1714,7 @@@@ bool d603 1 a603 1 + return (vm_physseg_find(atop(pa), NULL) != UVM_PHYSMEM_TYPE_INVALID); d607 1 a607 1 @@@@ -2015,11 +1724,11 @@@@ uvm_pageismanaged(paddr_t pa) d612 1 a612 1 + uvm_physmem_t upm; d617 3 a619 3 + upm = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); + KASSERT(upm != UVM_PHYSMEM_TYPE_INVALID); + return uvm_physmem_get_free_list(upm); d623 1 a623 1 @@@@ -2135,7 +1844,8 @@@@ uvm_page_printit(struct vm_page *pg, boo d628 1 a628 1 + uvm_physmem_t i; d633 1 a633 1 @@@@ -2143,8 +1853,14 @@@@ uvm_page_printall(void (*pr)(const char d639 5 a643 5 + for (i = uvm_physmem_get_first(); + uvm_physmem_valid(i); + i = uvm_physmem_get_next(i)) { + for (pfn = uvm_physmem_get_start(i); + pfn <= uvm_physmem_get_end(i); d656 1 a656 1 +++ sys/uvm/uvm_page.h 20 Nov 2016 07:20:25 -0000 d725 1 a725 1 +++ sys/uvm/uvm_pglist.c 20 Nov 2016 07:20:25 -0000 d731 1 a731 1 +uvm_pglistalloc_c_ps(uvm_physmem_t psi, int num, paddr_t low, paddr_t high, d750 1 a750 1 + if (high <= uvm_physmem_get_avail_start(psi) || low >= uvm_physmem_get_avail_end(psi)) d759 3 a761 3 + candidate = roundup2(max(low, uvm_physmem_get_avail_start(psi) + + uvm_physmem_get_start_hint(psi)), alignment); + limit = min(high, uvm_physmem_get_avail_end(psi)); d773 1 a773 1 + if (uvm_physmem_get_start_hint(psi) == 0 || second_pass) { d783 3 a785 3 + candidate = roundup2(max(low, uvm_physmem_get_avail_start(psi)), alignment); + limit = min(limit, uvm_physmem_get_avail_start(psi) + + uvm_physmem_get_start_hint(psi)); d794 1 a794 1 + if (vm_physseg_find(candidate, &cidx) != psi) d797 1 a797 1 + if (cidx != candidate - uvm_physmem_get_start(psi)) d800 1 a800 1 + if (vm_physseg_find(candidate + num - 1, &cidx) != psi) d803 1 a803 1 + if (cidx != candidate - uvm_physmem_get_start(psi) + num - 1) d807 1 a807 1 + candidateidx = candidate - uvm_physmem_get_start(psi); d816 1 a816 1 + if (VM_PAGE_IS_FREE(uvm_physmem_get_pg(psi, idx)) == 0) { d825 2 a826 2 + idxpa = VM_PAGE_TO_PHYS(uvm_physmem_get_pg(psi, idx)); + lastidxpa = VM_PAGE_TO_PHYS(uvm_physmem_get_pg(psi, idx)); d835 1 a835 1 + KDASSERT(VM_PAGE_IS_FREE(uvm_physmem_get_pg(psi, candidateidx + skip))); d846 1 a846 1 + uvm_pglist_add(uvm_physmem_get_pg(psi, idx), rlist); d854 4 a857 4 + uvm_physmem_set_start_hint(psi, candidate + num - + uvm_physmem_get_avail_start(psi)); + KASSERTMSG(uvm_physmem_get_start_hint(psi) <= + uvm_physmem_get_avail_end(psi) - uvm_physmem_get_avail_start(psi), d862 3 a864 3 + uvm_physmem_get_start_hint(psi), uvm_physmem_get_start_hint(psi), + uvm_physmem_get_avail_end(psi), uvm_physmem_get_avail_start(psi), + uvm_physmem_get_avail_end(psi) - uvm_physmem_get_avail_start(psi)); d877 1 a877 1 + uvm_physmem_t psi; d886 1 a886 1 + for (psi = uvm_physmem_get_last(); uvm_physmem_valid(psi); psi = uvm_physmem_get_prev(psi)) d890 1 a890 1 + for (psi = uvm_physmem_get_first(); uvm_physmem_valid(psi); psi = uvm_physmem_get_next(psi)) d896 1 a896 1 + if (uvm_physmem_get_free_list(psi) != fl) d909 1 a909 1 +uvm_pglistalloc_s_ps(uvm_physmem_t psi, int num, paddr_t low, paddr_t high, d925 4 a928 4 + KASSERT(uvm_physmem_get_start(psi) <= uvm_physmem_get_avail_start(psi)); + KASSERT(uvm_physmem_get_start(psi) <= uvm_physmem_get_avail_end(psi)); + KASSERT(uvm_physmem_get_avail_start(psi) <= uvm_physmem_get_end(psi)); + KASSERT(uvm_physmem_get_avail_end(psi) <= uvm_physmem_get_end(psi)); d936 4 a939 4 + candidate = max(low, uvm_physmem_get_avail_start(psi) + + uvm_physmem_get_start_hint(psi)); + limit = min(high, uvm_physmem_get_avail_end(psi)); + pg = uvm_physmem_get_pg(psi, candidate - uvm_physmem_get_start(psi)); d946 2 a947 2 + if (high <= uvm_physmem_get_avail_start(psi) || + low >= uvm_physmem_get_avail_end(psi)) d954 1 a954 1 + if (uvm_physmem_get_start_hint(psi) == 0 || second_pass) { d962 4 a965 4 + candidate = max(low, uvm_physmem_get_avail_start(psi)); + limit = min(limit, uvm_physmem_get_avail_start(psi) + + uvm_physmem_get_start_hint(psi)); + pg = uvm_physmem_get_pg(psi, candidate - uvm_physmem_get_start(psi)); d979 1 a979 1 + const uvm_physmem_t bank = vm_physseg_find(candidate, &cidx); d981 1 a981 1 + "vm_physseg_find(%#x) (%"PRIxPHYSMEM ") != psi %"PRIxPHYSMEM, d983 3 a985 3 + KDASSERTMSG(cidx == candidate - uvm_physmem_get_start(psi), + "vm_physseg_find(%#x): %#"PRIxPADDR" != off %"PRIxPADDR, + candidate, cidx, candidate - uvm_physmem_get_start(psi)); d995 3 a997 3 + uvm_physmem_set_start_hint(psi, candidate + 1 - uvm_physmem_get_avail_start(psi)); + KASSERTMSG(uvm_physmem_get_start_hint(psi) <= uvm_physmem_get_avail_end(psi) - + uvm_physmem_get_avail_start(psi), d1002 5 a1006 5 + uvm_physmem_get_start_hint(psi), + uvm_physmem_get_start_hint(psi), + uvm_physmem_get_avail_end(psi), + uvm_physmem_get_avail_start(psi), + uvm_physmem_get_avail_end(psi) - uvm_physmem_get_avail_start(psi)); d1018 1 a1018 1 + uvm_physmem_t psi; d1028 1 a1028 1 + for (psi = uvm_physmem_get_last(); uvm_physmem_valid(psi); psi = uvm_physmem_get_prev(psi)) d1032 1 a1032 1 + for (psi = uvm_physmem_get_first(); uvm_physmem_valid(psi); psi = uvm_physmem_get_next(psi)) d1038 1 a1038 1 + if (uvm_physmem_get_free_list(psi) != fl) d1046 1 a1046 1 Index: sys/uvm/uvm_physmem.c d1048 2 a1049 2 RCS file: sys/uvm/uvm_physmem.c diff -N sys/uvm/uvm_physmem.c d1051 2 a1052 2 +++ sys/uvm/uvm_physmem.c 20 Nov 2016 07:20:25 -0000 @@@@ -0,0 +1,1337 @@@@ d1136 1 a1136 1 +#include d1157 12 d1171 2 a1172 2 +#define HANDLE_TO_PHYSMEM_NODE(h) ((struct uvm_physseg *)(h)) +#define PHYSMEM_NODE_TO_HANDLE(u) ((uvm_physmem_t)(u)) d1207 1 a1207 1 + d1212 1 a1212 1 +uvm_physmem_alloc(size_t sz) d1227 1 a1227 1 + d1232 1 a1232 1 + d1237 1 a1237 1 +uvm_physmem_free(void *p, size_t sz) d1253 1 a1253 1 + d1260 1 a1260 1 + d1265 1 a1265 1 + d1282 1 a1282 1 +uvm_physmem_plug(paddr_t pfn, size_t pages, uvm_physmem_t *psp) d1291 4 a1294 2 + uvm_physmem_t upm; + upm = vm_physseg_find(pfn, &off); a1295 2 + ps = HANDLE_TO_PHYSMEM_NODE(upm); + d1299 1 a1299 1 + d1304 1 a1304 1 + ps = uvm_physmem_alloc(sizeof (struct uvm_physseg)); d1317 1 a1317 1 + d1326 1 a1326 1 + d1339 1 a1339 1 + pgs = uvm_physmem_seg_slab_alloc(current_ps, pages); d1362 1 a1362 1 + uvm_physmem_free(ps, sizeof(struct uvm_physseg)); d1366 1 a1366 1 + uvm_physmem_seg_chomp_slab(ps, slab, (size_t) slabpages); d1368 1 a1368 1 + pgs = uvm_physmem_seg_slab_alloc(ps, pages); d1371 1 a1371 1 + printf("unable to uvm_physmem_seg_slab_alloc() from backend\n"); d1385 1 a1385 1 + d1400 2 a1401 2 + * vm_physseg_find() to succeed. For this, the node needs to + * be inserted *before* uvm_physmem_init_seg() happens. d1404 1 a1404 1 + * uvm_physmem_init_seg() is called later on and separately d1408 1 a1408 1 + d1410 1 a1410 1 + uvm_physmem_init_seg(ps, pgs); d1419 1 a1419 1 +uvm_physmem_compare_nodes(void *ctx, const void *nnode1, const void *nnode2) d1435 1 a1435 1 +uvm_physmem_compare_key(void *ctx, const void *nnode, const void *pkey) d1450 3 a1452 3 +static const rb_tree_ops_t uvm_physmem_tree_ops = { + .rbto_compare_nodes = uvm_physmem_compare_nodes, + .rbto_compare_key = uvm_physmem_compare_key, d1458 1 a1458 1 + * uvm_physmem_init: init the physmem d1464 2 a1465 2 +uvm_physmem_init(void) { + rb_tree_init(&(uvm_physseg_graph.rb_tree), &uvm_physmem_tree_ops); d1469 2 a1470 2 +uvm_physmem_t +uvm_physmem_get_next(uvm_physmem_t upm) d1472 1 a1472 1 + return (uvm_physmem_t) rb_tree_iterate(&(uvm_physseg_graph.rb_tree), upm, d1476 2 a1477 2 +uvm_physmem_t +uvm_physmem_get_prev(uvm_physmem_t upm) d1479 1 a1479 1 + return (uvm_physmem_t) rb_tree_iterate(&(uvm_physseg_graph.rb_tree), upm, d1483 2 a1484 2 +uvm_physmem_t +uvm_physmem_get_last(void) d1486 1 a1486 1 + return (uvm_physmem_t) RB_TREE_MAX(&(uvm_physseg_graph.rb_tree)); d1489 2 a1490 2 +uvm_physmem_t +uvm_physmem_get_first(void) d1492 1 a1492 1 + return (uvm_physmem_t) RB_TREE_MIN(&(uvm_physseg_graph.rb_tree)); d1496 1 a1496 1 +uvm_physmem_get_highest_frame(void) d1499 1 a1499 1 + (uvm_physmem_t) RB_TREE_MAX(&(uvm_physseg_graph.rb_tree)); d1509 1 a1509 1 +uvm_page_physunload(uvm_physmem_t upm, int freelist, paddr_t *paddrp) d1513 1 a1513 1 + seg = HANDLE_TO_PHYSMEM_NODE(upm); d1537 1 a1537 1 + return uvm_physmem_unplug(seg->avail_start, 1); d1544 1 a1544 1 + return uvm_physmem_unplug(seg->avail_end - 1, 1); d1551 1 a1551 1 +uvm_page_physunload_force(uvm_physmem_t upm, int freelist, paddr_t *paddrp) d1555 1 a1555 1 + seg = HANDLE_TO_PHYSMEM_NODE(upm); d1564 1 a1564 1 + d1566 1 a1566 1 + return uvm_physmem_unplug(seg->avail_start, 1); d1573 2 a1574 2 +uvm_physmem_t +vm_physseg_find(paddr_t pframe, psize_t *offp) d1588 1 a1588 1 +uvm_physmem_set_avail_start(uvm_physmem_t upm, paddr_t avail_start) d1590 1 a1590 1 + struct uvm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); d1594 1 a1594 1 + avail_end = uvm_physmem_get_avail_end(upm); d1599 1 a1599 1 +void uvm_physmem_set_avail_end(uvm_physmem_t upm, paddr_t avail_end) d1601 1 a1601 1 + struct uvm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); d1605 1 a1605 1 + avail_start = uvm_physmem_get_avail_start(upm); d1628 2 a1629 2 +#define HANDLE_TO_PHYSMEM_NODE(h) (VM_PHYSMEM_PTR((int)h)) +#define PHYSMEM_NODE_TO_HANDLE(u) ((int)((vsize_t) (u - vm_physmem) / sizeof(struct uvm_physseg))) d1636 1 a1636 1 +uvm_physmem_init(void) { d1642 1 a1642 1 +uvm_physmem_get_next(uvm_physmem_t lcv) d1648 1 a1648 1 +uvm_physmem_get_prev(uvm_physmem_t lcv) d1654 1 a1654 1 +uvm_physmem_get_last(void) d1660 1 a1660 1 +uvm_physmem_get_first(void) d1666 1 a1666 1 +uvm_physmem_get_highest_frame(void) d1686 1 a1686 1 +uvm_page_physunload(uvm_physmem_t psi, int freelist, paddr_t *paddrp) d1738 1 a1738 1 +uvm_page_physunload_force(uvm_physmem_t psi, int freelist, paddr_t *paddrp) d1769 1 a1769 1 +uvm_physmem_plug(paddr_t pfn, size_t pages, uvm_physmem_t *psp) d1777 2 a1778 2 + uvm_physmem_t upm; + upm = vm_physseg_find(pfn, &off); d1780 1 a1780 1 + if (uvm_physmem_valid(upm)) /* XXX; do we allow "update" plugs ? */ d1788 1 a1788 1 + d1803 1 a1803 1 + *psp = UVM_PHYSMEM_TYPE_INVALID_OVERFLOW; d1897 1 a1897 1 +vm_physseg_find(paddr_t pframe, psize_t *offp) d1967 1 a1967 1 +#else d1989 1 a1989 1 +uvm_physmem_valid(uvm_physmem_t upm) d1993 3 a1995 3 + if (upm == UVM_PHYSMEM_TYPE_INVALID || + upm == UVM_PHYSMEM_TYPE_INVALID_EMPTY || + upm == UVM_PHYSMEM_TYPE_INVALID_OVERFLOW) d2005 1 a2005 1 + ps = HANDLE_TO_PHYSMEM_NODE(upm); d2022 1 a2022 1 +uvm_physmem_get_start(uvm_physmem_t upm) d2024 1 a2024 1 + if (uvm_physmem_valid(upm) == false) d2027 1 a2027 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->start; d2031 1 a2031 1 +uvm_physmem_get_end(uvm_physmem_t upm) d2033 1 a2033 1 + if (uvm_physmem_valid(upm) == false) d2036 1 a2036 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->end; d2040 1 a2040 1 +uvm_physmem_get_avail_start(uvm_physmem_t upm) d2042 1 a2042 1 + if (uvm_physmem_valid(upm) == false) d2045 1 a2045 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->avail_start; d2049 1 a2049 1 +uvm_physmem_get_avail_end(uvm_physmem_t upm) d2051 1 a2051 1 + if (uvm_physmem_valid(upm) == false) d2054 1 a2054 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->avail_end; d2058 1 a2058 1 +uvm_physmem_get_pg(uvm_physmem_t upm, paddr_t idx) d2060 2 a2061 2 + /* XXX: uvm_physmem_valid() */ + return &HANDLE_TO_PHYSMEM_NODE(upm)->pgs[idx]; d2066 1 a2066 1 +uvm_physmem_get_pmseg(uvm_physmem_t upm) d2068 2 a2069 2 + /* XXX: uvm_physmem_valid() */ + return &(HANDLE_TO_PHYSMEM_NODE(upm)->pmseg); d2074 1 a2074 1 +uvm_physmem_get_free_list(uvm_physmem_t upm) d2076 1 a2076 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->free_list; d2080 1 a2080 1 +uvm_physmem_get_start_hint(uvm_physmem_t upm) d2082 1 a2082 1 + return HANDLE_TO_PHYSMEM_NODE(upm)->start_hint; d2086 1 a2086 1 +uvm_physmem_set_start_hint(uvm_physmem_t upm, u_int start_hint) d2088 1 a2088 1 + if (uvm_physmem_valid(upm) == false) d2091 1 a2091 1 + HANDLE_TO_PHYSMEM_NODE(upm)->start_hint = start_hint; d2096 1 a2096 1 +uvm_physmem_init_seg(uvm_physmem_t upm, struct vm_page *pgs) d2103 1 a2103 1 + KASSERT(upm != UVM_PHYSMEM_TYPE_INVALID && pgs != NULL); d2105 1 a2105 1 + seg = HANDLE_TO_PHYSMEM_NODE(upm); d2108 1 a2108 1 + d2131 1 a2131 1 +uvm_physmem_seg_chomp_slab(uvm_physmem_t upm, struct vm_page *pgs, size_t n) d2133 2 a2134 2 + struct uvm_physseg *seg = HANDLE_TO_PHYSMEM_NODE(upm); + d2136 2 a2137 2 +#define UVM_PHYSMEM_BOOT_UNPLUG_MAX VM_PHYSSEG_MAX /* max number of pre-boot unplug()s allowed */ + static struct extent_region erboot[UVM_PHYSMEM_BOOT_UNPLUG_MAX]; d2150 1 a2150 1 +uvm_physmem_seg_slab_alloc(uvm_physmem_t upm, size_t pages) d2156 1 a2156 1 + seg = HANDLE_TO_PHYSMEM_NODE(upm); d2169 3 a2171 3 + + seg->ext = HANDLE_TO_PHYSMEM_NODE(uvm_physmem_get_prev(PHYSMEM_NODE_TO_HANDLE(seg)))->ext; + d2197 1 a2197 1 +uvm_physmem_t d2202 2 a2203 2 + uvm_physmem_t upm; + d2211 4 a2214 2 + if (uvm_physmem_plug(start, end - start, &upm) == false) { + return UVM_PHYSMEM_TYPE_INVALID; /* XXX: correct type */ d2217 2 a2218 2 + ps = HANDLE_TO_PHYSMEM_NODE(upm); + d2230 1 a2230 1 +uvm_physmem_unplug(paddr_t pfn, size_t pages) d2232 1 a2232 1 + uvm_physmem_t upm; a2234 2 + + upm = vm_physseg_find(pfn, &off); d2236 3 a2238 1 + if (!uvm_physmem_valid(upm)) { d2243 4 a2246 4 + seg = HANDLE_TO_PHYSMEM_NODE(upm); + + start = uvm_physmem_get_start(upm); + end = uvm_physmem_get_end(upm); d2264 1 a2264 1 + if (off == 0 && (pfn + pages) == end) { d2292 1 a2292 1 + uvm_physmem_free(seg, sizeof(struct uvm_physseg)); d2309 1 a2309 1 +#if defined(UVM_HOTPLUG) /* rbtree implementation */ d2312 1 a2312 1 + ps = uvm_physmem_alloc(sizeof (struct uvm_physseg)); d2348 1 a2348 1 + d2358 1 a2358 1 +#endif /* UVM_HOTPLUG */ d2383 1 a2383 1 + d2396 1 a2396 1 + d2399 1 a2399 1 + d2401 1 a2401 1 + d2404 1 a2404 1 Index: sys/uvm/uvm_physmem.h d2406 2 a2407 2 RCS file: sys/uvm/uvm_physmem.h diff -N sys/uvm/uvm_physmem.h d2409 2 a2410 2 +++ sys/uvm/uvm_physmem.h 20 Nov 2016 07:20:25 -0000 @@@@ -0,0 +1,124 @@@@ d2418 2 a2419 2 +#ifndef _UVM_UVM_PHYSMEM_H_ +#define _UVM_UVM_PHYSMEM_H_ d2430 1 a2430 1 + * No APIs are explicitly #included in uvm_physmem.c d2434 1 a2434 1 +#define PRIxPHYSMEM "p" d2437 2 a2438 2 + * These are specific values of invalid constants for uvm_physmem_t. + * uvm_physmem_valid() == false on any of the below constants. d2444 3 a2446 3 +#define UVM_PHYSMEM_TYPE_INVALID NULL /* Generic invalid value */ +#define UVM_PHYSMEM_TYPE_INVALID_EMPTY NULL /* empty segment access */ +#define UVM_PHYSMEM_TYPE_INVALID_OVERFLOW NULL /* ran off the end of the last segment */ d2448 1 a2448 1 +typedef struct uvm_physseg * uvm_physmem_t; d2452 1 a2452 1 +#define PRIxPHYSMEM "d" d2455 2 a2456 2 + * These are specific values of invalid constants for uvm_physmem_t. + * uvm_physmem_valid() == false on any of the below constants. d2462 3 a2464 3 +#define UVM_PHYSMEM_TYPE_INVALID -1 /* Generic invalid value */ +#define UVM_PHYSMEM_TYPE_INVALID_EMPTY -1 /* empty segment access */ +#define UVM_PHYSMEM_TYPE_INVALID_OVERFLOW (uvm_physmem_get_last() + 1) /* ran off the end of the last segment */ d2466 1 a2466 1 +typedef int uvm_physmem_t; d2469 1 a2469 7 +void uvm_physmem_init(void); +void uvm_physmem_init_seg(uvm_physmem_t, struct vm_page *); +void uvm_physmem_seg_chomp_slab(uvm_physmem_t, + struct vm_page *, size_t); + +/* returns a pgs array */ +struct vm_page *uvm_physmem_seg_slab_alloc(uvm_physmem_t, size_t); d2471 1 a2471 1 +bool uvm_physmem_valid(uvm_physmem_t); d2477 2 a2478 2 +paddr_t uvm_physmem_get_start(uvm_physmem_t); +paddr_t uvm_physmem_get_end(uvm_physmem_t); d2480 2 a2481 2 +paddr_t uvm_physmem_get_avail_start(uvm_physmem_t); +paddr_t uvm_physmem_get_avail_end(uvm_physmem_t); d2483 1 a2483 1 +struct vm_page * uvm_physmem_get_pg(uvm_physmem_t, paddr_t); d2486 1 a2486 1 +struct pmap_physseg * uvm_physmem_get_pmseg(uvm_physmem_t); d2489 3 a2491 3 +int uvm_physmem_get_free_list(uvm_physmem_t); +u_int uvm_physmem_get_start_hint(uvm_physmem_t); +bool uvm_physmem_set_start_hint(uvm_physmem_t, u_int); d2497 4 a2500 4 +uvm_physmem_t uvm_physmem_get_next(uvm_physmem_t); +uvm_physmem_t uvm_physmem_get_prev(uvm_physmem_t); +uvm_physmem_t uvm_physmem_get_first(void); +uvm_physmem_t uvm_physmem_get_last(void); d2504 1 a2504 1 +paddr_t uvm_physmem_get_highest_frame(void); d2507 1 a2507 1 +uvm_physmem_t uvm_page_physload(paddr_t, paddr_t, paddr_t, d2510 2 a2511 2 +bool uvm_page_physunload(uvm_physmem_t, int, paddr_t *); +bool uvm_page_physunload_force(uvm_physmem_t, int, paddr_t *); d2513 1 a2513 1 +uvm_physmem_t vm_physseg_find(paddr_t, psize_t *); d2515 2 a2516 2 +bool uvm_physmem_plug(paddr_t, size_t, uvm_physmem_t *); +bool uvm_physmem_unplug(paddr_t, size_t); d2523 2 a2524 2 +void uvm_physmem_set_avail_start(uvm_physmem_t, paddr_t); +void uvm_physmem_set_avail_end(uvm_physmem_t, paddr_t); d2527 1 a2527 1 +#endif /* _UVM_UVM_PHYSMEM_H_ */ d2532 4 a2535 4 retrieving revision 1.22 diff -p -u -r1.22 pmap.c --- sys/uvm/pmap/pmap.c 16 Sep 2016 17:27:09 -0000 1.22 +++ sys/uvm/pmap/pmap.c 20 Nov 2016 07:20:26 -0000 d2540 1 a2540 1 +#include d2551 1 a2551 1 + uvm_physmem_t maybe_bank = UVM_PHYSMEM_TYPE_INVALID; d2560 3 a2562 3 + for (uvm_physmem_t bank = uvm_physmem_get_first(); + uvm_physmem_valid(bank); + bank = uvm_physmem_get_next(bank)) { d2572 2 a2573 2 + uvm_physmem_get_avail_start(bank), uvm_physmem_get_start(bank), + uvm_physmem_get_avail_end(bank), uvm_physmem_get_end(bank)); d2578 2 a2579 2 + if (uvm_physmem_get_avail_start(bank) != uvm_physmem_get_start(bank) + || uvm_physmem_get_avail_start(bank) >= uvm_physmem_get_avail_end(bank)) { d2586 1 a2586 1 + if (uvm_physmem_get_avail_end(bank) - uvm_physmem_get_avail_start(bank) < npgs) { d2605 2 a2606 2 +#define VM_PHYSMEM_SPACE(b) ((uvm_physmem_get_avail_end(b)) - (uvm_physmem_get_avail_start(b))) + if (uvm_physmem_valid(maybe_bank) == false d2616 2 a2617 2 + if (uvm_physmem_valid(maybe_bank)) { + const uvm_physmem_t bank = maybe_bank; d2632 2 a2633 2 + pa = ptoa(uvm_physmem_get_start(bank)); + uvm_physmem_unplug(atop(pa), npgs); @ 1.7 log @Some of the changes that Chuck suggested. @ text @a0 6 ? sys/uvm/files_BACKUP_21538.uvm ? sys/uvm/files_BASE_21538.uvm ? sys/uvm/files_LOCAL_21538.uvm ? sys/uvm/files_REMOTE_21538.uvm ? sys/uvm/uvm_physmem_new.c ? sys/uvm/uvm_physmem_support.c @ 1.6 log @options UVM_HOTPLUG @ text @d1 6 d11 1 a11 1 diff -u -p -r1.9 Makefile d13 1 a13 1 +++ sys/uvm/Makefile 17 Nov 2016 15:38:54 -0000 d27 1 a27 1 diff -u -p -r1.26 files.uvm d29 1 a29 1 +++ sys/uvm/files.uvm 17 Nov 2016 15:38:54 -0000 d50 1 a50 1 diff -u -p -r1.66 uvm.h d52 1 a52 1 +++ sys/uvm/uvm.h 17 Nov 2016 15:38:54 -0000 a60 116 Index: sys/uvm/uvm_amap.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_amap.c,v retrieving revision 1.107 diff -u -p -r1.107 uvm_amap.c --- sys/uvm/uvm_amap.c 8 Apr 2012 20:47:10 -0000 1.107 +++ sys/uvm/uvm_amap.c 17 Nov 2016 15:38:56 -0000 @@@@ -37,7 +37,9 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.107 2012/04/08 20:47:10 chs Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" +#endif #include #include @@@@ -830,7 +832,7 @@@@ amap_copy(struct vm_map *map, struct vm_ } /* - * First check and see if we are the only map entry referencing + * First check and see if we are the only map entry referencing * he amap we currently have. If so, then just take it over instead * of copying it. Note that we are reading am_ref without lock held * as the value value can only be one if we have the only reference Index: sys/uvm/uvm_anon.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_anon.c,v retrieving revision 1.63 diff -u -p -r1.63 uvm_anon.c --- sys/uvm/uvm_anon.c 25 Oct 2013 20:08:11 -0000 1.63 +++ sys/uvm/uvm_anon.c 17 Nov 2016 15:38:56 -0000 @@@@ -32,7 +32,9 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.63 2013/10/25 20:08:11 martin Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" +#endif #include #include @@@@ -303,7 +305,7 @@@@ uvm_anon_lockloanpg(struct vm_anon *anon /* * someone locking the object has a chance to * lock us right now - * + * * XXX Better than yielding but inadequate. */ kpause("livelock", false, 1, anon->an_lock); Index: sys/uvm/uvm_bio.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_bio.c,v retrieving revision 1.83 diff -u -p -r1.83 uvm_bio.c --- sys/uvm/uvm_bio.c 27 May 2015 19:43:40 -0000 1.83 +++ sys/uvm/uvm_bio.c 17 Nov 2016 15:38:58 -0000 @@@@ -36,8 +36,10 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.83 2015/05/27 19:43:40 rmind Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" #include "opt_ubc.h" +#endif #include #include @@@@ -783,6 +785,7 @@@@ ubc_zerorange(struct uvm_object *uobj, o } } +#ifdef _KERNEL_OPT /* * ubc_purge: disassociate ubc_map structures from an empty uvm_object. */ @@@@ -816,3 +819,4 @@@@ ubc_purge(struct uvm_object *uobj) } mutex_exit(ubc_object.uobj.vmobjlock); } +#endif Index: sys/uvm/uvm_device.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_device.c,v retrieving revision 1.64 diff -u -p -r1.64 uvm_device.c --- sys/uvm/uvm_device.c 14 Dec 2014 23:48:58 -0000 1.64 +++ sys/uvm/uvm_device.c 17 Nov 2016 15:38:58 -0000 @@@@ -34,7 +34,9 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_device.c,v 1.64 2014/12/14 23:48:58 chs Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" +#endif #include #include @@@@ -95,6 +97,7 @@@@ udv_init(void) mutex_init(&udv_lock, MUTEX_DEFAULT, IPL_NONE); } +#ifdef _KERNEL_OPT /* * udv_attach * @@@@ -255,6 +258,7 @@@@ udv_attach(dev_t device, vm_prot_t acces } /*NOTREACHED*/ } +#endif /* * udv_reference d65 1 a65 1 diff -u -p -r1.198 uvm_extern.h d67 1 a67 1 +++ sys/uvm/uvm_extern.h 17 Nov 2016 15:38:59 -0000 a77 371 Index: sys/uvm/uvm_fault.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_fault.c,v retrieving revision 1.197 diff -u -p -r1.197 uvm_fault.c --- sys/uvm/uvm_fault.c 22 Jun 2015 06:24:17 -0000 1.197 +++ sys/uvm/uvm_fault.c 17 Nov 2016 15:39:01 -0000 @@@@ -34,7 +34,9 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.197 2015/06/22 06:24:17 matt Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" +#endif #include #include @@@@ -277,7 +279,9 @@@@ uvmfault_anonget(struct uvm_faultinfo *u struct vm_anon *anon) { struct vm_page *pg; +#ifdef _KERNEL_OPT int error; +#endif UVMHIST_FUNC("uvmfault_anonget"); UVMHIST_CALLED(maphist); KASSERT(mutex_owned(anon->an_lock)); @@@@ -290,7 +294,9 @@@@ uvmfault_anonget(struct uvm_faultinfo *u } else { curlwp->l_ru.ru_majflt++; } +#ifdef _KERNEL_OPT error = 0; +#endif /* * Loop until we get the anon data, or fail. Index: sys/uvm/uvm_init.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_init.c,v retrieving revision 1.46 diff -u -p -r1.46 uvm_init.c --- sys/uvm/uvm_init.c 3 Apr 2015 01:03:42 -0000 1.46 +++ sys/uvm/uvm_init.c 17 Nov 2016 15:39:01 -0000 @@@@ -68,6 +68,7 @@@@ kmutex_t uvm_fpageqlock; kmutex_t uvm_kentry_lock; kmutex_t uvm_swap_data_lock; +#ifdef _KERNEL_OPT /* * uvm_init: init the VM system. called from kern/init_main.c. */ @@@@ -184,3 +185,4 @@@@ uvm_init(void) uvm_ra_init(); } +#endif Index: sys/uvm/uvm_km.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_km.c,v retrieving revision 1.141 diff -u -p -r1.141 uvm_km.c --- sys/uvm/uvm_km.c 27 Jul 2016 16:45:00 -0000 1.141 +++ sys/uvm/uvm_km.c 17 Nov 2016 15:39:02 -0000 @@@@ -154,9 +154,11 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_km.c,v 1.141 2016/07/27 16:45:00 maxv Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" #include "opt_kmempages.h" +#endif #ifndef NKMEMPAGES #define NKMEMPAGES 0 @@@@ -189,7 +191,9 @@@@ __KERNEL_RCSID(0, "$NetBSD: uvm_km.c,v 1 * global data structures */ +#ifdef _KERNEL_OPT struct vm_map *kernel_map = NULL; +#endif /* * local data structues @@@@ -199,7 +203,9 @@@@ static struct vm_map kernel_map_store; static struct vm_map_entry kernel_image_mapent_store; static struct vm_map_entry kernel_kmem_mapent_store; +#ifdef _KERNEL_OPT int nkmempages = 0; +#endif vaddr_t kmembase; vsize_t kmemsize; @@@@ -367,6 +373,7 @@@@ uvm_km_init(void) kmem_init(); } +#ifdef _KERNEL_OPT /* * uvm_km_suballoc: allocate a submap in the kernel map. once a submap * is allocated all references to that area of VM must go through it. this @@@@ -429,6 +436,7 @@@@ uvm_km_suballoc(struct vm_map *map, vadd return(submap); } +#endif /* * uvm_km_pgremove: remove pages from a kernel uvm_object and KVA. @@@@ -575,6 +583,7 @@@@ uvm_km_check_empty(struct vm_map *map, v } #endif /* defined(DEBUG) */ +#ifdef _KERNEL_OPT /* * uvm_km_alloc: allocate an area of kernel memory. * @@@@ -707,7 +716,9 @@@@ uvm_km_alloc(struct vm_map *map, vsize_t UVMHIST_LOG(maphist,"<- done (kva=0x%x)", kva,0,0,0); return(kva); } +#endif +#ifdef _KERNEL_OPT /* * uvm_km_protect: change the protection of an allocated area */ @@@@ -752,6 +763,7 @@@@ uvm_km_free(struct vm_map *map, vaddr_t uvm_unmap1(map, addr, addr + size, UVM_FLAG_VAONLY); } +#endif /* Sanity; must specify both or none. */ #if (defined(PMAP_MAP_POOLPAGE) || defined(PMAP_UNMAP_POOLPAGE)) && \ @@@@ -759,6 +771,7 @@@@ uvm_km_free(struct vm_map *map, vaddr_t #error Must specify MAP and UNMAP together. #endif +#ifdef _KERNEL_OPT int uvm_km_kmem_alloc(vmem_t *vm, vmem_size_t size, vm_flag_t flags, vmem_addr_t *addr) @@@@ -853,7 +866,9 @@@@ again: return 0; } +#endif +#ifdef _KERNEL_OPT void uvm_km_kmem_free(vmem_t *vm, vmem_addr_t addr, size_t size) { @@@@ -873,6 +888,7 @@@@ uvm_km_kmem_free(vmem_t *vm, vmem_addr_t vmem_free(vm, addr, size); } +#endif bool uvm_km_va_starved_p(void) Index: sys/uvm/uvm_loan.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_loan.c,v retrieving revision 1.83 diff -u -p -r1.83 uvm_loan.c --- sys/uvm/uvm_loan.c 30 Jul 2012 23:56:48 -0000 1.83 +++ sys/uvm/uvm_loan.c 17 Nov 2016 15:39:02 -0000 @@@@ -107,8 +107,10 @@@@ static int uvm_loananon(struct uvm_fault static int uvm_loanuobj(struct uvm_faultinfo *, void ***, int, vaddr_t); static int uvm_loanzero(struct uvm_faultinfo *, void ***, int); +#ifdef _KERNEL_OPT static void uvm_unloananon(struct vm_anon **, int); static void uvm_unloanpage(struct vm_page **, int); +#endif static int uvm_loanpage(struct vm_page **, int); @@@@ -222,6 +224,7 @@@@ uvm_loanentry(struct uvm_faultinfo *ufi, * normal functions */ +#ifdef _KERNEL_OPT /* * uvm_loan: loan pages in a map out to anons or to the kernel * @@@@ -327,6 +330,7 @@@@ fail: UVMHIST_LOG(loanhist, "error %d", error,0,0,0); return (error); } +#endif /* * uvm_loananon: loan a page from an anon out @@@@ -500,6 +504,7 @@@@ uvm_loanpage(struct vm_page **pgpp, int */ #define UVM_LOAN_GET_CHUNK 16 +#ifdef _KERNEL_OPT /* * uvm_loanuobjpages: loan pages from a uobj out (O->K) * @@@@ -601,6 +606,7 @@@@ fail: return error; } +#endif /* * uvm_loanuobj: loan a page from a uobj out @@@@ -929,6 +935,7 @@@@ again: } +#ifdef _KERNEL_OPT /* * uvm_unloananon: kill loans on anons (basically a normal ref drop) * @@@@ -953,7 +960,9 @@@@ uvm_unloananon(struct vm_anon **aloans, uvm_anon_freelst(amap, to_free); #endif /* notdef */ } +#endif +#ifdef _KERNEL_OPT /* * uvm_unloanpage: kill loans on pages loaned out to the kernel * @@@@ -1021,7 +1030,9 @@@@ uvm_unloanpage(struct vm_page **ploans, } mutex_exit(&uvm_pageqlock); } +#endif +#ifdef _KERNEL_OPT /* * uvm_unloan: kill loans on pages or anons. */ @@@@ -1035,6 +1046,7 @@@@ uvm_unloan(void *v, int npages, int flag uvm_unloanpage(v, npages); } } +#endif /* * Minimal pager for uvm_loanzero_object. We need to provide a "put" @@@@ -1098,6 +1110,7 @@@@ uvm_loan_init(void) UVMHIST_INIT(loanhist, 300); } +#ifdef _KERNEL_OPT /* * uvm_loanbreak: break loan on a uobj page * @@@@ -1182,6 +1195,7 @@@@ uvm_loanbreak(struct vm_page *uobjpage) return pg; } +#endif int uvm_loanbreak_anon(struct vm_anon *anon, struct uvm_object *uobj) Index: sys/uvm/uvm_map.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_map.c,v retrieving revision 1.341 diff -u -p -r1.341 uvm_map.c --- sys/uvm/uvm_map.c 6 Aug 2016 15:13:14 -0000 1.341 +++ sys/uvm/uvm_map.c 17 Nov 2016 15:39:05 -0000 @@@@ -68,10 +68,12 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.341 2016/08/06 15:13:14 maxv Exp $"); +#ifdef _KERNEL_OPT #include "opt_ddb.h" #include "opt_uvmhist.h" #include "opt_uvm.h" #include "opt_sysv.h" +#endif #include #include @@@@ -87,8 +89,10 @@@@ __KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v #include #ifndef __USER_VA0_IS_SAFE #include +#ifdef _KERNEL_OPT #include "opt_user_va0_disable_default.h" #endif +#endif #include @@@@ -2944,6 +2948,7 @@@@ uvm_map_submap(struct vm_map *map, vaddr return error; } +#ifdef _KERNEL_OPT /* * uvm_map_protect: change map protection * @@@@ -3091,6 +3096,7 @@@@ uvm_map_protect(struct vm_map *map, vadd } #undef MASK +#endif /* * uvm_map_inherit: set inheritance code for range of addrs in map. @@@@ -3958,6 +3964,7 @@@@ uvmspace_alloc(vaddr_t vmin, vaddr_t vma return (vm); } +#ifdef _KERNEL_OPT /* * uvmspace_init: initialize a vmspace structure. * @@@@ -3986,6 +3993,7 @@@@ uvmspace_init(struct vmspace *vm, struct vm->vm_refcnt = 1; UVMHIST_LOG(maphist,"<- done",0,0,0,0); } +#endif /* * uvmspace_share: share a vmspace between two processes @@@@ -4138,6 +4146,7 @@@@ uvmspace_exec(struct lwp *l, vaddr_t sta } } +#ifdef _KERNEL_OPT /* * uvmspace_addref: add a referece to a vmspace. */ @@@@ -4154,7 +4163,9 @@@@ uvmspace_addref(struct vmspace *vm) vm->vm_refcnt++; mutex_exit(&map->misc_lock); } +#endif +#ifdef _KERNEL_OPT /* * uvmspace_free: free a vmspace data structure */ @@@@ -4202,6 +4213,7 @@@@ uvmspace_free(struct vmspace *vm) pmap_destroy(map->pmap); pool_cache_put(&uvm_vmspace_cache, vm); } +#endif static struct vm_map_entry * uvm_mapent_clone(struct vm_map *new_map, struct vm_map_entry *old_entry, @@@@ -4672,6 +4684,7 @@@@ uvm_map_reference(struct vm_map *map) mutex_exit(&map->misc_lock); } +#ifdef _KERNEL_OPT bool vm_map_starved_p(struct vm_map *map) { @@@@ -4685,6 +4698,7 @@@@ vm_map_starved_p(struct vm_map *map) } return false; } +#endif void uvm_map_lock_entry(struct vm_map_entry *entry) d82 1 a82 1 diff -u -p -r1.187 uvm_page.c d84 2 a85 15 +++ sys/uvm/uvm_page.c 17 Nov 2016 15:39:06 -0000 @@@@ -68,10 +68,12 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.187 2015/04/11 19:24:13 joerg Exp $"); +#ifdef _KERNEL_OPT #include "opt_ddb.h" #include "opt_uvm.h" #include "opt_uvmhist.h" #include "opt_readahead.h" +#endif #include #include @@@@ -81,24 +83,13 @@@@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v d111 1 a111 1 @@@@ -116,7 +107,7 @@@@ int vm_page_reserve_kernel = UVM_RESERVE d120 1 a120 36 @@@@ -152,6 +143,7 @@@@ vaddr_t uvm_zerocheckkva; static void uvm_pageinsert(struct uvm_object *, struct vm_page *); static void uvm_pageremove(struct uvm_object *, struct vm_page *); +#ifdef _KERNEL_OPT /* * per-object tree of pages */ @@@@ -170,7 +162,9 @@@@ uvm_page_compare_nodes(void *ctx, const return 1; return 0; } +#endif +#ifdef _KERNEL_OPT static signed int uvm_page_compare_key(void *ctx, const void *n, const void *key) { @@@@ -184,13 +178,16 @@@@ uvm_page_compare_key(void *ctx, const vo return 1; return 0; } +#endif +#ifdef _KERNEL_OPT const rb_tree_ops_t uvm_page_tree_ops = { .rbto_compare_nodes = uvm_page_compare_nodes, .rbto_compare_key = uvm_page_compare_key, .rbto_node_offset = offsetof(struct vm_page, rb_node), .rbto_context = NULL }; +#endif /* * inline functions @@@@ -337,11 +334,9 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d133 1 a133 1 @@@@ -369,7 +364,7 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d142 1 a142 1 @@@@ -381,9 +376,11 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d157 1 a157 1 @@@@ -428,31 +425,20 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d199 1 a199 1 @@@@ -625,92 +611,42 @@@@ static bool uvm_page_physget_freelist(pa d223 7 a229 1 - d247 1 a247 7 + /* Try to match at front or back on unused segment */ + if (uvm_page_physunload(lcv, freelist, paddrp) == false) { + if (paddrp == NULL) /* freelist fail, try next */ + continue; + } else + return true; d311 1 a311 2 @@@@ -726,228 +662,7 @@@@ uvm_page_physget(paddr_t *paddrp) } d314 1 a314 1 -/* d536 1 a536 2 +#ifdef _KERNEL_OPT /* d539 2 a540 1 @@@@ -956,21 +671,24 @@@@ struct vm_page * a556 10 +#endif +#ifdef _KERNEL_OPT paddr_t uvm_vm_page_to_phys(const struct vm_page *pg) { return pg->phys_addr; } +#endif d558 1 a558 3 /* * uvm_page_recolor: Recolor the pages if the new bucket count is @@@@ -985,7 +703,8 @@@@ uvm_page_recolor(int newncolors) d568 1 a568 1 @@@@ -1094,6 +813,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) d576 1 a576 19 @@@@ -1110,6 +830,7 @@@@ attachrnd: } +#ifdef _KERNEL_OPT /* * uvm_pagealloc_pgfl: helper routine for uvm_pagealloc_strat */ @@@@ -1196,7 +917,9 @@@@ uvm_pagealloc_pgfl(struct uvm_cpu *ucpu, return (pg); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagealloc_strat: allocate vm_page from a particular free list. * @@@@ -1219,7 +942,8 @@@@ struct vm_page * d586 1 a586 121 @@@@ -1389,6 +1113,7 @@@@ uvm_pagealloc_strat(struct uvm_object *o mutex_spin_exit(&uvm_fpageqlock); return (NULL); } +#endif /* * uvm_pagereplace: replace a page with another @@@@ -1481,6 +1206,7 @@@@ uvm_pagezerocheck(struct vm_page *pg) } #endif /* DEBUG */ +#ifdef _KERNEL_OPT /* * uvm_pagefree: free page * @@@@ -1632,7 +1358,9 @@@@ uvm_pagefree(struct vm_page *pg) mutex_spin_exit(&uvm_fpageqlock); } +#endif +#ifdef _KERNEL_OPT /* * uvm_page_unbusy: unbusy an array of pages. * @@@@ -1676,6 +1404,7 @@@@ uvm_page_unbusy(struct vm_page **pgs, in } } } +#endif #if defined(UVM_PAGE_TRKOWN) /* @@@@ -1831,6 +1560,7 @@@@ uvm_pageidlezero(void) mutex_spin_exit(&uvm_fpageqlock); } +#ifdef _KERNEL_OPT /* * uvm_pagelookup: look up a page * @@@@ -1852,7 +1582,9 @@@@ uvm_pagelookup(struct uvm_object *obj, v (pg->flags & PG_BUSY) != 0); return pg; } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagewire: wire the page, thus removing it from the daemon's grasp * @@@@ -1875,7 +1607,9 @@@@ uvm_pagewire(struct vm_page *pg) } pg->wire_count++; } +#endif +#ifdef _KERNEL_OPT /* * uvm_pageunwire: unwire the page. * @@@@ -1893,7 +1627,9 @@@@ uvm_pageunwire(struct vm_page *pg) uvmexp.wired--; } } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagedeactivate: deactivate page * @@@@ -1912,7 +1648,9 @@@@ uvm_pagedeactivate(struct vm_page *pg) KASSERT(pg->wire_count != 0 || uvmpdpol_pageisqueued_p(pg)); uvmpdpol_pagedeactivate(pg); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pageactivate: activate page * @@@@ -1936,7 +1674,9 @@@@ uvm_pageactivate(struct vm_page *pg) } uvmpdpol_pageactivate(pg); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagedequeue: remove a page from any paging queue */ @@@@ -1951,7 +1691,9 @@@@ uvm_pagedequeue(struct vm_page *pg) uvmpdpol_pagedequeue(pg); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pageenqueue: add a page to a paging queue without activating. * used where a page is not really demanded (yet). eg. read-ahead @@@@ -1967,7 +1709,9 @@@@ uvm_pageenqueue(struct vm_page *pg) } uvmpdpol_pageenqueue(pg); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagezero: zero fill a page * @@@@ -1981,6 +1725,7 @@@@ uvm_pagezero(struct vm_page *pg) pg->flags &= ~PG_CLEAN; pmap_zero_page(VM_PAGE_TO_PHYS(pg)); } +#endif /* * uvm_pagecopy: copy a page @@@@ -2005,7 +1750,7 @@@@ bool d595 1 a595 1 @@@@ -2015,13 +1760,14 @@@@ uvm_pageismanaged(paddr_t pa) a609 1 +#ifdef _KERNEL_OPT d611 1 a611 11 * uvm_page_locked_p: return true if object associated with page is * locked. this is a weak check for runtime assertions only. @@@@ -2039,6 +1785,7 @@@@ uvm_page_locked_p(struct vm_page *pg) } return true; } +#endif #if defined(DDB) || defined(DEBUGPRINT) @@@@ -2135,7 +1882,8 @@@@ uvm_page_printit(struct vm_page *pg, boo d621 1 a621 1 @@@@ -2143,8 +1891,14 @@@@ uvm_page_printall(void (*pr)(const char d642 1 a642 1 diff -u -p -r1.80 uvm_page.h d644 1 a644 1 +++ sys/uvm/uvm_page.h 17 Nov 2016 15:39:06 -0000 a706 270 Index: sys/uvm/uvm_pager.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_pager.c,v retrieving revision 1.110 diff -u -p -r1.110 uvm_pager.c --- sys/uvm/uvm_pager.c 1 Mar 2014 18:32:01 -0000 1.110 +++ sys/uvm/uvm_pager.c 17 Nov 2016 15:39:06 -0000 @@@@ -34,9 +34,11 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_pager.c,v 1.110 2014/03/01 18:32:01 christos Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" #include "opt_readahead.h" #include "opt_pagermap.h" +#endif #include #include @@@@ -159,6 +161,7 @@@@ uvm_pager_init(void) } } +#ifdef _KERNEL_OPT /* * uvm_pagermapin: map pages into KVA (pager_map) for I/O that needs mappings * @@@@ -238,7 +241,9 @@@@ enter: UVMHIST_LOG(maphist, "<- done (KVA=0x%x)", kva,0,0,0); return(kva); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pagermapout: remove pager_map mapping * @@@@ -284,6 +289,7 @@@@ uvm_pagermapout(vaddr_t kva, int npages) uvm_unmap_detach(entries, 0); UVMHIST_LOG(maphist,"<- done",0,0,0,0); } +#endif /* * interrupt-context iodone handler for single-buf i/os @@@@ -306,12 +312,16 @@@@ uvm_aio_aiodone_pages(struct vm_page **p struct vm_page *pg; kmutex_t *slock; int pageout_done; /* number of PG_PAGEOUT pages processed */ +#ifdef _KERNEL_OPT int swslot; +#endif int i; bool swap; UVMHIST_FUNC("uvm_aio_aiodone_pages"); UVMHIST_CALLED(ubchist); +#ifdef _KERNEL_OPT swslot = 0; +#endif pageout_done = 0; slock = NULL; uobj = NULL; @@@@ -378,7 +388,9 @@@@ uvm_aio_aiodone_pages(struct vm_page **p */ if (error) { +#ifdef _KERNEL_OPT int slot; +#endif if (!write) { pg->flags |= PG_RELEASED; continue; @@@@ -389,9 +401,15 @@@@ uvm_aio_aiodone_pages(struct vm_page **p } pg->flags &= ~PG_CLEAN; uvm_pageactivate(pg); +#ifdef _KERNEL_OPT slot = 0; - } else +#endif + } +#ifdef _KERNEL_OPT + else slot = SWSLOT_BAD; +#endif + #if defined(VMSWAP) if (swap) { @@@@ -518,6 +536,7 @@@@ uvm_aio_aiodone(struct buf *bp) putiobuf(bp); } +#ifdef _KERNEL_OPT /* * uvm_pageratop: convert KVAs in the pager map back to their page * structures. @@@@ -536,3 +555,4 @@@@ uvm_pageratop(vaddr_t kva) KASSERT(pg != NULL); return (pg); } +#endif Index: sys/uvm/uvm_pdaemon.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_pdaemon.c,v retrieving revision 1.108 diff -u -p -r1.108 uvm_pdaemon.c --- sys/uvm/uvm_pdaemon.c 25 Oct 2013 20:28:33 -0000 1.108 +++ sys/uvm/uvm_pdaemon.c 17 Nov 2016 15:39:07 -0000 @@@@ -68,8 +68,10 @@@@ #include __KERNEL_RCSID(0, "$NetBSD: uvm_pdaemon.c,v 1.108 2013/10/25 20:28:33 martin Exp $"); +#ifdef _KERNEL_OPT #include "opt_uvmhist.h" #include "opt_readahead.h" +#endif #include #include @@@@ -98,6 +100,7 @@@@ UVMHIST_DEFINE(pdhist); #define UVMPD_NUMTRYLOCKOWNER 16 +#ifdef _KERNEL_OPT /* * local prototypes */ @@@@ -105,14 +108,18 @@@@ UVMHIST_DEFINE(pdhist); static void uvmpd_scan(void); static void uvmpd_scan_queue(void); static void uvmpd_tune(void); +#endif +#ifdef _KERNEL_OPT static unsigned int uvm_pagedaemon_waiters; +#endif /* * XXX hack to avoid hangs when large processes fork. */ u_int uvm_extrapages; +#ifdef _KERNEL_OPT /* * uvm_wait: wait (sleep) for the page daemon to free some pages * @@@@ -161,7 +168,9 @@@@ uvm_wait(const char *wmsg) wakeup(&uvm.pagedaemon); /* wake the daemon! */ UVM_UNLOCK_AND_WAIT(&uvmexp.free, &uvm_fpageqlock, false, wmsg, timo); } +#endif +#ifdef _KERNEL_OPT /* * uvm_kick_pdaemon: perform checks to determine if we need to * give the pagedaemon a nudge, and do so if necessary. @@@@ -182,7 +191,9 @@@@ uvm_kick_pdaemon(void) wakeup(&uvm.pagedaemon); } } +#endif +#ifdef _KERNEL_OPT /* * uvmpd_tune: tune paging parameters * @@@@ -221,7 +232,9 @@@@ uvmpd_tune(void) UVMHIST_LOG(pdhist, "<- done, freemin=%d, freetarg=%d, wiredmax=%d", uvmexp.freemin, uvmexp.freetarg, uvmexp.wiredmax, 0); } +#endif +#ifdef _KERNEL_OPT /* * uvm_pageout: the main loop for the pagedaemon */ @@@@ -345,6 +358,7 @@@@ uvm_pageout(void *arg) /*NOTREACHED*/ } +#endif /* * uvm_aiodone_worker: a workqueue callback for the aiodone daemon. @@@@ -364,6 +378,7 @@@@ uvm_aiodone_worker(struct work *wk, void (*bp->b_iodone)(bp); } +#ifdef _KERNEL_OPT void uvm_pageout_start(int npages) { @@@@ -372,7 +387,9 @@@@ uvm_pageout_start(int npages) uvmexp.paging += npages; mutex_spin_exit(&uvm_fpageqlock); } +#endif +#ifdef _KERNEL_OPT void uvm_pageout_done(int npages) { @@@@ -393,6 +410,7 @@@@ uvm_pageout_done(int npages) } mutex_spin_exit(&uvm_fpageqlock); } +#endif /* * uvmpd_trylockowner: trylock the page's owner. @@@@ -640,6 +658,7 @@@@ uvmpd_trydropswap(struct vm_page *pg) #endif /* defined(VMSWAP) */ +#ifdef _KERNEL_OPT /* * uvmpd_scan_queue: scan an replace candidate list for pages * to clean or free. @@@@ -915,7 +934,9 @@@@ uvmpd_scan_queue(void) mutex_enter(&uvm_pageqlock); #endif /* defined(VMSWAP) */ } +#endif +#ifdef _KERNEL_OPT /* * uvmpd_scan: scan the page queues and attempt to meet our targets. * @@@@ -967,6 +988,7 @@@@ uvmpd_scan(void) module_thread_kick(); } } +#endif /* * uvm_reclaimable: decide whether to wait for pagedaemon. @@@@ -1015,6 +1037,7 @@@@ uvm_reclaimable(void) return false; } +#ifdef _KERNEL_OPT void uvm_estimatepageable(int *active, int *inactive) { @@@@ -1022,3 +1045,4 @@@@ uvm_estimatepageable(int *active, int *i uvmpdpol_estimatepageable(active, inactive); } +#endif Index: sys/uvm/uvm_pdpolicy_clock.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_pdpolicy_clock.c,v retrieving revision 1.17 diff -u -p -r1.17 uvm_pdpolicy_clock.c --- sys/uvm/uvm_pdpolicy_clock.c 30 Jan 2012 17:21:52 -0000 1.17 +++ sys/uvm/uvm_pdpolicy_clock.c 17 Nov 2016 15:39:07 -0000 @@@@ -348,10 +348,12 @@@@ uvmpdpol_pageenqueue(struct vm_page *pg) uvmpdpol_pageactivate(pg); } +#ifdef _KERNEL_OPT void uvmpdpol_anfree(struct vm_anon *an) { } +#endif bool uvmpdpol_pageisqueued_p(struct vm_page *pg) d711 1 a711 1 diff -u -p -r1.67 uvm_pglist.c d713 1 a713 1 +++ sys/uvm/uvm_pglist.c 17 Nov 2016 15:39:07 -0000 d1039 2 a1040 2 +++ sys/uvm/uvm_physmem.c 17 Nov 2016 15:39:08 -0000 @@@@ -0,0 +1,1331 @@@@ d1129 1 a1129 1 +struct vm_physseg { d1147 1 a1147 1 +#define HANDLE_TO_PHYSMEM_NODE(h) ((struct vm_physseg *)(h)) d1151 1 a1151 1 +struct vm_physmem { d1156 1 a1156 1 +static struct vm_physmem vm_physmem; d1185 1 a1185 1 +static struct vm_physseg uvm_physseg[VM_PHYSSEG_MAX]; d1197 1 a1197 1 + if (sz % sizeof(struct vm_physseg)) d1199 1 a1199 1 + "of struct vm_physseg at boot\n", __func__); d1201 1 a1201 1 + size_t n = sz / sizeof(struct vm_physseg); d1231 2 a1232 2 + if (sz % sizeof(struct vm_physseg)) + panic("%s: tried to free size other than struct vm_physseg" d1242 4 a1245 4 + if ((struct vm_physseg *)p >= uvm_physseg && + (struct vm_physseg *)p < (uvm_physseg + VM_PHYSSEG_MAX)) { + if (sz % sizeof(struct vm_physseg)) + panic("%s: tried to free() other than struct vm_physseg" d1248 1 a1248 1 + if ((sz / sizeof(struct vm_physseg)) >= VM_PHYSSEG_MAX) d1262 1 a1262 1 + struct vm_physseg *ps, *current_ps = NULL; d1280 1 a1280 1 + ps = uvm_physmem_alloc(sizeof (struct vm_physseg)); d1310 1 a1310 1 + RB_TREE_FOREACH(current_ps, &(vm_physmem.rb_tree)) { d1338 1 a1338 1 + uvm_physmem_free(ps, sizeof(struct vm_physseg)); d1363 1 a1363 1 + * now insert us in the proper place in vm_physmem.rb_tree d1366 1 a1366 1 + current_ps = rb_tree_insert_node(&(vm_physmem.rb_tree), ps); d1370 1 a1370 1 + vm_physmem.nentries++; d1397 2 a1398 2 + const struct vm_physseg *enode1 = nnode1; + const struct vm_physseg *enode2 = nnode2; d1413 1 a1413 1 + const struct vm_physseg *enode = nnode; d1416 1 a1416 1 + if((enode->start <= pa) && (pa < enode->end)) d1429 1 a1429 1 + .rbto_node_offset = offsetof(struct vm_physseg, rb_node), d1441 2 a1442 2 + rb_tree_init(&(vm_physmem.rb_tree), &uvm_physmem_tree_ops); + vm_physmem.nentries = 0; d1448 1 a1448 1 + return (uvm_physmem_t) rb_tree_iterate(&(vm_physmem.rb_tree), upm, d1455 1 a1455 1 + return (uvm_physmem_t) rb_tree_iterate(&(vm_physmem.rb_tree), upm, d1462 1 a1462 1 + return (uvm_physmem_t) RB_TREE_MAX(&(vm_physmem.rb_tree)); d1468 1 a1468 1 + return (uvm_physmem_t) RB_TREE_MIN(&(vm_physmem.rb_tree)); d1474 2 a1475 2 + struct vm_physseg *ps = + (uvm_physmem_t) RB_TREE_MAX(&(vm_physmem.rb_tree)); d1487 1 a1487 1 + struct vm_physseg *seg; d1529 1 a1529 1 + struct vm_physseg *seg; d1552 1 a1552 1 + struct vm_physseg * ps = NULL; d1554 1 a1554 1 + ps = rb_tree_find_node(&(vm_physmem.rb_tree), &pframe); d1566 1 a1566 1 + struct vm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); d1568 4 d1577 6 a1582 1 + struct vm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); d1605 1 a1605 1 +#define PHYSMEM_NODE_TO_HANDLE(u) ((int)((vsize_t) (u - vm_physmem) / sizeof(struct vm_physseg))) d1607 1 a1607 1 +static struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ d1646 1 a1646 1 + struct vm_physseg *ps; d1665 1 a1665 1 + struct vm_physseg *seg; d1717 1 a1717 1 + struct vm_physseg *seg; d1749 1 a1749 1 + struct vm_physseg *ps; d1756 1 a1756 3 + ps = HANDLE_TO_PHYSMEM_NODE(upm); + + if (ps != NULL) /* XXX; do we allow "update" plugs ? */ a1767 1 + d1862 1 a1862 1 +static inline int vm_physseg_find_contig(struct vm_physseg *, int, paddr_t, psize_t *); d1864 1 a1864 1 +static inline int vm_physseg_find_bsearch(struct vm_physseg *, int, paddr_t, psize_t *); d1866 1 a1866 1 +static inline int vm_physseg_find_linear(struct vm_physseg *, int, paddr_t, psize_t *); d1887 1 a1887 1 +vm_physseg_find_contig(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) d1902 1 a1902 1 +vm_physseg_find_bsearch(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) d1946 1 a1946 1 +vm_physseg_find_linear(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) d1967 1 a1967 1 + struct vm_physseg *ps; d2077 1 a2077 1 + struct vm_physseg *seg; d2109 1 a2109 1 + struct vm_physseg *seg = HANDLE_TO_PHYSMEM_NODE(upm); d2129 1 a2129 1 + struct vm_physseg *seg; d2177 1 a2177 1 + struct vm_physseg *ps; d2208 1 a2208 1 + struct vm_physseg *seg; d2241 1 a2241 1 + struct vm_physseg *current_ps; d2243 1 a2243 1 + if (vm_physmem.nentries == 1) d2247 1 a2247 1 + RB_TREE_FOREACH(current_ps, &(vm_physmem.rb_tree)) { d2264 4 a2267 4 + rb_tree_remove_node(&(vm_physmem.rb_tree), upm); + memset(seg, 0, sizeof(struct vm_physseg)); + uvm_physmem_free(seg, sizeof(struct vm_physseg)); + vm_physmem.nentries--; d2285 2 a2286 2 + struct vm_physseg *ps, *current_ps; + ps = uvm_physmem_alloc(sizeof (struct vm_physseg)); d2323 1 a2323 1 + current_ps = rb_tree_insert_node(&(vm_physmem.rb_tree), ps); d2327 1 a2327 1 + vm_physmem.nentries++; d2383 1 a2383 1 +++ sys/uvm/uvm_physmem.h 17 Nov 2016 15:39:08 -0000 d2422 1 a2422 1 +typedef struct vm_physseg * uvm_physmem_t; d2513 1 a2513 1 diff -u -p -r1.22 pmap.c d2515 2 a2516 14 +++ sys/uvm/pmap/pmap.c 17 Nov 2016 15:39:09 -0000 @@@@ -95,9 +95,11 @@@@ __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.2 * and to when physical maps must be made correct. */ +#ifdef _KERNEL_OPT #include "opt_modular.h" #include "opt_multiprocessor.h" #include "opt_sysv.h" +#endif #define __PMAP_PRIVATE @@@@ -112,6 +114,7 @@@@ __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.2 d2524 1 a2524 1 @@@@ -452,37 +455,39 @@@@ pmap_steal_memory(vsize_t size, vaddr_t d2577 1 a2577 1 @@@@ -490,44 +495,24 @@@@ pmap_steal_memory(vsize_t size, vaddr_t d2605 1 a2605 3 + pa = ptoa(uvm_physmem_get_start(bank)); + uvm_physmem_unplug(atop(pa), npgs); d2612 3 a2614 1 - @ 1.5 log @hotplug with balloon(4) implementation. Includes skrll@@ patches. @ text @d7 1 a7 1 +++ sys/uvm/Makefile 13 Nov 2016 10:38:26 -0000 d23 10 a32 2 +++ sys/uvm/files.uvm 13 Nov 2016 10:38:26 -0000 @@@@ -41,6 +41,7 @@@@ file uvm/uvm_pdaemon.c uvm d46 1 a46 1 +++ sys/uvm/uvm.h 13 Nov 2016 10:38:32 -0000 d61 1 a61 1 +++ sys/uvm/uvm_amap.c 13 Nov 2016 10:39:03 -0000 d87 1 a87 1 +++ sys/uvm/uvm_anon.c 13 Nov 2016 10:39:05 -0000 d113 1 a113 1 +++ sys/uvm/uvm_bio.c 13 Nov 2016 10:39:09 -0000 d144 1 a144 1 +++ sys/uvm/uvm_device.c 13 Nov 2016 10:39:10 -0000 d177 1 a177 1 +++ sys/uvm/uvm_extern.h 13 Nov 2016 10:39:13 -0000 d194 1 a194 1 +++ sys/uvm/uvm_fault.c 13 Nov 2016 10:39:25 -0000 d231 1 a231 1 +++ sys/uvm/uvm_init.c 13 Nov 2016 10:39:25 -0000 d251 1 a251 1 +++ sys/uvm/uvm_km.c 13 Nov 2016 10:39:29 -0000 d358 1 a358 1 +++ sys/uvm/uvm_loan.c 13 Nov 2016 10:39:37 -0000 d460 1 a460 1 +++ sys/uvm/uvm_map.c 13 Nov 2016 10:39:52 -0000 d565 1 a565 1 +++ sys/uvm/uvm_page.c 13 Nov 2016 10:40:03 -0000 d1335 1 a1335 1 +++ sys/uvm/uvm_page.h 13 Nov 2016 10:40:13 -0000 d1404 1 a1404 1 +++ sys/uvm/uvm_pager.c 13 Nov 2016 10:40:13 -0000 d1506 1 a1506 1 +++ sys/uvm/uvm_pdaemon.c 13 Nov 2016 10:40:20 -0000 d1654 1 a1654 1 +++ sys/uvm/uvm_pdpolicy_clock.c 13 Nov 2016 10:40:20 -0000 d1674 1 a1674 1 +++ sys/uvm/uvm_pglist.c 13 Nov 2016 10:40:29 -0000 d2000 2 a2001 2 +++ sys/uvm/uvm_physmem.c 13 Nov 2016 10:40:29 -0000 @@@@ -0,0 +1,924 @@@@ a2086 3 +#define HANDLE_TO_PHYSMEM_NODE(h) ((struct vm_physseg *)(h)) +#define PHYSMEM_NODE_TO_HANDLE(u) ((uvm_physmem_t)(u)) + d2106 6 a2354 155 +bool +uvm_physmem_unplug(paddr_t pfn, size_t pages) +{ + int segcount = 0; + uvm_physmem_t upm; + paddr_t off = 0, start, end; + struct vm_physseg *seg, *current_ps; + + upm = vm_physseg_find(pfn, &off); + + if (!uvm_physmem_valid(upm)) { + printf("%s: Tried to unplug from unknown offset\n", __func__); + return false; + } + + seg = HANDLE_TO_PHYSMEM_NODE(upm); + + start = uvm_physmem_get_start(upm); + end = uvm_physmem_get_end(upm); + + if (end < (pfn + pages)) { + printf("%s: Tried to unplug oversized span \n", __func__); + return false; + } + + KASSERT(pfn == start + off); /* sanity */ + + if (__predict_true(uvm.page_init_done == true)) { + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + if (extent_free(seg->ext, (u_long)seg->pgs + off, pages, EX_NOWAIT) != 0) + return false; + } + + if (off == 0 && (pfn + pages) == end) { + /* Complete segment */ + if (vm_physmem.nentries == 1) + panic("%s: out of memory!", __func__); + + if (__predict_true(uvm.page_init_done == true)) { + RB_TREE_FOREACH(current_ps, &(vm_physmem.rb_tree)) { + if (seg->ext == current_ps->ext) + segcount++; + } + KASSERT(segcount > 0); + + if (segcount == 1) { + extent_destroy(seg->ext); + } + + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + rb_tree_remove_node(&(vm_physmem.rb_tree), upm); + uvm_physmem_free(seg, sizeof(struct vm_physseg)); + vm_physmem.nentries--; + + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + return true; + } + + if (off > 0 && + (pfn + pages) < end) { + /* middle chunk - need a new segment */ + struct vm_physseg *ps; + ps = uvm_physmem_alloc(sizeof (struct vm_physseg)); + if (ps == NULL) { + printf("%s: Unable to allocated new fragment vm_physseg \n", + __func__); + return false; + } + + /* Remove middle chunk */ + if (__predict_true(uvm.page_init_done == true)) { + KASSERT(seg->ext != NULL); + ps->ext = seg->ext; + + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + ps->start = pfn + pages; + ps->avail_start = ps->start; /* XXX: Legacy */ + + ps->end = seg->end; + ps->avail_end = ps->end; /* XXX: Legacy */ + + seg->end = pfn; + seg->avail_end = seg->end; /* XXX: Legacy */ + + + /* + * The new pgs array points to the beginning of the + * tail fragment. + */ + ps->pgs = seg->pgs + off + pages; + + current_ps = rb_tree_insert_node(&(vm_physmem.rb_tree), ps); + if (current_ps != ps) { + panic("uvm_page_physload: Duplicate address range detected!"); + } + vm_physmem.nentries++; + + return true; + } + + if (off == 0 && (pfn + pages) < end) { + /* Remove front chunk */ + if (__predict_true(uvm.page_init_done == true)) { + /* XXX: KASSERT() that seg->pgs[] are not on any uvm lists */ + /* + * We assume that the unplug will succeed from + * this point onwards + */ + uvmexp.npages -= (int) pages; + } + + /* Truncate */ + seg->start = pfn + pages; + seg->avail_start = seg->start; /* XXX: Legacy */ + + /* + * Move the pgs array start to the beginning of the + * tail end. + */ + seg->pgs += pages; + + return true; + } + + if (off > 0 && (pfn + pages) == end) { + /* back chunk */ + + + /* Truncate! */ + seg->end = pfn; + seg->avail_end = seg->end; /* XXX: Legacy */ + + uvmexp.npages -= (int) pages; + + return true; + } + + printf("%s: Tried to unplug unknown range \n", __func__); + + return false; +} + d2406 16 a2421 2 +void +uvm_physmem_seg_chomp_slab(struct vm_physseg *seg, struct vm_page *pgs, size_t n) d2423 2 a2424 3 + /* One per segment at boot */ +#define UVM_PHYSMEM_BOOT_UNPLUG_MAX 32 /* max number of pre-boot unplug()s allowed */ + static struct extent_region erboot[UVM_PHYSMEM_BOOT_UNPLUG_MAX]; d2426 5 a2430 5 + if (__predict_false(uvm.page_init_done == false)) { + seg->ext = extent_create("Boot time slab", (u_long) pgs, (u_long) (pgs + n), erboot, sizeof(erboot), EX_MALLOCOK); + } else { + seg->ext = extent_create("Hotplug slab", (u_long) pgs, (u_long) (pgs + n), NULL, 0, EX_MALLOCOK); + } d2432 5 a2436 1 + KASSERT(seg->ext != NULL); d2438 1 d2441 6 a2446 2 +struct vm_page * +uvm_physmem_seg_slab_alloc(uvm_physmem_t upm, size_t pages) a2447 1 + int err; a2448 1 + struct vm_page *pgs = NULL; d2452 17 a2468 1 + KASSERT(pages > 0); d2470 5 a2474 13 + if (__predict_false(seg->ext == NULL)) { + /* + * This is a situation unique to boot time. + * It shouldn't happen at any point other than from + * the first uvm_page.c:uvm_page_init() call + * Since we're in a loop, we can get away with the + * below. + */ + KASSERT(uvm.page_init_done != true); + + seg->ext = HANDLE_TO_PHYSMEM_NODE(uvm_physmem_get_prev(PHYSMEM_NODE_TO_HANDLE(seg)))->ext; + + KASSERT(seg->ext != NULL); d2477 5 a2481 8 + /* We allocate enough for this segment */ + err = extent_alloc(seg->ext, sizeof(*pgs) * pages, 1, 0, EX_BOUNDZERO, (u_long *)&pgs); + + if (err != 0) { +#ifdef DEBUG + printf("%s: extent_alloc failed with error: %d \n", + __func__, err); +#endif d2484 1 a2484 1 + return pgs; d2487 76 d2564 103 a2666 1 +uvm_physmem_init_seg(uvm_physmem_t upm, struct vm_page *pgs) d2668 1 a2668 3 + psize_t i; + psize_t n; + paddr_t paddr; d2671 81 a2751 1 + KASSERT(upm != NULL && pgs != NULL); d2753 70 a2822 1 + seg = HANDLE_TO_PHYSMEM_NODE(upm); d2824 6 a2829 2 + n = seg->end - seg->start; + seg->pgs = pgs; d2831 6 a2836 6 + /* init and free vm_pages (we've already zeroed them) */ + paddr = ctob(seg->start); + for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) { + seg->pgs[i].phys_addr = paddr; +#ifdef __HAVE_VM_PAGE_MD + VM_MDPAGE_INIT(&seg->pgs[i]); d2838 74 a2911 7 + if (atop(paddr) >= seg->avail_start && + atop(paddr) < seg->avail_end) { + uvmexp.npages++; + mutex_enter(&uvm_pageqlock); + /* add page to free pool */ + uvm_pagefree(&seg->pgs[i]); + mutex_exit(&uvm_pageqlock); d2914 32 d3026 2 a3027 2 +uvm_physmem_t +uvm_physmem_get_next(uvm_physmem_t upm) d3029 4 a3032 3 + return (uvm_physmem_t) rb_tree_iterate(&(vm_physmem.rb_tree), upm, + RB_DIR_RIGHT); +} d3034 1 a3034 6 +uvm_physmem_t +uvm_physmem_get_prev(uvm_physmem_t upm) +{ + return (uvm_physmem_t) rb_tree_iterate(&(vm_physmem.rb_tree), upm, + RB_DIR_LEFT); +} d3036 6 a3041 5 +uvm_physmem_t +uvm_physmem_get_last(void) +{ + return (uvm_physmem_t) RB_TREE_MAX(&(vm_physmem.rb_tree)); +} d3043 16 a3058 4 +uvm_physmem_t +uvm_physmem_get_first(void) +{ + return (uvm_physmem_t) RB_TREE_MIN(&(vm_physmem.rb_tree)); d3061 2 a3062 2 +bool +uvm_physmem_valid(uvm_physmem_t upm) d3064 5 a3068 49 + struct vm_physseg *ps; + + if (upm == NULL) + return false; + + /* + * This is the delicate init dance - + * needs to go with the dance. + */ + if (uvm.page_init_done != true) + return true; + + ps = HANDLE_TO_PHYSMEM_NODE(upm); + + /* Extra checks needed only post uvm_page_init() */ + if (ps->pgs == NULL) + return false; + + /* XXX: etc. */ + + return true; + +} + + +paddr_t +uvm_physmem_get_highest_frame(void) +{ + struct vm_physseg *ps = + (uvm_physmem_t) RB_TREE_MAX(&(vm_physmem.rb_tree)); + + return ps->end - 1; +} + +/* + * uvm_page_physunload: unload physical memory and return it to + * caller. + */ +bool +uvm_page_physunload(uvm_physmem_t upm, int freelist, paddr_t *paddrp) +{ + struct vm_physseg *seg; + + seg = HANDLE_TO_PHYSMEM_NODE(upm); + + if (seg->free_list != freelist) { + paddrp = NULL; + return false; + } d3070 4 a3073 18 + /* + * During cold boot, what we're about to unplug hasn't been + * put on the uvm freelist, nor has uvmexp.npages been + * updated. (This happens in uvm_page.c:uvm_page_init()) + * + * For hotplug, we assume here that the pages being unloaded + * here are completely out of sight of uvm (ie; not on any uvm + * lists), and that uvmexp.npages has been suitably + * decremented before we're called. + * + * XXX: will avail_end == start if avail_start < avail_end? + */ + + /* try from front */ + if (seg->avail_start == seg->start && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_start); + return uvm_physmem_unplug(seg->avail_start, 1); d3076 1 a3076 6 + /* try from rear */ + if (seg->avail_end == seg->end && + seg->avail_start < seg->avail_end) { + *paddrp = ctob(seg->avail_end - 1); + return uvm_physmem_unplug(seg->avail_end - 1, 1); + } a3077 1 + return false; d3080 2 a3081 2 +bool +uvm_page_physunload_force(uvm_physmem_t upm, int freelist, paddr_t *paddrp) d3083 1 d3085 1 d3089 25 a3113 4 + /* any room in this bank? */ + if (seg->avail_start >= seg->avail_end) { + paddrp = NULL; + return false; /* nope */ d3116 1 a3116 4 + *paddrp = ctob(seg->avail_start); + + /* Always unplug from front */ + return uvm_physmem_unplug(seg->avail_start, 1); a3118 1 + d3133 2 a3134 1 + d3142 1 a3142 1 + if (uvm_physmem_plug(start, end - start, &ps) == false) { d3146 2 d3155 1 a3155 1 + return ps; d3158 111 a3269 7 +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ +uvm_physmem_t +vm_physseg_find(paddr_t pframe, psize_t *offp) +{ + struct vm_physseg * ps = NULL; d3271 30 a3300 1 + ps = rb_tree_find_node(&(vm_physmem.rb_tree), &pframe); d3302 3 a3304 2 + if(ps != NULL && offp != NULL) + *offp = pframe - ps->start; d3306 9 a3314 2 + return ps; +} d3316 2 a3317 5 +#if defined(PMAP_STEAL_MEMORY) +void +uvm_physmem_set_avail_start(uvm_physmem_t upm, paddr_t avail_start) +{ + struct vm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); a3318 6 + KASSERT(avail_start < avail_end && avail_start >= ps->start); + ps->avail_start = avail_start; +} +void uvm_physmem_set_avail_end(uvm_physmem_t upm, paddr_t avail_end) +{ + struct vm_physseg *ps = HANDLE_TO_PHYSMEM_NODE(upm); d3320 3 a3322 1 + KASSERT(avail_end > avail_start && avail_end <= ps->end); d3324 8 a3331 1 + ps->avail_end = avail_end; a3332 2 + +#endif /* PMAP_STEAL_MEMORY */ d3338 2 a3339 2 +++ sys/uvm/uvm_physmem.h 13 Nov 2016 10:40:41 -0000 @@@@ -0,0 +1,99 @@@@ d3350 4 d3362 1 d3379 19 d3399 1 a3401 1 +void uvm_physmem_init_seg(uvm_physmem_t, struct vm_page *); d3463 1 d3470 1 a3470 1 +++ sys/uvm/pmap/pmap.c 13 Nov 2016 10:40:55 -0000 @ 1.4 log @Move to the rbtree implementation. tests + MD stuff .' @ text @d7 1 a7 1 +++ sys/uvm/Makefile 30 Oct 2016 16:48:42 -0000 d23 1 a23 1 +++ sys/uvm/files.uvm 30 Oct 2016 16:48:42 -0000 d38 1 a38 1 +++ sys/uvm/uvm.h 30 Oct 2016 16:48:42 -0000 d53 1 a53 1 +++ sys/uvm/uvm_amap.c 30 Oct 2016 16:48:43 -0000 d79 1 a79 1 +++ sys/uvm/uvm_anon.c 30 Oct 2016 16:48:43 -0000 d105 1 a105 1 +++ sys/uvm/uvm_bio.c 30 Oct 2016 16:48:44 -0000 d136 1 a136 1 +++ sys/uvm/uvm_device.c 30 Oct 2016 16:48:44 -0000 d169 1 a169 1 +++ sys/uvm/uvm_extern.h 30 Oct 2016 16:48:44 -0000 d186 1 a186 1 +++ sys/uvm/uvm_fault.c 30 Oct 2016 16:48:44 -0000 d223 1 a223 1 +++ sys/uvm/uvm_init.c 30 Oct 2016 16:48:44 -0000 d243 1 a243 1 +++ sys/uvm/uvm_km.c 30 Oct 2016 16:48:45 -0000 d350 1 a350 1 +++ sys/uvm/uvm_loan.c 30 Oct 2016 16:48:46 -0000 d452 1 a452 1 +++ sys/uvm/uvm_map.c 30 Oct 2016 16:48:57 -0000 d557 1 a557 1 +++ sys/uvm/uvm_page.c 30 Oct 2016 16:48:59 -0000 d571 8 a578 1 @@@@ -87,18 +89,6 @@@@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v d597 1 a597 1 @@@@ -116,7 +106,7 @@@@ int vm_page_reserve_kernel = UVM_RESERVE d606 1 a606 1 @@@@ -152,6 +142,7 @@@@ vaddr_t uvm_zerocheckkva; d614 1 a614 1 @@@@ -170,7 +161,9 @@@@ uvm_page_compare_nodes(void *ctx, const d624 1 a624 1 @@@@ -184,13 +177,16 @@@@ uvm_page_compare_key(void *ctx, const vo d641 1 a641 1 @@@@ -337,11 +333,9 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d654 1 a654 1 @@@@ -369,7 +363,7 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d663 1 a663 1 @@@@ -381,9 +375,11 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d678 1 a678 1 @@@@ -428,31 +424,16 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d682 1 a682 3 + for (bank = uvm_physmem_get_first(); + uvm_physmem_valid(bank); + bank = uvm_physmem_get_next(bank)) { d687 6 d694 1 d696 1 a696 1 d720 1 a720 1 @@@@ -625,92 +606,42 @@@@ static bool uvm_page_physget_freelist(pa d731 1 a731 1 + for (lcv = uvm_physmem_get_last() ; lcv >= uvm_physmem_get_first() ; lcv = uvm_physmem_get_prev(lcv)) d734 1 a734 1 + for (lcv = uvm_physmem_get_first() ; lcv <= uvm_physmem_get_last() ; lcv = uvm_physmem_get_next(lcv)) d744 1 a744 7 + /* Try to match at front or back on unused segment */ + if (uvm_page_physunload(lcv, freelist, paddrp) == false) { + if (paddrp == NULL) /* freelist fail, try next */ + continue; + } else + return true; d762 7 a768 1 - d791 1 a791 1 + for (lcv = uvm_physmem_get_last() ; lcv >= uvm_physmem_get_first() ; lcv = uvm_physmem_get_prev(lcv)) d794 1 a794 1 + for (lcv = uvm_physmem_get_first() ; lcv <= uvm_physmem_get_last() ; lcv = uvm_physmem_get_next(lcv)) d832 1 a832 1 @@@@ -726,228 +657,7 @@@@ uvm_page_physget(paddr_t *paddrp) d1062 1 a1062 1 @@@@ -956,21 +666,24 @@@@ struct vm_page * d1092 1 a1092 1 @@@@ -985,7 +698,8 @@@@ uvm_page_recolor(int newncolors) d1102 1 a1102 1 @@@@ -1094,6 +808,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) d1110 1 a1110 1 @@@@ -1110,6 +825,7 @@@@ attachrnd: d1118 1 a1118 1 @@@@ -1196,7 +912,9 @@@@ uvm_pagealloc_pgfl(struct uvm_cpu *ucpu, d1128 1 a1128 1 @@@@ -1219,7 +937,8 @@@@ struct vm_page * d1138 1 a1138 1 @@@@ -1389,6 +1108,7 @@@@ uvm_pagealloc_strat(struct uvm_object *o d1146 1 a1146 1 @@@@ -1481,6 +1201,7 @@@@ uvm_pagezerocheck(struct vm_page *pg) d1154 1 a1154 1 @@@@ -1632,7 +1353,9 @@@@ uvm_pagefree(struct vm_page *pg) d1164 1 a1164 1 @@@@ -1676,6 +1399,7 @@@@ uvm_page_unbusy(struct vm_page **pgs, in d1172 1 a1172 1 @@@@ -1831,6 +1555,7 @@@@ uvm_pageidlezero(void) d1180 1 a1180 1 @@@@ -1852,7 +1577,9 @@@@ uvm_pagelookup(struct uvm_object *obj, v d1190 1 a1190 1 @@@@ -1875,7 +1602,9 @@@@ uvm_pagewire(struct vm_page *pg) d1200 1 a1200 1 @@@@ -1893,7 +1622,9 @@@@ uvm_pageunwire(struct vm_page *pg) d1210 1 a1210 1 @@@@ -1912,7 +1643,9 @@@@ uvm_pagedeactivate(struct vm_page *pg) d1220 1 a1220 1 @@@@ -1936,7 +1669,9 @@@@ uvm_pageactivate(struct vm_page *pg) d1230 1 a1230 1 @@@@ -1951,7 +1686,9 @@@@ uvm_pagedequeue(struct vm_page *pg) d1240 1 a1240 1 @@@@ -1967,7 +1704,9 @@@@ uvm_pageenqueue(struct vm_page *pg) d1250 1 a1250 1 @@@@ -1981,6 +1720,7 @@@@ uvm_pagezero(struct vm_page *pg) d1258 1 a1258 1 @@@@ -2005,7 +1745,7 @@@@ bool d1267 1 a1267 1 @@@@ -2015,13 +1755,14 @@@@ uvm_pageismanaged(paddr_t pa) d1286 1 a1286 1 @@@@ -2039,6 +1780,7 @@@@ uvm_page_locked_p(struct vm_page *pg) d1294 1 a1294 1 @@@@ -2135,7 +1877,8 @@@@ uvm_page_printit(struct vm_page *pg, boo d1304 1 a1304 1 @@@@ -2143,8 +1886,14 @@@@ uvm_page_printall(void (*pr)(const char d1327 1 a1327 1 +++ sys/uvm/uvm_page.h 30 Oct 2016 16:48:59 -0000 d1396 1 a1396 1 +++ sys/uvm/uvm_pager.c 30 Oct 2016 16:48:59 -0000 d1498 1 a1498 1 +++ sys/uvm/uvm_pdaemon.c 30 Oct 2016 16:48:59 -0000 d1646 1 a1646 1 +++ sys/uvm/uvm_pdpolicy_clock.c 30 Oct 2016 16:48:59 -0000 d1666 1 a1666 1 +++ sys/uvm/uvm_pglist.c 30 Oct 2016 16:48:59 -0000 d1912 1 a1912 2 + paddr_t cidx = 0; const int bank = vm_physseg_find(candidate, &cidx); d1919 2 d1922 1 a1922 1 + "vm_physseg_find(%#x) (%d) != psi %"PRIxPHYSMEM, d1992 2 a1993 2 +++ sys/uvm/uvm_physmem.c 30 Oct 2016 16:48:59 -0000 @@@@ -0,0 +1,645 @@@@ d2060 1 a2060 1 + * rbtree backing implementation by: d2070 1 d2075 1 d2080 1 d2092 1 a2092 1 + struct vm_page *lastpg; /* vm_page structure for end */ d2109 13 d2159 1 a2159 1 + return kmem_zalloc(sz, KM_SLEEP); d2206 292 d2551 56 d2614 1 a2614 1 + KASSERT(upm != NULL); a2617 2 + KASSERT(seg->pgs == NULL); + a2619 1 + seg->lastpg = seg->pgs + n; d2631 1 d2634 1 a2763 3 + if (ps->lastpg == NULL) + return false; + d2772 1 a2772 1 +uvm_physmem_get_highest(void) d2777 1 a2777 1 + return ps->end; d2797 9 a2805 1 + * XXX: why is uvmexp.npages not updated? d2813 1 a2813 11 + seg->avail_start++; + seg->start++; + /* nothing left? nuke it */ + if (seg->avail_start == seg->end) { + if (vm_physmem.nentries == 1) + panic("uvm_page_physunload: out of memory!"); + rb_tree_remove_node(&(vm_physmem.rb_tree), upm); + uvm_physmem_free(upm, sizeof(struct vm_physseg)); + vm_physmem.nentries--; + } + return (true); d2820 1 a2820 11 + seg->avail_end--; + seg->end--; + /* nothing left? nuke it */ + if (seg->avail_end == seg->start) { + if (vm_physmem.nentries == 1) + panic("uvm_page_physunload: out of memory!"); + rb_tree_remove_node(&(vm_physmem.rb_tree), upm); + uvm_physmem_free(upm, sizeof(struct vm_physseg)); + vm_physmem.nentries--; + } + return (true); d2840 3 a2842 13 + seg->avail_start++; + /* truncate! */ + seg->start = seg->avail_start; + + /* nothing left? nuke it */ + if (seg->avail_start == seg->end) { + if (vm_physmem.nentries == 1) + panic("uvm_page_physunload: out of memory!"); + rb_tree_remove_node(&(vm_physmem.rb_tree), upm); + uvm_physmem_free(upm, sizeof(struct vm_physseg)); + vm_physmem.nentries--; + } + return (true); d2859 1 a2859 4 + int preload; + psize_t npages; + struct vm_page *pgs; + struct vm_physseg *ps, *current_ps; d2868 2 a2869 40 + /* + * do we have room? + */ + + ps = uvm_physmem_alloc(sizeof (struct vm_physseg)); + if (ps == NULL) { + printf("uvm_page_physload: unable to load physical memory " + "segment\n"); + printf("\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n", + VM_PHYSSEG_MAX, (long long)start, (long long)end); + printf("\tincrease VM_PHYSSEG_MAX\n"); + return UVM_PHYSMEM_TYPE_INVALID_OVERFLOW; + } + + /* + * check to see if this is a "preload" (i.e. uvm_page_init hasn't been + * called yet, so kmem is not available). + */ + + preload = 1; /* We are going to assume it is a preload */ + RB_TREE_FOREACH(current_ps, &(vm_physmem.rb_tree)) { + /* If there are non NULL pages then we are not in a preload */ + if (current_ps->pgs) { + preload = 0; + break; + } + } + + current_ps = NULL; + + /* + * if VM is already running, attempt to kmem_alloc vm_page structures + */ + + if (!preload) { + npages = end - start; + pgs = kmem_zalloc(sizeof *pgs * npages, KM_SLEEP); + } else { + pgs = NULL; + npages = 0; d2872 1 a2872 3 + + ps->start = start; + ps->end = end; d2876 1 a2876 33 + ps->pgs = pgs; + ps->lastpg = pgs + npages; + + ps->free_list = free_list; + + /* + * now insert us in the proper place in vm_physmem.rb_tree + */ + + current_ps = rb_tree_insert_node(&(vm_physmem.rb_tree), ps); + if (current_ps != ps) { + panic("uvm_page_physload: Duplicate address range detected!"); + } + vm_physmem.nentries++; + + if (!preload) { + paddr_t i; + paddr_t paddr; + + /* init and free vm_pages (we've already zeroed them) */ + paddr = ctob(ps->start); + for (i = 0 ; i < npages ; i++, paddr += PAGE_SIZE) { + ps->pgs[i].phys_addr = paddr; +#ifdef __HAVE_VM_PAGE_MD + VM_MDPAGE_INIT(&ps->pgs[i]); +#endif + if (atop(paddr) >= ps->avail_start && + atop(paddr) < ps->avail_end) { + uvmexp.npages++; + /* add page to free pool */ + uvm_pagefree(&ps->pgs[i]); + } + } a2877 4 + physmem += npages; + + uvmpdpol_reinit(); + } d2898 20 d2923 2 a2924 2 +++ sys/uvm/uvm_physmem.h 30 Oct 2016 16:48:59 -0000 @@@@ -0,0 +1,83 @@@@ d2943 1 a2943 1 +#define PRIxPHYSMEM "d" d2960 3 d2964 2 a2965 1 +void uvm_physmem_init_seg(uvm_physmem_t, struct vm_page *); d3000 1 a3000 1 +paddr_t uvm_physmem_get_highest(void); d3011 12 d3030 1 a3030 1 +++ sys/uvm/pmap/pmap.c 30 Oct 2016 16:49:00 -0000 d3074 2 a3075 1 aprint_debug("%s: seg %u: %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR"\n", d3079 1 a3079 1 + uvm_physmem_get_avail_start(bank),uvm_physmem_get_start(bank), d3084 1 d3087 1 a3087 1 aprint_debug("%s: seg %u: bad start\n", __func__, bank); d3092 1 d3094 1 a3094 1 aprint_debug("%s: seg %u: too small for %zu pages\n", d3104 1 a3104 1 @@@@ -490,44 +495,32 @@@@ pmap_steal_memory(vsize_t size, vaddr_t d3113 1 a3113 1 + if (uvm_physmem_valid(maybe_bank == false) a3123 1 + paddr_t stolenpa; a3124 1 + int freelist; d3132 3 a3134 1 - d3154 1 a3154 10 + freelist = uvm_physmem_get_free_list(bank); + uvm_page_physunload_force(bank, freelist, &pa); + stolenpa = pa; + + KASSERT(npgs > 0); + /* XXX: This loop assumes linear pa allocation */ + while(pa + ptoa(npgs - 1) > stolenpa) + uvm_page_physunload_force(bank, freelist, &stolenpa); + + aprint_debug("%s: seg %u: %zu pages stolen (%#"PRIxPADDR" left)\n", @ 1.3 log @Chop off unknown file listings in the diff. @ text @d7 1 a7 1 +++ sys/uvm/Makefile 28 Oct 2016 08:23:14 -0000 d23 1 a23 1 +++ sys/uvm/files.uvm 28 Oct 2016 08:23:14 -0000 d38 1 a38 1 +++ sys/uvm/uvm.h 28 Oct 2016 08:23:14 -0000 d53 1 a53 1 +++ sys/uvm/uvm_amap.c 28 Oct 2016 08:23:15 -0000 d79 1 a79 1 +++ sys/uvm/uvm_anon.c 28 Oct 2016 08:23:15 -0000 d105 1 a105 1 +++ sys/uvm/uvm_bio.c 28 Oct 2016 08:23:16 -0000 d136 1 a136 1 +++ sys/uvm/uvm_device.c 28 Oct 2016 08:23:16 -0000 d169 1 a169 1 +++ sys/uvm/uvm_extern.h 28 Oct 2016 08:23:16 -0000 d186 1 a186 1 +++ sys/uvm/uvm_fault.c 28 Oct 2016 08:23:18 -0000 d223 1 a223 1 +++ sys/uvm/uvm_init.c 28 Oct 2016 08:23:18 -0000 d243 1 a243 1 +++ sys/uvm/uvm_km.c 28 Oct 2016 08:23:18 -0000 d350 1 a350 1 +++ sys/uvm/uvm_loan.c 28 Oct 2016 08:23:19 -0000 d452 1 a452 1 +++ sys/uvm/uvm_map.c 28 Oct 2016 08:23:21 -0000 d557 1 a557 1 +++ sys/uvm/uvm_page.c 28 Oct 2016 08:23:22 -0000 d634 1 a634 1 @@@@ -337,11 +333,8 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d640 2 a641 1 - int lcv; a643 1 + uvm_physmem_t lcv; d647 1 a647 1 @@@@ -369,7 +362,7 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d652 1 a652 1 + if (uvm_physmem_get_last() == -1) d656 1 a656 1 @@@@ -381,9 +374,11 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d664 4 a667 4 + for (lcv = uvm_physmem_get_first(); + lcv <= uvm_physmem_get_last() ; + lcv = uvm_physmem_get_next(lcv)) { + freepages += (uvm_physmem_get_end(lcv) - uvm_physmem_get_start(lcv)); d671 1 a671 1 @@@@ -428,31 +423,16 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr d675 3 a677 3 + for (lcv = uvm_physmem_get_first(); + lcv <= uvm_physmem_get_last(); + lcv = uvm_physmem_get_next(lcv)) { d682 2 a683 2 + n = uvm_physmem_get_end(lcv) - uvm_physmem_get_start(lcv); + uvm_physmem_init_seg(lcv, pagearray); d708 1 a708 1 @@@@ -625,92 +605,42 @@@@ static bool uvm_page_physget_freelist(pa d732 7 a738 1 - d756 1 a756 7 + /* Try to match at front or back on unused segment */ + if (uvm_page_physunload(lcv, freelist, paddrp) == false) { + if (paddrp == NULL) /* freelist fail, try next */ + continue; + } else + return true; d820 1 a820 1 @@@@ -726,228 +656,7 @@@@ uvm_page_physget(paddr_t *paddrp) d1050 1 a1050 1 @@@@ -956,21 +665,24 @@@@ struct vm_page * d1055 1 d1057 1 a1057 1 int psi; d1059 2 a1060 2 psi = vm_physseg_find(pf, &off); if (psi != -1) d1062 3 a1064 1 + return uvm_physmem_get_pg(psi, off); d1080 1 a1080 1 @@@@ -985,7 +697,8 @@@@ uvm_page_recolor(int newncolors) d1086 1 a1086 1 + uvm_physmem_t lcv; d1090 9 a1098 10 @@@@ -1076,7 +789,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) struct pgfreelist pgfl; struct uvm_cpu *ucpu; vsize_t bucketcount; - int lcv; + uvm_physmem_t lcv; if (CPU_IS_PRIMARY(ci)) { /* Already done in uvm_page_init(). */ @@@@ -1110,6 +823,7 @@@@ attachrnd: d1106 1 a1106 1 @@@@ -1196,7 +910,9 @@@@ uvm_pagealloc_pgfl(struct uvm_cpu *ucpu, d1116 1 a1116 1 @@@@ -1219,7 +935,8 @@@@ struct vm_page * d1122 1 a1122 1 + uvm_physmem_t lcv; d1126 1 a1126 1 @@@@ -1389,6 +1106,7 @@@@ uvm_pagealloc_strat(struct uvm_object *o d1134 1 a1134 1 @@@@ -1481,6 +1199,7 @@@@ uvm_pagezerocheck(struct vm_page *pg) d1142 1 a1142 1 @@@@ -1632,7 +1351,9 @@@@ uvm_pagefree(struct vm_page *pg) d1152 1 a1152 1 @@@@ -1676,6 +1397,7 @@@@ uvm_page_unbusy(struct vm_page **pgs, in d1160 1 a1160 1 @@@@ -1831,6 +1553,7 @@@@ uvm_pageidlezero(void) d1168 1 a1168 1 @@@@ -1852,7 +1575,9 @@@@ uvm_pagelookup(struct uvm_object *obj, v d1178 1 a1178 1 @@@@ -1875,7 +1600,9 @@@@ uvm_pagewire(struct vm_page *pg) d1188 1 a1188 1 @@@@ -1893,7 +1620,9 @@@@ uvm_pageunwire(struct vm_page *pg) d1198 1 a1198 1 @@@@ -1912,7 +1641,9 @@@@ uvm_pagedeactivate(struct vm_page *pg) d1208 1 a1208 1 @@@@ -1936,7 +1667,9 @@@@ uvm_pageactivate(struct vm_page *pg) d1218 1 a1218 1 @@@@ -1951,7 +1684,9 @@@@ uvm_pagedequeue(struct vm_page *pg) d1228 1 a1228 1 @@@@ -1967,7 +1702,9 @@@@ uvm_pageenqueue(struct vm_page *pg) d1238 1 a1238 1 @@@@ -1981,6 +1718,7 @@@@ uvm_pagezero(struct vm_page *pg) d1246 10 a1255 1 @@@@ -2015,13 +1753,14 @@@@ uvm_pageismanaged(paddr_t pa) d1260 1 a1260 1 + uvm_physmem_t lcv; d1262 2 a1263 2 lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); KASSERT(lcv != -1); d1265 3 a1267 1 + return uvm_physmem_get_free_list(lcv); d1274 1 a1274 1 @@@@ -2039,6 +1778,7 @@@@ uvm_page_locked_p(struct vm_page *pg) d1282 1 a1282 1 @@@@ -2135,7 +1875,8 @@@@ uvm_page_printit(struct vm_page *pg, boo d1292 1 a1292 1 @@@@ -2143,8 +1884,14 @@@@ uvm_page_printall(void (*pr)(const char d1315 1 a1315 1 +++ sys/uvm/uvm_page.h 28 Oct 2016 08:23:22 -0000 d1363 1 a1363 1 @@@@ -366,10 +333,14 @@@@ bool uvm_page_locked_p(struct vm_page *) a1367 1 +int vm_physseg_find(paddr_t, psize_t *); d1384 1 a1384 1 +++ sys/uvm/uvm_pager.c 28 Oct 2016 08:23:22 -0000 d1486 1 a1486 1 +++ sys/uvm/uvm_pdaemon.c 28 Oct 2016 08:23:23 -0000 d1634 1 a1634 1 +++ sys/uvm/uvm_pdpolicy_clock.c 28 Oct 2016 08:23:23 -0000 d1654 1 a1654 1 +++ sys/uvm/uvm_pglist.c 28 Oct 2016 08:23:23 -0000 d1979 2 a1980 2 +++ sys/uvm/uvm_physmem.c 28 Oct 2016 08:23:23 -0000 @@@@ -0,0 +1,638 @@@@ d2047 2 d2064 1 a2064 11 +/* + * physical memory config is stored in vm_physmem. + */ + +#define VM_PHYSMEM_PTR(i) (&vm_physmem[i]) +#if VM_PHYSSEG_MAX == 1 +#define VM_PHYSMEM_PTR_SWAP(i, j) /* impossible */ +#else +#define VM_PHYSMEM_PTR_SWAP(i, j) \ + do { vm_physmem[(i)] = vm_physmem[(j)]; } while (0) +#endif d2070 1 d2085 124 d2210 12 a2221 3 +static struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ +static int vm_nphysseg; /* XXXCDC: uvm.nphysseg */ +#define vm_nphysmem vm_nphysseg d2225 2 a2226 2 + /* XXX: Provisioning for rb_tree related init(s) */ + return; d2230 1 a2230 1 +uvm_physmem_init_seg(uvm_physmem_t lcv, struct vm_page *pgs) d2237 1 a2237 1 + KASSERT(lcv >= 0 && lcv < vm_nphysmem); d2239 1 a2239 1 + seg = VM_PHYSMEM_PTR(lcv); d2268 1 a2268 1 +uvm_physmem_get_start(uvm_physmem_t lcv) d2270 1 a2270 1 + if (uvm_physmem_valid(lcv) == false) d2273 1 a2273 1 + return VM_PHYSMEM_PTR(lcv)->start; d2277 1 a2277 1 +uvm_physmem_get_end(uvm_physmem_t lcv) d2279 1 a2279 1 + if (uvm_physmem_valid(lcv) == false) d2282 1 a2282 1 + return VM_PHYSMEM_PTR(lcv)->end; d2286 1 a2286 1 +uvm_physmem_get_avail_start(uvm_physmem_t lcv) d2288 1 a2288 1 + if (uvm_physmem_valid(lcv) == false) d2291 1 a2291 1 + return VM_PHYSMEM_PTR(lcv)->avail_start; d2295 1 a2295 1 +uvm_physmem_get_avail_end(uvm_physmem_t lcv) d2297 1 a2297 1 + if (uvm_physmem_valid(lcv) == false) d2300 1 a2300 1 + return VM_PHYSMEM_PTR(lcv)->avail_end; d2304 1 a2304 1 +uvm_physmem_get_pg(uvm_physmem_t lcv, paddr_t idx) d2307 1 a2307 1 + return &VM_PHYSMEM_PTR(lcv)->pgs[idx]; d2312 1 a2312 1 +uvm_physmem_get_pmseg(uvm_physmem_t lcv) d2315 1 a2315 1 + return &VM_PHYSMEM_PTR(lcv)->pmseg; d2320 1 a2320 1 +uvm_physmem_get_free_list(uvm_physmem_t lcv) d2322 1 a2322 1 + return VM_PHYSMEM_PTR(lcv)->free_list; d2326 1 a2326 1 +uvm_physmem_get_start_hint(uvm_physmem_t lcv) d2328 1 a2328 1 + return VM_PHYSMEM_PTR(lcv)->start_hint; d2332 1 a2332 1 +uvm_physmem_set_start_hint(uvm_physmem_t lcv, u_int start_hint) d2334 1 a2334 1 + if (uvm_physmem_valid(lcv) == false) d2337 1 a2337 1 + VM_PHYSMEM_PTR(lcv)->start_hint = start_hint; d2341 2 a2342 2 +int +uvm_physmem_get_next(uvm_physmem_t lcv) d2344 2 a2345 1 + return (lcv + 1); d2348 2 a2349 2 +int +uvm_physmem_get_prev(uvm_physmem_t lcv) d2351 2 a2352 1 + return (lcv - 1); d2355 1 a2355 1 +int d2358 1 a2358 1 + return (vm_nphysseg - 1); d2361 1 a2361 1 +int d2364 1 a2364 1 + return 0; d2368 1 a2368 1 +uvm_physmem_valid(uvm_physmem_t lcv) d2372 1 a2372 4 + if (lcv < 0) + return false; + + if (lcv >= vm_nphysseg) d2382 1 a2382 1 + ps = VM_PHYSMEM_PTR(lcv); d2401 2 a2402 3 + int lcv; + paddr_t last = 0; + struct vm_physseg *ps; d2404 1 a2404 7 + for (lcv = 0; lcv < vm_nphysseg; lcv++) { + ps = VM_PHYSMEM_PTR(lcv); + if (last < ps->end) + last = ps->end; + } + + return last; d2412 1 a2412 1 +uvm_page_physunload(uvm_physmem_t psi, int freelist, paddr_t *paddrp) a2413 1 + int x; d2416 1 a2416 1 + seg = VM_PHYSMEM_PTR(psi); d2423 5 d2436 5 a2440 6 + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); d2453 5 a2457 6 + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); d2466 1 a2466 1 +uvm_page_physunload_force(uvm_physmem_t psi, int freelist, paddr_t *paddrp) a2467 1 + int x; d2470 1 a2470 1 + seg = VM_PHYSMEM_PTR(psi); d2485 5 a2489 6 + if (vm_nphysmem == 1) + panic("uvm_page_physget: out of memory!"); + vm_nphysmem--; + for (x = psi ; x < vm_nphysmem ; x++) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x + 1); d2508 1 a2508 1 + int preload, lcv; d2511 1 a2511 1 + struct vm_physseg *ps; d2524 2 a2525 1 + if (vm_nphysmem == VM_PHYSSEG_MAX) { d2539 5 a2543 2 + for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) { + if (VM_PHYSMEM_PTR(lcv)->pgs) d2545 1 d2547 2 a2548 1 + preload = (lcv == vm_nphysmem); a2561 37 + /* + * now insert us in the proper place in vm_physmem[] + */ + +#if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) + /* random: put it at the end (easy!) */ + ps = VM_PHYSMEM_PTR(vm_nphysmem); +#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_PTR(lcv)->start) + break; + ps = VM_PHYSMEM_PTR(lcv); + /* move back other entries, if necessary ... */ + for (x = vm_nphysmem ; x > lcv ; x--) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x - 1); + } +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) + { + int x; + /* sort by largest segment first */ + for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) + if ((end - start) > + (VM_PHYSMEM_PTR(lcv)->end - VM_PHYSMEM_PTR(lcv)->start)) + break; + ps = VM_PHYSMEM_PTR(lcv); + /* move back other entries, if necessary ... */ + for (x = vm_nphysmem ; x > lcv ; x--) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x - 1); + } +#else + panic("uvm_page_physload: unknown physseg strategy selected!"); +#endif d2572 10 a2581 1 + vm_nphysmem++; d2607 1 a2607 1 + return lcv; a2609 11 +/* + * when VM_PHYSSEG_MAX is 1, we can simplify these functions + */ + +#if VM_PHYSSEG_MAX == 1 +static inline int vm_physseg_find_contig(struct vm_physseg *, int, paddr_t, psize_t *); +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) +static inline int vm_physseg_find_bsearch(struct vm_physseg *, int, paddr_t, psize_t *); +#else +static inline int vm_physseg_find_linear(struct vm_physseg *, int, paddr_t, psize_t *); +#endif d2614 1 a2614 1 +int d2617 1 d2619 1 a2619 8 +#if VM_PHYSSEG_MAX == 1 + return vm_physseg_find_contig(vm_physmem, vm_nphysseg, pframe, offp); +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) + return vm_physseg_find_bsearch(vm_physmem, vm_nphysseg, pframe, offp); +#else + return vm_physseg_find_linear(vm_physmem, vm_nphysseg, pframe, offp); +#endif +} d2621 2 a2622 4 +#if VM_PHYSSEG_MAX == 1 +static inline int +vm_physseg_find_contig(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ d2624 1 a2624 7 + /* 'contig' case */ + if (pframe >= segs[0].start && pframe < segs[0].end) { + if (offp) + *offp = pframe - segs[0].start; + return(0); + } + return(-1); a2625 64 + +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) + +static inline int +vm_physseg_find_bsearch(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ + /* binary search for it */ + int start, len, guess; + + /* + * if try is too large (thus target is less than try) we reduce + * the length to trunc(len/2) [i.e. everything smaller than "try"] + * + * if the try is too small (thus target is greater than try) then + * we set the new start to be (try + 1). this means we need to + * reduce the length to (round(len/2) - 1). + * + * note "adjust" below which takes advantage of the fact that + * (round(len/2) - 1) == trunc((len - 1) / 2) + * for any value of len we may have + */ + + for (start = 0, len = nsegs ; len != 0 ; len = len / 2) { + guess = start + (len / 2); /* try in the middle */ + + /* start past our try? */ + if (pframe >= segs[guess].start) { + /* was try correct? */ + if (pframe < segs[guess].end) { + if (offp) + *offp = pframe - segs[guess].start; + return guess; /* got it */ + } + start = guess + 1; /* next time, start here */ + len--; /* "adjust" */ + } else { + /* + * pframe before try, just reduce length of + * region, done in "for" loop + */ + } + } + return(-1); +} + +#else + +static inline int +vm_physseg_find_linear(struct vm_physseg *segs, int nsegs, paddr_t pframe, psize_t *offp) +{ + /* linear search for it */ + int lcv; + + for (lcv = 0; lcv < nsegs; lcv++) { + if (pframe >= segs[lcv].start && + pframe < segs[lcv].end) { + if (offp) + *offp = pframe - segs[lcv].start; + return(lcv); /* got it */ + } + } + return(-1); +} +#endif d2631 1 a2631 1 +++ sys/uvm/uvm_physmem.h 28 Oct 2016 08:23:23 -0000 d2656 1 a2656 1 + * a2659 4 + +#define UVM_PHYSMEM_TYPE_INVALID -1 /* Generic invalid value */ +#define UVM_PHYSMEM_TYPE_INVALID_EMPTY -1 /* empty segment access */ +#define UVM_PHYSMEM_TYPE_INVALID_OVERFLOW (uvm_physmem_get_last() + 1) /* ran off the end of the last segment */ d2661 5 a2665 1 +typedef int uvm_physmem_t; d2695 1 a2695 1 + * Returns: -1 if the segment number is invalid d2722 1 a2722 1 +++ sys/uvm/pmap/pmap.c 28 Oct 2016 08:23:24 -0000 @ 1.2 log @Immutable uvm_physmem_t test, shakedown of tests to make sure that the semantics are clear. Tested on amd64 @ text @a0 5 ? sys/uvm/files_BACKUP_21538.uvm ? sys/uvm/files_BASE_21538.uvm ? sys/uvm/files_LOCAL_21538.uvm ? sys/uvm/files_REMOTE_21538.uvm ? sys/uvm/uvm_physmem_new.c @ 1.1 log @Initial revision @ text @d1 5 d12 1 a12 1 +++ sys/uvm/Makefile 20 Oct 2016 14:19:24 -0000 d28 1 a28 1 +++ sys/uvm/files.uvm 20 Oct 2016 14:19:24 -0000 d43 1 a43 1 +++ sys/uvm/uvm.h 20 Oct 2016 14:19:24 -0000 d58 1 a58 1 +++ sys/uvm/uvm_amap.c 20 Oct 2016 14:19:24 -0000 d84 1 a84 1 +++ sys/uvm/uvm_anon.c 20 Oct 2016 14:19:24 -0000 d110 1 a110 1 +++ sys/uvm/uvm_bio.c 20 Oct 2016 14:19:25 -0000 d141 1 a141 1 +++ sys/uvm/uvm_device.c 20 Oct 2016 14:19:25 -0000 d174 1 a174 1 +++ sys/uvm/uvm_extern.h 20 Oct 2016 14:19:25 -0000 d191 1 a191 1 +++ sys/uvm/uvm_fault.c 20 Oct 2016 14:19:26 -0000 d228 1 a228 1 +++ sys/uvm/uvm_init.c 20 Oct 2016 14:19:26 -0000 d248 1 a248 1 +++ sys/uvm/uvm_km.c 20 Oct 2016 14:19:27 -0000 d355 1 a355 1 +++ sys/uvm/uvm_loan.c 20 Oct 2016 14:19:28 -0000 d457 1 a457 1 +++ sys/uvm/uvm_map.c 20 Oct 2016 14:19:30 -0000 d562 1 a562 1 +++ sys/uvm/uvm_page.c 20 Oct 2016 14:19:30 -0000 d676 1 a676 1 @@@@ -428,31 +423,19 @@@@ uvm_page_init(vaddr_t *kvm_startp, vaddr a682 4 + + n = uvm_physmem_get_end(lcv) - uvm_physmem_get_start(lcv); + n = ((n + 1) << PAGE_SHIFT) / + (PAGE_SIZE + sizeof(struct vm_page)); d687 1 d713 1 a713 1 @@@@ -625,92 +608,42 @@@@ static bool uvm_page_physget_freelist(pa d825 1 a825 1 @@@@ -726,228 +659,7 @@@@ uvm_page_physget(paddr_t *paddrp) d1055 1 a1055 1 @@@@ -956,21 +668,24 @@@@ struct vm_page * d1082 1 a1082 1 @@@@ -985,7 +700,8 @@@@ uvm_page_recolor(int newncolors) d1092 1 a1092 1 @@@@ -1076,7 +792,7 @@@@ uvm_cpu_attach(struct cpu_info *ci) d1101 1 a1101 1 @@@@ -1110,6 +826,7 @@@@ attachrnd: d1109 1 a1109 1 @@@@ -1196,7 +913,9 @@@@ uvm_pagealloc_pgfl(struct uvm_cpu *ucpu, d1119 1 a1119 1 @@@@ -1219,7 +938,8 @@@@ struct vm_page * d1129 1 a1129 1 @@@@ -1389,6 +1109,7 @@@@ uvm_pagealloc_strat(struct uvm_object *o d1137 1 a1137 1 @@@@ -1481,6 +1202,7 @@@@ uvm_pagezerocheck(struct vm_page *pg) d1145 1 a1145 1 @@@@ -1632,7 +1354,9 @@@@ uvm_pagefree(struct vm_page *pg) d1155 1 a1155 1 @@@@ -1676,6 +1400,7 @@@@ uvm_page_unbusy(struct vm_page **pgs, in d1163 1 a1163 1 @@@@ -1831,6 +1556,7 @@@@ uvm_pageidlezero(void) d1171 1 a1171 1 @@@@ -1852,7 +1578,9 @@@@ uvm_pagelookup(struct uvm_object *obj, v d1181 1 a1181 1 @@@@ -1875,7 +1603,9 @@@@ uvm_pagewire(struct vm_page *pg) d1191 1 a1191 1 @@@@ -1893,7 +1623,9 @@@@ uvm_pageunwire(struct vm_page *pg) d1201 1 a1201 1 @@@@ -1912,7 +1644,9 @@@@ uvm_pagedeactivate(struct vm_page *pg) d1211 1 a1211 1 @@@@ -1936,7 +1670,9 @@@@ uvm_pageactivate(struct vm_page *pg) d1221 1 a1221 1 @@@@ -1951,7 +1687,9 @@@@ uvm_pagedequeue(struct vm_page *pg) d1231 1 a1231 1 @@@@ -1967,7 +1705,9 @@@@ uvm_pageenqueue(struct vm_page *pg) d1241 1 a1241 1 @@@@ -1981,6 +1721,7 @@@@ uvm_pagezero(struct vm_page *pg) d1249 1 a1249 1 @@@@ -2015,13 +1756,14 @@@@ uvm_pageismanaged(paddr_t pa) d1266 1 a1266 1 @@@@ -2039,6 +1781,7 @@@@ uvm_page_locked_p(struct vm_page *pg) d1274 1 a1274 1 @@@@ -2135,7 +1878,8 @@@@ uvm_page_printit(struct vm_page *pg, boo d1284 1 a1284 1 @@@@ -2143,8 +1887,14 @@@@ uvm_page_printall(void (*pr)(const char d1307 1 a1307 1 +++ sys/uvm/uvm_page.h 20 Oct 2016 14:19:31 -0000 d1377 1 a1377 1 +++ sys/uvm/uvm_pager.c 20 Oct 2016 14:19:31 -0000 d1479 1 a1479 1 +++ sys/uvm/uvm_pdaemon.c 20 Oct 2016 14:19:31 -0000 d1627 1 a1627 1 +++ sys/uvm/uvm_pdpolicy_clock.c 20 Oct 2016 14:19:31 -0000 d1647 1 a1647 1 +++ sys/uvm/uvm_pglist.c 20 Oct 2016 14:19:32 -0000 d1972 2 a1973 2 +++ sys/uvm/uvm_physmem.c 20 Oct 2016 14:19:32 -0000 @@@@ -0,0 +1,635 @@@@ a2110 3 + n = ((n + 1) << PAGE_SHIFT) / + (PAGE_SIZE + sizeof(struct vm_page)); + d2304 1 d2322 1 d2354 2 d2379 1 a2379 1 +void d2405 1 a2405 1 + return; d2503 2 d2555 1 a2555 1 + u_int start, len, guess; d2617 2 a2618 2 +++ sys/uvm/uvm_physmem.h 20 Oct 2016 14:19:32 -0000 @@@@ -0,0 +1,72 @@@@ d2638 12 a2649 1 +#define UVM_PHYSMEM_TYPE_INVALID -1 d2693 1 a2693 1 +void uvm_page_physload(paddr_t, paddr_t, paddr_t, d2708 1 a2708 1 +++ sys/uvm/pmap/pmap.c 20 Oct 2016 14:19:33 -0000 @