Move uvm_page-related DDB hooks into uvm_page.c.
This commit is contained in:
parent
932fb37c13
commit
21d14bd56b
@ -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_object_printit(struct uvm_object *uobj, bool full,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.150 2009/08/18 18:06:53 thorpej Exp $
|
||||
#include <sys/cpu.h>
|
||||
|
||||
#include <uvm/uvm.h>
|
||||
#include <uvm/uvm_ddb.h>
|
||||
#include <uvm/uvm_pdpolicy.h>
|
||||
|
||||
/*
|
||||
@ -1873,3 +1875,122 @@ uvm_page_lookup_freelist(struct vm_page *pg)
|
||||
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 */
|
||||
|
202
sys/uvm/uvm_page_impl.h
Normal file
202
sys/uvm/uvm_page_impl.h
Normal file
@ -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.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.
|
||||
*/
|
||||
|
||||
#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_ */
|
Loading…
Reference in New Issue
Block a user