Mercurial > illumos > illumos-gate
changeset 13088:e0735b974926
6973928 mdb_page_lookup() broken by 6778289; breaks ::pmap
author | Jonathan Adams <Jonathan.Adams@Sun.COM> |
---|---|
date | Wed, 11 Aug 2010 14:15:45 -0700 |
parents | 71556dfac9dc |
children | 9ff7ff6709c5 |
files | usr/src/cmd/mdb/common/mdb/mdb_param.h usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c usr/src/uts/common/sys/param.h usr/src/uts/common/vm/page.h |
diffstat | 4 files changed, 102 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/mdb/mdb_param.h Wed Aug 11 12:59:10 2010 -0700 +++ b/usr/src/cmd/mdb/common/mdb/mdb_param.h Wed Aug 11 14:15:45 2010 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _MDB_PARAM_H #define _MDB_PARAM_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -112,6 +108,8 @@ extern unsigned long _mdb_ks_msg_bsize; extern unsigned long _mdb_ks_defaultstksz; extern int _mdb_ks_ncpu; +extern int _mdb_ks_ncpu_log2; +extern int _mdb_ks_ncpu_p2; /* * Now derive all the macros using the global variables defined in @@ -134,6 +132,8 @@ #define MSG_BSIZE _mdb_ks_msg_bsize #define DEFAULTSTKSZ _mdb_ks_defaultstksz #define NCPU _mdb_ks_ncpu +#define NCPU_LOG2 _mdb_ks_ncpu_log2 +#define NCPU_P2 _mdb_ks_ncpu_p2 #define _STRING_H /* Do not re-include <string.h> */
--- a/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c Wed Aug 11 12:59:10 2010 -0700 +++ b/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c Wed Aug 11 14:15:45 2010 -0700 @@ -31,7 +31,6 @@ * to zero. */ - #include <mdb/mdb_target.h> #include <mdb/mdb_param.h> #include <mdb/mdb_modapi.h> @@ -88,6 +87,8 @@ unsigned long _mdb_ks_msg_bsize; unsigned long _mdb_ks_defaultstksz; int _mdb_ks_ncpu; +int _mdb_ks_ncpu_log2; +int _mdb_ks_ncpu_p2; /* * In-core copy of DNLC information: @@ -97,8 +98,17 @@ #define MDB_DNLC_NCACHE_SZ(ncp) (sizeof (ncache_t) + (ncp)->namlen) #define MDB_DNLC_MAX_RETRY 4 +static ncache_t **dnlc_hash; /* mdbs hash array of dnlc entries */ -static ncache_t **dnlc_hash; /* mdbs hash array of dnlc entries */ +/* + * copy of page_hash-related data + */ +static int page_hash_loaded; +static long mdb_page_hashsz; +static uint_t mdb_page_hashsz_shift; /* Needed for PAGE_HASH_FUNC */ +static uintptr_t mdb_page_hash; /* base address of page hash */ +#define page_hashsz mdb_page_hashsz +#define page_hashsz_shift mdb_page_hashsz_shift /* * This will be the location of the vnodeops pointer for "autofs_vnodeops" @@ -624,32 +634,78 @@ return (cpu); } +static int +page_hash_load(void) +{ + if (page_hash_loaded) { + return (1); + } + + if (mdb_readvar(&mdb_page_hashsz, "page_hashsz") == -1) { + mdb_warn("unable to read page_hashsz"); + return (0); + } + if (mdb_readvar(&mdb_page_hashsz_shift, "page_hashsz_shift") == -1) { + mdb_warn("unable to read page_hashsz_shift"); + return (0); + } + if (mdb_readvar(&mdb_page_hash, "page_hash") == -1) { + mdb_warn("unable to read page_hash"); + return (0); + } + + page_hash_loaded = 1; /* zeroed on state change */ + return (1); +} + uintptr_t mdb_page_lookup(uintptr_t vp, u_offset_t offset) { - long page_hashsz, ndx; - int page_hashsz_shift; /* Needed for PAGE_HASH_FUNC */ - uintptr_t page_hash, pp; + size_t ndx; + uintptr_t page_hash_entry, pp; - if (mdb_readvar(&page_hashsz, "page_hashsz") == -1 || - mdb_readvar(&page_hashsz_shift, "page_hashsz_shift") == -1 || - mdb_readvar(&page_hash, "page_hash") == -1) + if (!page_hash_loaded && !page_hash_load()) { return (NULL); + } ndx = PAGE_HASH_FUNC(vp, offset); - page_hash += ndx * sizeof (uintptr_t); + page_hash_entry = mdb_page_hash + ndx * sizeof (uintptr_t); - mdb_vread(&pp, sizeof (pp), page_hash); + if (mdb_vread(&pp, sizeof (pp), page_hash_entry) < 0) { + mdb_warn("unable to read page_hash[%ld] (%p)", ndx, + page_hash_entry); + return (NULL); + } while (pp != NULL) { page_t page; + long nndx; - mdb_vread(&page, sizeof (page), pp); + if (mdb_vread(&page, sizeof (page), pp) < 0) { + mdb_warn("unable to read page_t at %p", pp); + return (NULL); + } if ((uintptr_t)page.p_vnode == vp && (uint64_t)page.p_offset == offset) return (pp); + /* + * Double check that the pages actually hash to the + * bucket we're searching. If not, our version of + * PAGE_HASH_FUNC() doesn't match the kernel's, and we're + * not going to be able to find the page. The most + * likely reason for this that mdb_ks doesn't match the + * kernel we're running against. + */ + nndx = PAGE_HASH_FUNC(page.p_vnode, page.p_offset); + if (page.p_vnode != NULL && nndx != ndx) { + mdb_warn("mdb_page_lookup: mdb_ks PAGE_HASH_FUNC() " + "mismatch: in bucket %ld, but page %p hashes to " + "bucket %ld\n", ndx, pp, nndx); + return (NULL); + } + pp = (uintptr_t)page.p_hash; } @@ -1164,6 +1220,10 @@ (void) mdb_readvar(&_mdb_ks_msg_bsize, "_msg_bsize"); (void) mdb_readvar(&_mdb_ks_defaultstksz, "_defaultstksz"); (void) mdb_readvar(&_mdb_ks_ncpu, "_ncpu"); + (void) mdb_readvar(&_mdb_ks_ncpu_log2, "_ncpu_log2"); + (void) mdb_readvar(&_mdb_ks_ncpu_p2, "_ncpu_p2"); + + page_hash_loaded = 0; /* invalidate cached page_hash state */ } const mdb_modinfo_t *
--- a/usr/src/uts/common/sys/param.h Wed Aug 11 12:59:10 2010 -0700 +++ b/usr/src/uts/common/sys/param.h Wed Aug 11 14:15:45 2010 -0700 @@ -384,6 +384,7 @@ extern const int _clsize; #endif /* defined(_KERNEL) && !defined(_ASM) */ +/* Any additions to these #defines must be reflected in mdb_param.h+mdb_ks.c */ #define PAGESIZE _pagesize #define PAGESHIFT _pageshift #define PAGEOFFSET _pageoffset
--- a/usr/src/uts/common/vm/page.h Wed Aug 11 12:59:10 2010 -0700 +++ b/usr/src/uts/common/vm/page.h Wed Aug 11 14:15:45 2010 -0700 @@ -104,13 +104,15 @@ /* * PAGE_LLOCK_SIZE is 2 * NCPU, but no smaller than 128. * PAGE_LLOCK_SHIFT is log2(PAGE_LLOCK_SIZE). + * + * We use ? : instead of #if because <vm/page.h> is included everywhere; + * NCPU_P2 is only a constant in the "unix" module. + * */ -#if ((2*NCPU_P2) > 128) -#define PAGE_LLOCK_SHIFT ((unsigned)(NCPU_LOG2 + 1)) -#else -#define PAGE_LLOCK_SHIFT 7U -#endif -#define PAGE_LLOCK_SIZE (1 << PAGE_LLOCK_SHIFT) +#define PAGE_LLOCK_SHIFT \ + ((unsigned)(((2*NCPU_P2) > 128) ? NCPU_LOG2 + 1 : 7)) + +#define PAGE_LLOCK_SIZE (1ul << PAGE_LLOCK_SHIFT) /* * The number of low order 0 (or less variable) bits in the page_t address. @@ -573,28 +575,17 @@ * PH_SHIFT_SIZE is the amount to use for the successive shifts in the hash * function below. The actual value is LOG2(PH_TABLE_SIZE), so that as many * bits as possible will filter thru PAGE_HASH_FUNC() and PAGE_HASH_MUTEX(). + * + * We use ? : instead of #if because <vm/page.h> is included everywhere; + * NCPU maps to a global variable outside of the "unix" module. */ #if defined(_LP64) - -#if NCPU < 4 -#define PH_TABLE_SIZE 128 -#define PH_SHIFT_SIZE 7 -#else -#define PH_TABLE_SIZE (2 * NCPU_P2) -#define PH_SHIFT_SIZE (NCPU_LOG2 + 1) -#endif - +#define PH_SHIFT_SIZE ((NCPU < 4) ? 7 : (NCPU_LOG2 + 1)) #else /* 32 bits */ +#define PH_SHIFT_SIZE ((NCPU < 4) ? 4 : 7) +#endif /* _LP64 */ -#if NCPU < 4 -#define PH_TABLE_SIZE 16 -#define PH_SHIFT_SIZE 4 -#else -#define PH_TABLE_SIZE 128 -#define PH_SHIFT_SIZE 7 -#endif - -#endif /* _LP64 */ +#define PH_TABLE_SIZE (1ul << PH_SHIFT_SIZE) /* * @@ -618,13 +609,14 @@ #define PAGE_HASHAVELEN 4 #define PAGE_HASH_FUNC(vp, off) \ (((((uintptr_t)(off) >> PAGESHIFT) ^ \ - ((uintptr_t)(off) >> (PAGESHIFT + PH_SHIFT_SIZE))) ^ \ - (((uintptr_t)(vp) >> 3) ^ \ - ((uintptr_t)(vp) >> (3 + PH_SHIFT_SIZE)) ^ \ - ((uintptr_t)(vp) >> (3 + 2 * PH_SHIFT_SIZE)) ^ \ - ((uintptr_t)(vp) << \ - (page_hashsz_shift - AN_VPSHIFT - VNODE_ALIGN_LOG2)))) & \ - (PAGE_HASHSZ - 1)) + ((uintptr_t)(off) >> (PAGESHIFT + PH_SHIFT_SIZE))) ^ \ + (((uintptr_t)(vp) >> 3) ^ \ + ((uintptr_t)(vp) >> (3 + PH_SHIFT_SIZE)) ^ \ + ((uintptr_t)(vp) >> (3 + 2 * PH_SHIFT_SIZE)) ^ \ + ((uintptr_t)(vp) << \ + (page_hashsz_shift - AN_VPSHIFT - VNODE_ALIGN_LOG2)))) & \ + (PAGE_HASHSZ - 1)) + #ifdef _KERNEL /*