Module Name: src Committed By: thorpej Date: Tue Aug 18 19:08:39 UTC 2009
Modified Files: src/sys/uvm: uvm_map.c uvm_page.c Added Files: src/sys/uvm: uvm_page_impl.h Log Message: Move uvm_page-related DDB hooks into uvm_page.c. To generate a diff of this commit: cvs rdiff -u -r1.278 -r1.279 src/sys/uvm/uvm_map.c cvs rdiff -u -r1.150 -r1.151 src/sys/uvm/uvm_page.c cvs rdiff -u -r0 -r1.1 src/sys/uvm/uvm_page_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_map.c diff -u src/sys/uvm/uvm_map.c:1.278 src/sys/uvm/uvm_map.c:1.279 --- src/sys/uvm/uvm_map.c:1.278 Thu Aug 13 03:21:03 2009 +++ src/sys/uvm/uvm_map.c Tue Aug 18 19:08:39 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_map.c,v 1.278 2009/08/13 03:21:03 matt Exp $ */ +/* $NetBSD: uvm_map.c,v 1.279 2009/08/18 19:08:39 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.278 2009/08/13 03:21:03 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.279 2009/08/18 19:08:39 thorpej Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -5097,122 +5097,7 @@ } } -/* - * uvm_page_printit: actually print the page - */ - -static const char page_flagbits[] = UVM_PGFLAGBITS; -static const char page_pqflagbits[] = UVM_PQFLAGBITS; - -void -uvm_page_printit(struct vm_page *pg, bool full, - void (*pr)(const char *, ...)) -{ - struct vm_page *tpg; - struct uvm_object *uobj; - struct pgflist *pgl; - char pgbuf[128]; - char pqbuf[128]; - - (*pr)("PAGE %p:\n", pg); - snprintb(pgbuf, sizeof(pgbuf), page_flagbits, pg->flags); - snprintb(pqbuf, sizeof(pqbuf), page_pqflagbits, pg->pqflags); - (*pr)(" flags=%s, pqflags=%s, wire_count=%d, pa=0x%lx\n", - pgbuf, pqbuf, pg->wire_count, (long)VM_PAGE_TO_PHYS(pg)); - (*pr)(" uobject=%p, uanon=%p, offset=0x%llx loan_count=%d\n", - pg->uobject, pg->uanon, (long long)pg->offset, pg->loan_count); -#if defined(UVM_PAGE_TRKOWN) - if (pg->flags & PG_BUSY) - (*pr)(" owning process = %d, tag=%s\n", - pg->owner, pg->owner_tag); - else - (*pr)(" page not busy, no owner\n"); -#else - (*pr)(" [page ownership tracking disabled]\n"); -#endif - - if (!full) - return; - - /* cross-verify object/anon */ - if ((pg->pqflags & PQ_FREE) == 0) { - if (pg->pqflags & PQ_ANON) { - if (pg->uanon == NULL || pg->uanon->an_page != pg) - (*pr)(" >>> ANON DOES NOT POINT HERE <<< (%p)\n", - (pg->uanon) ? pg->uanon->an_page : NULL); - else - (*pr)(" anon backpointer is OK\n"); - } else { - uobj = pg->uobject; - if (uobj) { - (*pr)(" checking object list\n"); - TAILQ_FOREACH(tpg, &uobj->memq, listq.queue) { - if (tpg == pg) { - break; - } - } - if (tpg) - (*pr)(" page found on object list\n"); - else - (*pr)(" >>> PAGE NOT FOUND ON OBJECT LIST! <<<\n"); - } - } - } - - /* cross-verify page queue */ - if (pg->pqflags & PQ_FREE) { - int fl = uvm_page_lookup_freelist(pg); - int color = VM_PGCOLOR_BUCKET(pg); - pgl = &uvm.page_free[fl].pgfl_buckets[color].pgfl_queues[ - ((pg)->flags & PG_ZERO) ? PGFL_ZEROS : PGFL_UNKNOWN]; - } else { - pgl = NULL; - } - - if (pgl) { - (*pr)(" checking pageq list\n"); - LIST_FOREACH(tpg, pgl, pageq.list) { - if (tpg == pg) { - break; - } - } - if (tpg) - (*pr)(" page found on pageq list\n"); - else - (*pr)(" >>> PAGE NOT FOUND ON PAGEQ LIST! <<<\n"); - } -} - -/* - * uvm_pages_printthem - print a summary of all managed pages - */ - -void -uvm_page_printall(void (*pr)(const char *, ...)) -{ - unsigned i; - struct vm_page *pg; - - (*pr)("%18s %4s %4s %18s %18s" -#ifdef UVM_PAGE_TRKOWN - " OWNER" -#endif - "\n", "PAGE", "FLAG", "PQ", "UOBJECT", "UANON"); - for (i = 0; i < vm_nphysseg; i++) { - for (pg = vm_physmem[i].pgs; pg <= vm_physmem[i].lastpg; pg++) { - (*pr)("%18p %04x %04x %18p %18p", - pg, pg->flags, pg->pqflags, pg->uobject, - pg->uanon); -#ifdef UVM_PAGE_TRKOWN - if (pg->flags & PG_BUSY) - (*pr)(" %d [%s]", pg->owner, pg->owner_tag); -#endif - (*pr)("\n"); - } - } -} - -#endif +#endif /* DDB || DEBUGPRINT */ /* * uvm_map_create: create map Index: src/sys/uvm/uvm_page.c diff -u src/sys/uvm/uvm_page.c:1.150 src/sys/uvm/uvm_page.c:1.151 --- src/sys/uvm/uvm_page.c:1.150 Tue Aug 18 18:06:53 2009 +++ src/sys/uvm/uvm_page.c Tue Aug 18 19:08:39 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.c,v 1.150 2009/08/18 18:06:53 thorpej Exp $ */ +/* $NetBSD: uvm_page.c,v 1.151 2009/08/18 19:08:39 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -71,8 +71,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.150 2009/08/18 18:06:53 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.151 2009/08/18 19:08:39 thorpej Exp $"); +#include "opt_ddb.h" #include "opt_uvmhist.h" #include "opt_readahead.h" @@ -87,6 +88,7 @@ #include <sys/cpu.h> #include <uvm/uvm.h> +#include <uvm/uvm_ddb.h> #include <uvm/uvm_pdpolicy.h> /* @@ -1873,3 +1875,122 @@ KASSERT(lcv != -1); return (vm_physmem[lcv].free_list); } + +#if defined(DDB) || defined(DEBUGPRINT) + +/* + * uvm_page_printit: actually print the page + */ + +static const char page_flagbits[] = UVM_PGFLAGBITS; +static const char page_pqflagbits[] = UVM_PQFLAGBITS; + +void +uvm_page_printit(struct vm_page *pg, bool full, + void (*pr)(const char *, ...)) +{ + struct vm_page *tpg; + struct uvm_object *uobj; + struct pgflist *pgl; + char pgbuf[128]; + char pqbuf[128]; + + (*pr)("PAGE %p:\n", pg); + snprintb(pgbuf, sizeof(pgbuf), page_flagbits, pg->flags); + snprintb(pqbuf, sizeof(pqbuf), page_pqflagbits, pg->pqflags); + (*pr)(" flags=%s, pqflags=%s, wire_count=%d, pa=0x%lx\n", + pgbuf, pqbuf, pg->wire_count, (long)VM_PAGE_TO_PHYS(pg)); + (*pr)(" uobject=%p, uanon=%p, offset=0x%llx loan_count=%d\n", + pg->uobject, pg->uanon, (long long)pg->offset, pg->loan_count); +#if defined(UVM_PAGE_TRKOWN) + if (pg->flags & PG_BUSY) + (*pr)(" owning process = %d, tag=%s\n", + pg->owner, pg->owner_tag); + else + (*pr)(" page not busy, no owner\n"); +#else + (*pr)(" [page ownership tracking disabled]\n"); +#endif + + if (!full) + return; + + /* cross-verify object/anon */ + if ((pg->pqflags & PQ_FREE) == 0) { + if (pg->pqflags & PQ_ANON) { + if (pg->uanon == NULL || pg->uanon->an_page != pg) + (*pr)(" >>> ANON DOES NOT POINT HERE <<< (%p)\n", + (pg->uanon) ? pg->uanon->an_page : NULL); + else + (*pr)(" anon backpointer is OK\n"); + } else { + uobj = pg->uobject; + if (uobj) { + (*pr)(" checking object list\n"); + TAILQ_FOREACH(tpg, &uobj->memq, listq.queue) { + if (tpg == pg) { + break; + } + } + if (tpg) + (*pr)(" page found on object list\n"); + else + (*pr)(" >>> PAGE NOT FOUND ON OBJECT LIST! <<<\n"); + } + } + } + + /* cross-verify page queue */ + if (pg->pqflags & PQ_FREE) { + int fl = uvm_page_lookup_freelist(pg); + int color = VM_PGCOLOR_BUCKET(pg); + pgl = &uvm.page_free[fl].pgfl_buckets[color].pgfl_queues[ + ((pg)->flags & PG_ZERO) ? PGFL_ZEROS : PGFL_UNKNOWN]; + } else { + pgl = NULL; + } + + if (pgl) { + (*pr)(" checking pageq list\n"); + LIST_FOREACH(tpg, pgl, pageq.list) { + if (tpg == pg) { + break; + } + } + if (tpg) + (*pr)(" page found on pageq list\n"); + else + (*pr)(" >>> PAGE NOT FOUND ON PAGEQ LIST! <<<\n"); + } +} + +/* + * uvm_pages_printthem - print a summary of all managed pages + */ + +void +uvm_page_printall(void (*pr)(const char *, ...)) +{ + unsigned i; + struct vm_page *pg; + + (*pr)("%18s %4s %4s %18s %18s" +#ifdef UVM_PAGE_TRKOWN + " OWNER" +#endif + "\n", "PAGE", "FLAG", "PQ", "UOBJECT", "UANON"); + for (i = 0; i < vm_nphysseg; i++) { + for (pg = vm_physmem[i].pgs; pg <= vm_physmem[i].lastpg; pg++) { + (*pr)("%18p %04x %04x %18p %18p", + pg, pg->flags, pg->pqflags, pg->uobject, + pg->uanon); +#ifdef UVM_PAGE_TRKOWN + if (pg->flags & PG_BUSY) + (*pr)(" %d [%s]", pg->owner, pg->owner_tag); +#endif + (*pr)("\n"); + } + } +} + +#endif /* DDB || DEBUGPRINT */ Added files: Index: src/sys/uvm/uvm_page_impl.h diff -u /dev/null src/sys/uvm/uvm_page_impl.h:1.1 --- /dev/null Tue Aug 18 19:08:39 2009 +++ src/sys/uvm/uvm_page_impl.h Tue Aug 18 19:08:39 2009 @@ -0,0 +1,202 @@ +/* $NetBSD: uvm_page_impl.h,v 1.1 2009/08/18 19:08:39 thorpej Exp $ */ + +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor, + * Washington University, the University of California, Berkeley and + * its contributors. + * 4. 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.distribut...@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. + */ + +#ifndef _UVM_UVM_PAGE_IMPL_H_ +#define _UVM_UVM_PAGE_IMPL_H_ + +/* + * uvm_page_impl.h + */ + +/* + * Private resident memory system definitions. + */ + +#include <uvm/uvm_page.h> + +/* + * physical memory layout structure + * + * MD vmparam.h must #define: + * VM_PHYSEG_MAX = max number of physical memory segments we support + * (if this is "1" then we revert to a "contig" case) + * VM_PHYSSEG_STRAT: memory sort/search options (for VM_PHYSEG_MAX > 1) + * - VM_PSTRAT_RANDOM: linear search (random order) + * - VM_PSTRAT_BSEARCH: binary search (sorted by address) + * - VM_PSTRAT_BIGFIRST: linear search (sorted by largest segment first) + * - others? + * XXXCDC: eventually we should purge all left-over global variables... + */ +#define VM_PSTRAT_RANDOM 1 +#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 */ + 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 */ +#ifdef __HAVE_PMAP_PHYSSEG + struct pmap_physseg pmseg; /* pmap specific (MD) data */ +#endif +}; + +#ifdef _KERNEL + +/* + * physical memory config is stored in vm_physmem. + */ + +extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; +extern int vm_nphysseg; + +/* + * when VM_PHYSSEG_MAX is 1, we can simplify these functions + */ + +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ +static __inline int +vm_physseg_find(paddr_t pframe, int *offp) +{ +#if VM_PHYSSEG_MAX == 1 + + /* 'contig' case */ + if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) { + if (offp) + *offp = pframe - vm_physmem[0].start; + return(0); + } + return(-1); + +#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) + /* binary search for it */ + u_int start, len, try; + + /* + * 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 = vm_nphysseg ; len != 0 ; len = len / 2) { + try = start + (len / 2); /* try in the middle */ + + /* start past our try? */ + if (pframe >= vm_physmem[try].start) { + /* was try correct? */ + if (pframe < vm_physmem[try].end) { + if (offp) + *offp = pframe - vm_physmem[try].start; + return(try); /* got it */ + } + start = try + 1; /* next time, start here */ + len--; /* "adjust" */ + } else { + /* + * pframe before try, just reduce length of + * region, done in "for" loop + */ + } + } + return(-1); + +#else + /* linear search for it */ + int lcv; + + for (lcv = 0; lcv < vm_nphysseg; lcv++) { + if (pframe >= vm_physmem[lcv].start && + pframe < vm_physmem[lcv].end) { + if (offp) + *offp = pframe - vm_physmem[lcv].start; + return(lcv); /* got it */ + } + } + return(-1); + +#endif +} + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_PAGE_IMPL_H_ */