Module Name: src Committed By: uebayasi Date: Thu Nov 25 04:45:30 UTC 2010
Modified Files: src/sys/uvm: uvm_page.c uvm_page.h uvm_pglist.c Log Message: Revert vm_physseg allocation changes. A report says that it causes panics when used with mplayer in heavy load. To generate a diff of this commit: cvs rdiff -u -r1.166 -r1.167 src/sys/uvm/uvm_page.c cvs rdiff -u -r1.67 -r1.68 src/sys/uvm/uvm_page.h cvs rdiff -u -r1.50 -r1.51 src/sys/uvm/uvm_pglist.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_page.c diff -u src/sys/uvm/uvm_page.c:1.166 src/sys/uvm/uvm_page.c:1.167 --- src/sys/uvm/uvm_page.c:1.166 Sun Nov 14 15:18:07 2010 +++ src/sys/uvm/uvm_page.c Thu Nov 25 04:45:30 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.c,v 1.166 2010/11/14 15:18:07 uebayasi Exp $ */ +/* $NetBSD: uvm_page.c,v 1.167 2010/11/25 04:45:30 uebayasi Exp $ */ /* * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -97,7 +97,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.166 2010/11/14 15:18:07 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.167 2010/11/25 04:45:30 uebayasi Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -125,13 +125,9 @@ * physical memory config is stored in vm_physmem. */ -SIMPLEQ_HEAD(vm_physseg_freelist, vm_physseg); - -struct vm_physseg *vm_physmem_ptrs[VM_PHYSSEG_MAX]; -int vm_nphysmem = 0; -static struct vm_physseg vm_physmem_store[VM_PHYSSEG_MAX]; -static struct vm_physseg_freelist vm_physmem_freelist = - SIMPLEQ_HEAD_INITIALIZER(vm_physmem_freelist); +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 @@ -185,19 +181,6 @@ static void uvm_pageinsert(struct uvm_object *, struct vm_page *); static void uvm_pageremove(struct uvm_object *, struct vm_page *); -static struct vm_physseg *uvm_physseg_alloc( - struct vm_physseg_freelist * const, struct vm_physseg **, int, - const paddr_t, const paddr_t); -#if 0 -static void uvm_physseg_free(struct vm_physseg_freelist *, - struct vm_physseg **, struct vm_physseg *); -#endif -static void uvm_physseg_init(void); -static void uvm_physseg_insert(struct vm_physseg *, - struct vm_physseg **, int); -#if 0 -static void uvm_physseg_remove(struct vm_physseg **, struct vm_physseg *); -#endif /* * per-object tree of pages @@ -701,6 +684,7 @@ 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); @@ -718,6 +702,7 @@ 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); @@ -748,6 +733,7 @@ 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); @@ -782,18 +768,31 @@ uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, paddr_t avail_end, int free_list) { - struct vm_physseg *seg; - int lcv; + 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"); - seg = uvm_physseg_alloc(&vm_physmem_freelist, vm_physmem_ptrs, - vm_nphysmem, start, end); - KASSERT(seg != NULL); + /* + * 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; + } - seg->avail_start = avail_start; - seg->avail_end = avail_end; /* * check to see if this is a "preload" (i.e. uvm_page_init hasn't been * called yet, so malloc is not available). @@ -803,188 +802,112 @@ if (VM_PHYSMEM_PTR(lcv)->pgs) break; } - if (lcv == vm_nphysmem) { - seg->pgs = NULL; - seg->lastpg = NULL; - seg->free_list = free_list; - } else { - panic("uvm_page_physload: " - "tried to add RAM after uvm_page_init"); - } - vm_nphysmem++; -} - -#if 0 -void -uvm_page_physunload(void *cookie) -{ - struct vm_physseg *seg = cookie; - - panic("memory unload is not supported yet"); - - uvm_physseg_free(&vm_physmem_freelist, vm_physmem_ptrs, seg); - vm_nphysmem--; -} -#endif - -int uvm_physseg_inited; - -static struct vm_physseg * -uvm_physseg_alloc(struct vm_physseg_freelist *freelist, - struct vm_physseg **segs, int nsegs, - const paddr_t start, const paddr_t end) -{ - struct vm_physseg *ps; - - if (uvmexp.pagesize == 0) - panic("uvm_page_physload: page size not set!"); - if (start >= end) - panic("uvm_page_physload: start >= end"); - if (nsegs == VM_PHYSSEG_MAX) - panic("uvm_page_physload: unable to load physical memory " - "segment\n" - "\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n" - "\tincrease VM_PHYSSEG_MAX\n", - VM_PHYSSEG_MAX, (long long)start, (long long)end); - - if (uvm_physseg_inited == 0) { - uvm_physseg_inited = 1; - uvm_physseg_init(); - } - - ps = SIMPLEQ_FIRST(freelist); - KASSERT(ps != NULL); - SIMPLEQ_REMOVE_HEAD(freelist, list); - - ps->start = start; - ps->end = end; - uvm_physseg_insert(ps, segs, nsegs); - return ps; -} - -#if 0 -void -uvm_physseg_free(struct vm_physseg_freelist *freelist, - struct vm_physseg **segs, struct vm_physseg *seg) -{ - - uvm_physseg_remove(segs, seg); - SIMPLEQ_INSERT_TAIL(freelist, seg, list); -} -#endif + preload = (lcv == vm_nphysmem); -static void -uvm_physseg_init(void) -{ - int lcv; + /* + * if VM is already running, attempt to malloc() vm_page structures + */ - for (lcv = 0; lcv < VM_PHYSSEG_MAX; lcv++) { - SIMPLEQ_INSERT_TAIL(&vm_physmem_freelist, - &vm_physmem_store[lcv], list); + if (!preload) { + panic("uvm_page_physload: tried to add RAM after vm_mem_init"); + } else { + pgs = NULL; + npages = 0; } -} -static void -uvm_physseg_insert(struct vm_physseg *ps, - struct vm_physseg **segs, int nsegs) -{ + /* + * now insert us in the proper place in vm_physmem[] + */ #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) /* random: put it at the end (easy!) */ - segs[nsegs] = ps; + ps = VM_PHYSMEM_PTR(vm_nphysmem); #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) { - int lcv; int x; /* sort by address for binary search */ - for (lcv = 0 ; lcv < nsegs ; lcv++) - if (ps->start < segs[lcv]->start) + 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 = nsegs ; x > lcv ; x--) - segs[x] = segs[x - 1]; - segs[lcv] = ps; + for (x = vm_nphysmem ; x > lcv ; x--) + /* structure copy */ + VM_PHYSMEM_PTR_SWAP(x, x - 1); } #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) { - int lcv; int x; /* sort by largest segment first */ - for (lcv = 0 ; lcv < nsegs ; lcv++) - if ((ps->end - ps->start) > - (segs[lcv]->end - segs[lcv]->start)) + 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 = nsegs ; x > lcv ; x--) - segs[x] = segs[x - 1]; - segs[lcv] = ps; + 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 -} -#if 0 -static void -uvm_physseg_remove(struct vm_physseg **segs, struct vm_physseg *seg) -{ - struct vm_physseg **segp; + 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++; - for (segp = segs; segp < segs + VM_PHYSSEG_MAX; segp++) - if (*segp == seg) - break; - if (segp == segs + VM_PHYSSEG_MAX) - panic("unknown segment: %p", seg); - while (segp + 1 < segs + VM_PHYSSEG_MAX) { - *segp = *(segp + 1); - segp++; + if (!preload) { + uvmpdpol_reinit(); } - *segp = NULL; } -#endif /* - * vm_physseg_find: find vm_physseg structure that belongs to a PA + * when VM_PHYSSEG_MAX is 1, we can simplify these functions */ -#define VM_PHYSSEG_OP_PF 1 -#define VM_PHYSSEG_OP_PG 2 - #if VM_PHYSSEG_MAX == 1 -#define VM_PHYSSEG_FIND vm_physseg_find_contig +static inline int vm_physseg_find_contig(struct vm_physseg *, int, paddr_t, int *); #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) -#define VM_PHYSSEG_FIND vm_physseg_find_bsearch +static inline int vm_physseg_find_bsearch(struct vm_physseg *, int, paddr_t, int *); #else -#define VM_PHYSSEG_FIND vm_physseg_find_linear +static inline int vm_physseg_find_linear(struct vm_physseg *, int, paddr_t, int *); #endif -static inline int VM_PHYSSEG_FIND(struct vm_physseg **, int, int, - paddr_t, const struct vm_page *, int *); -static inline bool vm_physseg_within_p(struct vm_physseg *, int, paddr_t, - const struct vm_page *, int *); -static inline bool vm_physseg_ge_p(struct vm_physseg *, int, paddr_t, - const struct vm_page *, int *); -static inline bool vm_physseg_lt_p(struct vm_physseg *, int, paddr_t, - const struct vm_page *, int *); - +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ int vm_physseg_find(paddr_t pframe, int *offp) { - return VM_PHYSSEG_FIND(vm_physmem_ptrs, vm_nphysmem, VM_PHYSSEG_OP_PF, - pframe, NULL, 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, int op, - paddr_t pframe, const struct vm_page *pg, int *offp) +vm_physseg_find_contig(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp) { /* 'contig' case */ - if (nsegs == 0) - return(-1); - if (vm_physseg_within_p(segs[0], op, pframe, pg, offp)) { + if (pframe >= segs[0].start && pframe < segs[0].end) { + if (offp) + *offp = pframe - segs[0].start; return(0); } return(-1); @@ -993,8 +916,7 @@ #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) static inline int -vm_physseg_find_bsearch(struct vm_physseg **segs, int nsegs, int op, - paddr_t pframe, const struct vm_page *pg, int *offp) +vm_physseg_find_bsearch(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp) { /* binary search for it */ u_int start, len, try; @@ -1016,9 +938,11 @@ try = start + (len / 2); /* try in the middle */ /* start past our try? */ - if (vm_physseg_ge_p(segs[try], op, pframe, pg, offp)) { + if (pframe >= segs[try].start) { /* was try correct? */ - if (vm_physseg_lt_p(segs[try], op, pframe, pg, offp)) { + if (pframe < segs[try].end) { + if (offp) + *offp = pframe - segs[try].start; return(try); /* got it */ } start = try + 1; /* next time, start here */ @@ -1036,14 +960,16 @@ #else static inline int -vm_physseg_find_linear(struct vm_physseg **segs, int nsegs, int op, - paddr_t pframe, const struct vm_page *pg, int *offp) +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 (vm_physseg_within_p(segs[lcv], op, pframe, pg, offp)) { + if (pframe >= segs[lcv].start && + pframe < segs[lcv].end) { + if (offp) + *offp = pframe - segs[lcv].start; return(lcv); /* got it */ } } @@ -1051,49 +977,6 @@ } #endif -static inline bool -vm_physseg_within_p(struct vm_physseg *seg, int op, paddr_t pframe, - const struct vm_page *pg, int *offp) -{ - - return vm_physseg_ge_p(seg, op, pframe, pg, offp) && - vm_physseg_lt_p(seg, op, pframe, pg, offp); -} - -static inline bool -vm_physseg_ge_p(struct vm_physseg *seg, int op, paddr_t pframe, - const struct vm_page *pg, int *offp) -{ - - switch (op) { - case VM_PHYSSEG_OP_PF: - if (offp) - *offp = pframe - seg->start; - return pframe >= seg->start; - case VM_PHYSSEG_OP_PG: - if (offp) - *offp = pg - seg->pgs; - return pg >= seg->pgs; - default: - return false; - } -} - -static inline bool -vm_physseg_lt_p(struct vm_physseg *seg, int op, paddr_t pframe, - const struct vm_page *pg, int *offp) -{ - - switch (op) { - case VM_PHYSSEG_OP_PF: - return pframe < seg->end; - case VM_PHYSSEG_OP_PG: - return pg < seg->lastpg; - default: - return false; - } -} - /* * 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. Index: src/sys/uvm/uvm_page.h diff -u src/sys/uvm/uvm_page.h:1.67 src/sys/uvm/uvm_page.h:1.68 --- src/sys/uvm/uvm_page.h:1.67 Sun Nov 14 15:06:34 2010 +++ src/sys/uvm/uvm_page.h Thu Nov 25 04:45:30 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.h,v 1.67 2010/11/14 15:06:34 uebayasi Exp $ */ +/* $NetBSD: uvm_page.h,v 1.68 2010/11/25 04:45:30 uebayasi Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -238,8 +238,6 @@ int free_list; /* which free list they belong on */ struct vm_page *pgs; /* vm_page structures (from start) */ struct vm_page *lastpg; /* vm_page structure for end */ - SIMPLEQ_ENTRY(vm_physseg) list; - #ifdef __HAVE_PMAP_PHYSSEG struct pmap_physseg pmseg; /* pmap specific (MD) data */ #endif @@ -257,14 +255,12 @@ * physical memory config is stored in vm_physmem. */ -#define VM_PHYSMEM_PTR(i) (vm_physmem_ptrs[i]) -#define VM_PHYSMEM_PTR_SWAP(i, j) \ - do { VM_PHYSMEM_PTR(i) = VM_PHYSMEM_PTR(j); } while (0) - -extern struct vm_physseg *vm_physmem_ptrs[VM_PHYSSEG_MAX]; -extern int vm_nphysmem; +#define VM_PHYSMEM_PTR(i) (&vm_physmem[i]) +#define VM_PHYSMEM_PTR_SWAP(i, j) \ + do { vm_physmem[(i)] = vm_physmem[(j)]; } while (0) -#define vm_nphysseg vm_nphysmem /* XXX backward compat */ +extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; +extern int vm_nphysseg; /* * prototypes: the following prototypes define the interface to pages @@ -310,10 +306,6 @@ #define VM_PAGE_TO_PHYS(entry) uvm_vm_page_to_phys(entry) -#ifdef __HAVE_VM_PAGE_MD -#define VM_PAGE_TO_MD(pg) (&(pg)->mdpage) -#endif - /* * Compute the page color bucket for a given page. */ Index: src/sys/uvm/uvm_pglist.c diff -u src/sys/uvm/uvm_pglist.c:1.50 src/sys/uvm/uvm_pglist.c:1.51 --- src/sys/uvm/uvm_pglist.c:1.50 Thu Nov 18 11:49:41 2010 +++ src/sys/uvm/uvm_pglist.c Thu Nov 25 04:45:30 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_pglist.c,v 1.50 2010/11/18 11:49:41 cegger Exp $ */ +/* $NetBSD: uvm_pglist.c,v 1.51 2010/11/25 04:45:30 uebayasi Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.50 2010/11/18 11:49:41 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.51 2010/11/25 04:45:30 uebayasi Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -59,20 +59,6 @@ #define STAT_DECR(v) #endif -#ifdef DEBUG -static int -vm_physmem_index(struct vm_physseg *ps) -{ - int i; - - for (i = 0; i < vm_nphysmem; i++) { - if (VM_PHYSMEM_PTR(i) == ps) - return i; - } - return -1; -} -#endif - /* * uvm_pglistalloc: allocate a list of pages * @@ -147,7 +133,7 @@ #endif #ifdef PGALLOC_VERBOSE printf("pgalloc: contig %d pgs from psi %ld\n", num, - (long)(ps - VM_PHYSMEM_PTR(0))); + (long)(ps - vm_physmem)); #endif KASSERT(mutex_owned(&uvm_fpageqlock)); @@ -178,11 +164,11 @@ * Make sure this is a managed physical page. */ - if (vm_physseg_find(try, &cidx) != vm_physmem_index(ps)) + if (vm_physseg_find(try, &cidx) != ps - vm_physmem) panic("pgalloc contig: botch1"); if (cidx != try - ps->start) panic("pgalloc contig: botch2"); - if (vm_physseg_find(try + num - 1, &cidx) != vm_physmem_index(ps)) + if (vm_physseg_find(try + num - 1, &cidx) != ps - vm_physmem) panic("pgalloc contig: botch3"); if (cidx != try - ps->start + num - 1) panic("pgalloc contig: botch4"); @@ -260,12 +246,12 @@ for (fl = 0; fl < VM_NFREELIST; fl++) { #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (psi = vm_nphysmem - 1 ; psi >= 0 ; psi--) + for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--) #else - for (psi = 0 ; psi < vm_nphysmem ; psi++) + for (psi = 0 ; psi < vm_nphysseg ; psi++) #endif { - ps = VM_PHYSMEM_PTR(psi); + ps = &vm_physmem[psi]; if (ps->free_list != fl) continue; @@ -306,7 +292,7 @@ #endif #ifdef PGALLOC_VERBOSE printf("pgalloc: simple %d pgs from psi %ld\n", num, - (long)(ps - VM_PHYSMEM_PTR(0))); + (long)(ps - vm_physmem)); #endif KASSERT(mutex_owned(&uvm_fpageqlock)); @@ -317,7 +303,7 @@ for (try = max(atop(low), ps->avail_start); try < limit; try ++) { #ifdef DEBUG - if (vm_physseg_find(try, &cidx) != vm_physmem_index(ps)) + if (vm_physseg_find(try, &cidx) != ps - vm_physmem) panic("pgalloc simple: botch1"); if (cidx != (try - ps->start)) panic("pgalloc simple: botch2"); @@ -359,12 +345,12 @@ for (fl = 0; fl < VM_NFREELIST; fl++) { #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST) - for (psi = vm_nphysmem - 1 ; psi >= 0 ; psi--) + for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--) #else - for (psi = 0 ; psi < vm_nphysmem ; psi++) + for (psi = 0 ; psi < vm_nphysseg ; psi++) #endif { - ps = VM_PHYSMEM_PTR(psi); + ps = &vm_physmem[psi]; if (ps->free_list != fl) continue;