xref: /onnv-gate/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/machparam.h>
31*0Sstevel@tonic-gate #include <vm/as.h>
32*0Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
35*0Sstevel@tonic-gate #include <mdb/mdb_target.h>
36*0Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  * sfmmu mdb support
40*0Sstevel@tonic-gate  */
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_SYMBOL	1
43*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_VERBOSE	2
44*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_DEBUG	4
45*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_ALL	(SFMMU_VTOP_DBG_SYMBOL|SFMMU_VTOP_DBG_VERBOSE|\
46*0Sstevel@tonic-gate 				SFMMU_VTOP_DBG_DEBUG)
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_SYM	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_SYMBOL) \
49*0Sstevel@tonic-gate 				    mdb_printf
50*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_VRB	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_VERBOSE) \
51*0Sstevel@tonic-gate 				    mdb_printf
52*0Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_DBG	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_DEBUG) \
53*0Sstevel@tonic-gate 				    mdb_printf
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate #define	SFMMU_VTOP_READSYM(dest, synm, where) \
56*0Sstevel@tonic-gate 	if (mdb_readsym(&(dest), sizeof (dest), (synm)) == -1) \
57*0Sstevel@tonic-gate 		mdb_warn("%s: couldn't find or read '%s'\n", (where), (synm));
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate struct hme_blks_max {
60*0Sstevel@tonic-gate 	struct hme_blk	hmx_hmeblk;
61*0Sstevel@tonic-gate 	struct sf_hment	hmx_hmes[NHMENTS - 1];
62*0Sstevel@tonic-gate };
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate int sfmmu_vtop(uintptr_t, uint_t, int, const mdb_arg_t *);
65*0Sstevel@tonic-gate static int sfmmu_vtop_common(struct as *, uintptr_t, physaddr_t *);
66*0Sstevel@tonic-gate static int sfmmu_vtop_impl(uintptr_t, sfmmu_t *, sfmmu_t *, physaddr_t *);
67*0Sstevel@tonic-gate static void sfmmu_vtop_print_hmeblk(struct hme_blk *);
68*0Sstevel@tonic-gate static struct sf_hment *mdb_sfmmu_hblktohme(struct hme_blk *, caddr_t, int *);
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate int sfmmu_vtop_dbg_wanted = 0;	/* set this as desired */
71*0Sstevel@tonic-gate int sfmmu_vtop_dbg = 0;
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /*
74*0Sstevel@tonic-gate  * ::sfmmu_vtop [[-v] -a as]
75*0Sstevel@tonic-gate  * Extended version of the vtop builtin. The optional <as> argument is
76*0Sstevel@tonic-gate  * used as base address space for translating a virtual address into a
77*0Sstevel@tonic-gate  * physical address. The verbose option ("-v") shows intermediate
78*0Sstevel@tonic-gate  * translation steps. If <as> or kas is ommitted, the builtin ::vtop
79*0Sstevel@tonic-gate  * dcmd is called.
80*0Sstevel@tonic-gate  */
81*0Sstevel@tonic-gate int
82*0Sstevel@tonic-gate sfmmu_vtop(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
83*0Sstevel@tonic-gate {
84*0Sstevel@tonic-gate 	int ret;
85*0Sstevel@tonic-gate 	struct as *asp = NULL;
86*0Sstevel@tonic-gate 	char *asnmp = NULL;
87*0Sstevel@tonic-gate 	int verbose = 0;
88*0Sstevel@tonic-gate 	physaddr_t paddr;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	sfmmu_vtop_dbg = sfmmu_vtop_dbg_wanted;
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
93*0Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
94*0Sstevel@tonic-gate 	    'a', MDB_OPT_STR, &asnmp,
95*0Sstevel@tonic-gate 	    NULL) != argc)
96*0Sstevel@tonic-gate 		return (DCMD_USAGE);
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	if (verbose != 0 && asnmp == NULL) {
99*0Sstevel@tonic-gate 		mdb_warn("-v requires -a option\n");
100*0Sstevel@tonic-gate 		return (DCMD_USAGE);
101*0Sstevel@tonic-gate 	}
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 	if (verbose != 0 && (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_VERBOSE) == 0) {
104*0Sstevel@tonic-gate 		sfmmu_vtop_dbg |= SFMMU_VTOP_DBG_VERBOSE;
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	if (asnmp != NULL) {
108*0Sstevel@tonic-gate 		GElf_Sym sym;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("asnmp=%p asnm=%s\n", asnmp, asnmp);
111*0Sstevel@tonic-gate 		if (strcmp(asnmp, "kas") == 0) {
112*0Sstevel@tonic-gate 			if (mdb_lookup_by_name("kas", &sym) == -1) {
113*0Sstevel@tonic-gate 				mdb_warn("couldn't find 'kas'\n");
114*0Sstevel@tonic-gate 				return (DCMD_ERR);
115*0Sstevel@tonic-gate 			} else {
116*0Sstevel@tonic-gate 				asp = (struct as *)sym.st_value;
117*0Sstevel@tonic-gate 				SFMMU_VTOP_DBG_SYM("kas &sym=%p\n", &sym);
118*0Sstevel@tonic-gate 			}
119*0Sstevel@tonic-gate 		} else {
120*0Sstevel@tonic-gate 			asp = (struct as *)mdb_strtoull(asnmp);
121*0Sstevel@tonic-gate 		}
122*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("asp=0x%p\n", asp);
123*0Sstevel@tonic-gate 	}
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	if (asp == 0) {
126*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("sfmmu_vtop: call standard vtop\n");
127*0Sstevel@tonic-gate 		return (mdb_call_dcmd("vtop", addr, flags, argc, argv));
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	if ((ret = sfmmu_vtop_common(asp, addr, &paddr)) == -1L) {
131*0Sstevel@tonic-gate 		mdb_printf("no mapping found for addr=%p\n", addr);
132*0Sstevel@tonic-gate 		return (DCMD_ERR);
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	if (ret == 0) {
136*0Sstevel@tonic-gate 		mdb_printf("address space %p: virtual %lr mapped to physical "
137*0Sstevel@tonic-gate 			"%llr", asp, addr, paddr);
138*0Sstevel@tonic-gate 	} else {
139*0Sstevel@tonic-gate 		return (DCMD_ERR);
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	return (DCMD_OK);
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate static int
146*0Sstevel@tonic-gate sfmmu_vtop_common(struct as *asp, uintptr_t addr, physaddr_t *pap)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate 	struct as mas;
149*0Sstevel@tonic-gate 	struct as *masp = &mas;
150*0Sstevel@tonic-gate 	sfmmu_t *hatp;
151*0Sstevel@tonic-gate 	sfmmu_t mhat;
152*0Sstevel@tonic-gate 	sfmmu_t *mhatp = &mhat;
153*0Sstevel@tonic-gate 	int ret;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	if (mdb_vread(masp, sizeof (mas), (uintptr_t)asp) == -1) {
156*0Sstevel@tonic-gate 		mdb_warn("couldn't read as at %p\n", asp);
157*0Sstevel@tonic-gate 		return (DCMD_ERR);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	hatp = masp->a_hat;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("hatp=%p addr=%p masp=%p\n", hatp, addr, masp);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	if (mdb_vread(mhatp, sizeof (mhat), (uintptr_t)hatp) == -1) {
165*0Sstevel@tonic-gate 		mdb_warn("couldn't read hat at %p\n", hatp);
166*0Sstevel@tonic-gate 		return (DCMD_ERR);
167*0Sstevel@tonic-gate 	}
168*0Sstevel@tonic-gate 	if (mhatp->sfmmu_as != asp) {
169*0Sstevel@tonic-gate 		mdb_warn("%p is not a valid address space\n", asp);
170*0Sstevel@tonic-gate 		return (DCMD_ERR);
171*0Sstevel@tonic-gate 	}
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	ret = sfmmu_vtop_impl(addr, hatp, mhatp, pap);
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	return (ret);
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate static int
179*0Sstevel@tonic-gate sfmmu_vtop_impl(uintptr_t addr, sfmmu_t *sfmmup, sfmmu_t *msfmmup,
180*0Sstevel@tonic-gate 	    physaddr_t *pap)
181*0Sstevel@tonic-gate {
182*0Sstevel@tonic-gate 	struct hmehash_bucket *uhme_hash;
183*0Sstevel@tonic-gate 	struct hmehash_bucket *khme_hash;
184*0Sstevel@tonic-gate 	int uhmehash_num;
185*0Sstevel@tonic-gate 	int khmehash_num;
186*0Sstevel@tonic-gate 	sfmmu_t *ksfmmup;
187*0Sstevel@tonic-gate 	struct hmehash_bucket mbucket;
188*0Sstevel@tonic-gate 	struct hmehash_bucket *hmebp;
189*0Sstevel@tonic-gate 	struct hmehash_bucket *shmebp;
190*0Sstevel@tonic-gate 	hmeblk_tag hblktag;
191*0Sstevel@tonic-gate 	int hmeshift;
192*0Sstevel@tonic-gate 	int hashno = 1;
193*0Sstevel@tonic-gate 	struct hme_blk *hmeblkp = NULL;
194*0Sstevel@tonic-gate 	struct hme_blks_max mhmeblkmax;
195*0Sstevel@tonic-gate 	intptr_t thmeblkp;
196*0Sstevel@tonic-gate 	struct sf_hment *sfhmep;
197*0Sstevel@tonic-gate 	int i;
198*0Sstevel@tonic-gate 	ism_blk_t mism_blk;
199*0Sstevel@tonic-gate 	ism_map_t *ism_map;
200*0Sstevel@tonic-gate 	ism_blk_t *ism_blkp;
201*0Sstevel@tonic-gate 	ism_blk_t *sism_blkp;
202*0Sstevel@tonic-gate 	sfmmu_t *ism_hatid = NULL;
203*0Sstevel@tonic-gate 	int sfhmeinx = 0;
204*0Sstevel@tonic-gate 	tte_t tte;
205*0Sstevel@tonic-gate 	pfn_t pfn;
206*0Sstevel@tonic-gate 	pfn_t start_pfn;
207*0Sstevel@tonic-gate 	page_t *pp;
208*0Sstevel@tonic-gate 	int ret = -1;
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(uhme_hash, "uhme_hash", "sfmmu_vtop_impl");
211*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("uhme_hash=%p\t", uhme_hash);
212*0Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(uhmehash_num, "uhmehash_num", "sfmmu_vtop_impl");
213*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("uhmehash_num=%lx\n", uhmehash_num);
214*0Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(khme_hash, "khme_hash", "sfmmu_vtop_impl");
215*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("khme_hash=%p\t", khme_hash);
216*0Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(khmehash_num, "khmehash_num", "sfmmu_vtop_impl");
217*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("khmehash_num=%lx\n", khmehash_num);
218*0Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(ksfmmup, "ksfmmup", "sfmmu_vtop_impl");
219*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("ksfmmup=%p\n", ksfmmup);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	ism_blkp = sism_blkp = msfmmup->sfmmu_iblk;
222*0Sstevel@tonic-gate 	while (ism_blkp != NULL && ism_hatid == NULL) {
223*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("ism_blkp=%p\n", ism_blkp);
224*0Sstevel@tonic-gate 		if (mdb_vread(&mism_blk, sizeof (mism_blk),
225*0Sstevel@tonic-gate 		    (uintptr_t)ism_blkp) == -1) {
226*0Sstevel@tonic-gate 			mdb_warn("couldn't read ism_blk at %p\n", ism_blkp);
227*0Sstevel@tonic-gate 			return (DCMD_ERR);
228*0Sstevel@tonic-gate 		}
229*0Sstevel@tonic-gate 		ism_blkp = &mism_blk;
230*0Sstevel@tonic-gate 		ism_map = ism_blkp->iblk_maps;
231*0Sstevel@tonic-gate 		for (i = 0; ism_map[i].imap_ismhat && i < ISM_MAP_SLOTS; i++) {
232*0Sstevel@tonic-gate 			if ((caddr_t)addr >= ism_start(ism_map[i]) &&
233*0Sstevel@tonic-gate 			    (caddr_t)addr < ism_end(ism_map[i])) {
234*0Sstevel@tonic-gate 				sfmmup = ism_hatid = ism_map[i].imap_ismhat;
235*0Sstevel@tonic-gate 				addr = (caddr_t)addr - ism_start(ism_map[i]);
236*0Sstevel@tonic-gate 				SFMMU_VTOP_DBG_VRB("ism_blkp=%p inx=%d\n",
237*0Sstevel@tonic-gate 				    sism_blkp, i);
238*0Sstevel@tonic-gate 				SFMMU_VTOP_DBG_DBG("ism map=%p ism hat=%p "
239*0Sstevel@tonic-gate 				    "addr=%llx\n",
240*0Sstevel@tonic-gate 				    (caddr_t)&ism_map[i] - (caddr_t)ism_blkp
241*0Sstevel@tonic-gate 				    + (caddr_t)sism_blkp, sfmmup, addr);
242*0Sstevel@tonic-gate 				break;
243*0Sstevel@tonic-gate 			}
244*0Sstevel@tonic-gate 		}
245*0Sstevel@tonic-gate 		ism_blkp = sism_blkp = ism_blkp->iblk_next;
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 	hblktag.htag_id = sfmmup;
249*0Sstevel@tonic-gate 	do {
250*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("-hashno=%d-\n", hashno);
251*0Sstevel@tonic-gate 		hmeshift = HME_HASH_SHIFT(hashno);
252*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hmeshift=%d\n", hmeshift);
253*0Sstevel@tonic-gate 		hblktag.htag_bspage = HME_HASH_BSPAGE(addr, hmeshift);
254*0Sstevel@tonic-gate 		hblktag.htag_rehash = hashno;
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate #ifdef __sparcv9
257*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hblktag=%lx %lx\n",
258*0Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag[0],
259*0Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag[1]);
260*0Sstevel@tonic-gate #else
261*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hblktag=%llx\n",
262*0Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag);
263*0Sstevel@tonic-gate #endif
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 		hmebp = shmebp = HME_HASH_FUNCTION(sfmmup, addr, hmeshift);
266*0Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hmebp=%p\n", hmebp);
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 		if (mdb_vread(&mbucket, sizeof (mbucket),
269*0Sstevel@tonic-gate 				(uintptr_t)hmebp) == -1) {
270*0Sstevel@tonic-gate 			mdb_warn("couldn't read mbucket at %p\n", hmebp);
271*0Sstevel@tonic-gate 			return (DCMD_ERR);
272*0Sstevel@tonic-gate 		}
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 		hmebp = &mbucket;
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		for (hmeblkp = hmebp->hmeblkp; hmeblkp;
277*0Sstevel@tonic-gate 			hmeblkp = hmeblkp->hblk_next) {
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 			SFMMU_VTOP_DBG_DBG("hmeblkp=%p\n", hmeblkp);
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 			if (hmeblkp == NULL)
282*0Sstevel@tonic-gate 				break;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 			if (mdb_vread(&mhmeblkmax, sizeof (struct hme_blk),
285*0Sstevel@tonic-gate 					(uintptr_t)hmeblkp) == -1) {
286*0Sstevel@tonic-gate 				mdb_warn("couldn't read hme_blk at %p\n",
287*0Sstevel@tonic-gate 					hmeblkp);
288*0Sstevel@tonic-gate 				return (DCMD_ERR);
289*0Sstevel@tonic-gate 			}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 			thmeblkp = (uintptr_t)hmeblkp;
292*0Sstevel@tonic-gate 			hmeblkp = &mhmeblkmax.hmx_hmeblk;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 			if (HTAGS_EQ(hmeblkp->hblk_tag, hblktag)) {
295*0Sstevel@tonic-gate 				/* found hme_blk */
296*0Sstevel@tonic-gate 				break;
297*0Sstevel@tonic-gate 			}
298*0Sstevel@tonic-gate 		}
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 		if (hmeblkp != NULL) {
301*0Sstevel@tonic-gate 			sfmmu_vtop_print_hmeblk(hmeblkp);
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 			sfhmep = mdb_sfmmu_hblktohme(hmeblkp, (caddr_t)addr,
304*0Sstevel@tonic-gate 					&sfhmeinx);
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 			SFMMU_VTOP_DBG_DBG("sfhmeinx=%d ", sfhmeinx);
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate 			if (sfhmeinx > 0) {
309*0Sstevel@tonic-gate 				thmeblkp += sizeof (struct hme_blk) +
310*0Sstevel@tonic-gate 				    sizeof (struct sf_hment) * (sfhmeinx - 1);
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 				if (mdb_vread(sfhmep, sizeof (struct sf_hment),
313*0Sstevel@tonic-gate 						thmeblkp) == -1) {
314*0Sstevel@tonic-gate 					mdb_warn("couldn't read msfhme at %p\n",
315*0Sstevel@tonic-gate 						sfhmep);
316*0Sstevel@tonic-gate 					return (DCMD_ERR);
317*0Sstevel@tonic-gate 				}
318*0Sstevel@tonic-gate 			}
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 			SFMMU_VTOP_DBG_VRB("sfmmup=%p hmebp=%p hmeblkp=%p\n",
321*0Sstevel@tonic-gate 					sfmmup, shmebp, thmeblkp);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 			tte = sfhmep->hme_tte;
324*0Sstevel@tonic-gate 			SFMMU_VTOP_DBG_VRB("tte=%llx ", tte.ll);
325*0Sstevel@tonic-gate 			if (TTE_IS_VALID(&tte)) {
326*0Sstevel@tonic-gate 				start_pfn = TTE_TO_TTEPFN(&tte);
327*0Sstevel@tonic-gate 				*pap = (start_pfn << MMU_PAGESHIFT) +
328*0Sstevel@tonic-gate 					(addr & TTE_PAGE_OFFSET(tte.tte_size));
329*0Sstevel@tonic-gate 				pfn = *pap >> MMU_PAGESHIFT;
330*0Sstevel@tonic-gate 				pp = (sfhmep->hme_page != 0) ?
331*0Sstevel@tonic-gate 					sfhmep->hme_page + (pfn - start_pfn) :
332*0Sstevel@tonic-gate 					0;
333*0Sstevel@tonic-gate 				SFMMU_VTOP_DBG_VRB("pfn=%lx pp=%p\n",
334*0Sstevel@tonic-gate 					pfn, pp);
335*0Sstevel@tonic-gate 				ret = 0;
336*0Sstevel@tonic-gate 			}
337*0Sstevel@tonic-gate 			break;
338*0Sstevel@tonic-gate 		}
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 		hashno++;
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	} while (HME_REHASH(msfmmup) && (hashno <= MAX_HASHCNT));
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	return (ret);
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate static void
348*0Sstevel@tonic-gate sfmmu_vtop_print_hmeblk(struct hme_blk *hmeblkp)
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 	if ((sfmmu_vtop_dbg & SFMMU_VTOP_DBG_DEBUG) == NULL)
352*0Sstevel@tonic-gate 		return;
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 	mdb_printf("    hblk_nextpa=%llx\n", hmeblkp->hblk_nextpa);
355*0Sstevel@tonic-gate #ifdef __sparcv9
356*0Sstevel@tonic-gate 	mdb_printf("    hblktag=%lx %lx\n", hmeblkp->hblk_tag.htag_tag[0],
357*0Sstevel@tonic-gate 			hmeblkp->hblk_tag.htag_tag[1]);
358*0Sstevel@tonic-gate #else
359*0Sstevel@tonic-gate 	mdb_printf("    hblktag=%llx\n", hmeblkp->hblk_tag.htag_tag);
360*0Sstevel@tonic-gate #endif
361*0Sstevel@tonic-gate 	mdb_printf("    hblk_next=%p\n", hmeblkp->hblk_next);
362*0Sstevel@tonic-gate 	mdb_printf("    hblk_shadow=%p\n", hmeblkp->hblk_shadow);
363*0Sstevel@tonic-gate 	mdb_printf("    hblk_span=%d\n", hmeblkp->hblk_span);
364*0Sstevel@tonic-gate 	mdb_printf("    hblk_ttesz=%d\n", hmeblkp->hblk_ttesz);
365*0Sstevel@tonic-gate 	if (hmeblkp->hblk_shw_bit == 0) {
366*0Sstevel@tonic-gate 		mdb_printf("    hblk_hmecnt=%d\n", hmeblkp->hblk_hmecnt);
367*0Sstevel@tonic-gate 		mdb_printf("    hblk_vcnt=%d\n", hmeblkp->hblk_vcnt);
368*0Sstevel@tonic-gate 	} else {
369*0Sstevel@tonic-gate 		mdb_printf("    hblk_shw_mask=%x\n", hmeblkp->hblk_shw_mask);
370*0Sstevel@tonic-gate 	}
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate static struct sf_hment *
374*0Sstevel@tonic-gate mdb_sfmmu_hblktohme(struct hme_blk *hmeblkp, caddr_t addr, int *hmenump)
375*0Sstevel@tonic-gate {
376*0Sstevel@tonic-gate 	int index = 0;
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	if (get_hblk_ttesz(hmeblkp) == TTE8K) {
379*0Sstevel@tonic-gate 		index = (((uintptr_t)addr >> MMU_PAGESHIFT) & (NHMENTS-1));
380*0Sstevel@tonic-gate 	}
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 	if (hmenump) {
383*0Sstevel@tonic-gate 		*hmenump = index;
384*0Sstevel@tonic-gate 	}
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	return (&hmeblkp->hblk_hme[index]);
387*0Sstevel@tonic-gate }
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate /*
390*0Sstevel@tonic-gate  * memseg walker based callback function: used internal and for ::page_num2pp
391*0Sstevel@tonic-gate  */
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate struct pfn2pp {
394*0Sstevel@tonic-gate 	pfn_t pfn;
395*0Sstevel@tonic-gate 	page_t *pp;
396*0Sstevel@tonic-gate };
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate /*ARGSUSED*/
399*0Sstevel@tonic-gate int
400*0Sstevel@tonic-gate page_num2pp_cb(uintptr_t addr, void *ignored, uintptr_t *data)
401*0Sstevel@tonic-gate {
402*0Sstevel@tonic-gate 	struct memseg ms, *msp = &ms;
403*0Sstevel@tonic-gate 	struct pfn2pp *p = (struct pfn2pp *)data;
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	if (mdb_vread(msp, sizeof (struct memseg), addr) == -1) {
406*0Sstevel@tonic-gate 		mdb_warn("can't read memseg at %#lx", addr);
407*0Sstevel@tonic-gate 		return (DCMD_ERR);
408*0Sstevel@tonic-gate 	}
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	if (p->pfn >= msp->pages_base && p->pfn < msp->pages_end) {
411*0Sstevel@tonic-gate 		p->pp = msp->pages + (p->pfn - msp->pages_base);
412*0Sstevel@tonic-gate 		return (WALK_DONE);
413*0Sstevel@tonic-gate 	}
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 	return (WALK_NEXT);
416*0Sstevel@tonic-gate }
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate /*
419*0Sstevel@tonic-gate  * ::page_num2pp dcmd
420*0Sstevel@tonic-gate  */
421*0Sstevel@tonic-gate /*ARGSUSED*/
422*0Sstevel@tonic-gate int
423*0Sstevel@tonic-gate page_num2pp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
424*0Sstevel@tonic-gate {
425*0Sstevel@tonic-gate 	struct pfn2pp pfn2pp;
426*0Sstevel@tonic-gate 	page_t page;
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
429*0Sstevel@tonic-gate 		mdb_warn("page frame number missing\n");
430*0Sstevel@tonic-gate 			return (DCMD_USAGE);
431*0Sstevel@tonic-gate 	}
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 	pfn2pp.pfn = (pfn_t)addr;
434*0Sstevel@tonic-gate 	pfn2pp.pp = NULL;
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 	if (mdb_walk("memseg", (mdb_walk_cb_t)page_num2pp_cb,
437*0Sstevel@tonic-gate 	    (void *)&pfn2pp) == -1) {
438*0Sstevel@tonic-gate 		mdb_warn("can't walk memseg");
439*0Sstevel@tonic-gate 		return (DCMD_ERR);
440*0Sstevel@tonic-gate 	}
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	if (pfn2pp.pp == NULL)
443*0Sstevel@tonic-gate 		return (DCMD_ERR);
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	mdb_printf("%lx has mpage at %p\n", pfn2pp.pfn, pfn2pp.pp);
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	if (mdb_vread(&page, sizeof (page_t),
448*0Sstevel@tonic-gate 	    (uintptr_t)pfn2pp.pp) == -1) {
449*0Sstevel@tonic-gate 		mdb_warn("can't read page at %p", &page);
450*0Sstevel@tonic-gate 		return (DCMD_ERR);
451*0Sstevel@tonic-gate 	}
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 	if (page.p_pagenum != pfn2pp.pfn) {
454*0Sstevel@tonic-gate 		mdb_warn("WARNING! Found page structure contains "
455*0Sstevel@tonic-gate 			"different pagenumber %x\n", page.p_pagenum);
456*0Sstevel@tonic-gate 	}
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 	return (DCMD_OK);
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate /*
462*0Sstevel@tonic-gate  * ::memseg_list dcmd
463*0Sstevel@tonic-gate  */
464*0Sstevel@tonic-gate /*ARGSUSED*/
465*0Sstevel@tonic-gate int
466*0Sstevel@tonic-gate memseg_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
467*0Sstevel@tonic-gate {
468*0Sstevel@tonic-gate 	struct memseg ms;
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
471*0Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("memseg", "memseg_list",
472*0Sstevel@tonic-gate 		    0, NULL, 0) == -1) {
473*0Sstevel@tonic-gate 			mdb_warn("can't walk memseg");
474*0Sstevel@tonic-gate 			return (DCMD_ERR);
475*0Sstevel@tonic-gate 		}
476*0Sstevel@tonic-gate 		return (DCMD_OK);
477*0Sstevel@tonic-gate 	}
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
480*0Sstevel@tonic-gate 		mdb_printf("%<u>%?s %?s %?s %?s %?s%</u>\n", "ADDR",
481*0Sstevel@tonic-gate 			"PAGES", "EPAGES", "BASE", "END");
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate 	if (mdb_vread(&ms, sizeof (struct memseg), addr) == -1) {
484*0Sstevel@tonic-gate 		mdb_warn("can't read memseg at %#lx", addr);
485*0Sstevel@tonic-gate 		return (DCMD_ERR);
486*0Sstevel@tonic-gate 	}
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	mdb_printf("%0?lx %0?lx %0?lx %0?lx %0?lx\n", addr,
489*0Sstevel@tonic-gate 		ms.pages, ms.epages, ms.pages_base, ms.pages_end);
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate 	return (DCMD_OK);
492*0Sstevel@tonic-gate }
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate /*
495*0Sstevel@tonic-gate  * walk the memseg structures
496*0Sstevel@tonic-gate  */
497*0Sstevel@tonic-gate int
498*0Sstevel@tonic-gate memseg_walk_init(mdb_walk_state_t *wsp)
499*0Sstevel@tonic-gate {
500*0Sstevel@tonic-gate 	if (wsp->walk_addr != NULL) {
501*0Sstevel@tonic-gate 		mdb_warn("memseg only supports global walks\n");
502*0Sstevel@tonic-gate 		return (WALK_ERR);
503*0Sstevel@tonic-gate 	}
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 	if (mdb_readvar(&wsp->walk_addr, "memsegs") == -1) {
506*0Sstevel@tonic-gate 		mdb_warn("symbol 'memsegs' not found");
507*0Sstevel@tonic-gate 		return (WALK_ERR);
508*0Sstevel@tonic-gate 	}
509*0Sstevel@tonic-gate 
510*0Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (struct memseg), UM_SLEEP);
511*0Sstevel@tonic-gate 	return (WALK_NEXT);
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate }
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate int
516*0Sstevel@tonic-gate memseg_walk_step(mdb_walk_state_t *wsp)
517*0Sstevel@tonic-gate {
518*0Sstevel@tonic-gate 	int status;
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	if (wsp->walk_addr == 0) {
521*0Sstevel@tonic-gate 		return (WALK_DONE);
522*0Sstevel@tonic-gate 	}
523*0Sstevel@tonic-gate 
524*0Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (struct memseg),
525*0Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
526*0Sstevel@tonic-gate 		mdb_warn("failed to read struct memseg at %p", wsp->walk_addr);
527*0Sstevel@tonic-gate 		return (WALK_DONE);
528*0Sstevel@tonic-gate 	}
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
531*0Sstevel@tonic-gate 	    wsp->walk_cbdata);
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((struct memseg *)wsp->walk_data)->next);
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 	return (status);
536*0Sstevel@tonic-gate }
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate void
539*0Sstevel@tonic-gate memseg_walk_fini(mdb_walk_state_t *wsp)
540*0Sstevel@tonic-gate {
541*0Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (struct memseg));
542*0Sstevel@tonic-gate }
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate int
545*0Sstevel@tonic-gate platform_vtop(uintptr_t addr, struct as *asp, physaddr_t *pap)
546*0Sstevel@tonic-gate {
547*0Sstevel@tonic-gate 	int rv;
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 	sfmmu_vtop_dbg = sfmmu_vtop_dbg_wanted;
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("platform_vtop: called.\n");
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate 	if (asp == NULL) {
554*0Sstevel@tonic-gate 		return (DCMD_ERR);
555*0Sstevel@tonic-gate 	}
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 	if ((rv = sfmmu_vtop_common(asp, addr, pap)) == 0) {
558*0Sstevel@tonic-gate 		mdb_printf("address space %p: ", asp);
559*0Sstevel@tonic-gate 	}
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 	return (rv);
562*0Sstevel@tonic-gate }
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate /*
565*0Sstevel@tonic-gate  * ::tsbinfo help
566*0Sstevel@tonic-gate  */
567*0Sstevel@tonic-gate void
568*0Sstevel@tonic-gate tsbinfo_help(void)
569*0Sstevel@tonic-gate {
570*0Sstevel@tonic-gate 	mdb_printf("-l\tlist valid TSB entries.\n"
571*0Sstevel@tonic-gate 	    "-a\tlist all TSB entries.  Can only be used with -l.\n");
572*0Sstevel@tonic-gate }
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate /*
575*0Sstevel@tonic-gate  * ::tsbinfo dcmd
576*0Sstevel@tonic-gate  */
577*0Sstevel@tonic-gate int
578*0Sstevel@tonic-gate tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
579*0Sstevel@tonic-gate {
580*0Sstevel@tonic-gate 	uint_t lflag = 0, aflag = 0;
581*0Sstevel@tonic-gate 	struct tsb_info tsbinfo;
582*0Sstevel@tonic-gate 	unsigned int entries = 0;
583*0Sstevel@tonic-gate 	struct tsbe *tsbp, *tsbend, *tsbstart;
584*0Sstevel@tonic-gate 	caddr_t va;
585*0Sstevel@tonic-gate 	uintptr_t pa;
586*0Sstevel@tonic-gate 	uint_t tsbbytes;
587*0Sstevel@tonic-gate 	char tsbsize[16];
588*0Sstevel@tonic-gate #define	FLAGS_SIZE	sizeof ("RELOC,FLUSH,SWAPPED")
589*0Sstevel@tonic-gate 	char tsbflags[FLAGS_SIZE + 1];
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 	static const mdb_bitmask_t ttesz_mask_bits[] = {
592*0Sstevel@tonic-gate 		{ "8K", TSB8K, TSB8K },
593*0Sstevel@tonic-gate 		{ "64K", TSB64K, TSB64K },
594*0Sstevel@tonic-gate 		{ "512K", TSB512K, TSB512K },
595*0Sstevel@tonic-gate 		{ "4M", TSB4M, TSB4M },
596*0Sstevel@tonic-gate 		{ NULL, 0, 0 }
597*0Sstevel@tonic-gate 	};
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate 	static const mdb_bitmask_t flags_bits[] = {
600*0Sstevel@tonic-gate 		{ "RELOC", TSB_RELOC_FLAG, TSB_RELOC_FLAG },
601*0Sstevel@tonic-gate 		{ "FLUSH", TSB_FLUSH_NEEDED, TSB_FLUSH_NEEDED },
602*0Sstevel@tonic-gate 		{ "SWAPPED", TSB_SWAPPED, TSB_SWAPPED },
603*0Sstevel@tonic-gate 		{ NULL, 0, 0 }
604*0Sstevel@tonic-gate 	};
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
607*0Sstevel@tonic-gate 		return (DCMD_USAGE);
608*0Sstevel@tonic-gate 	}
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
611*0Sstevel@tonic-gate 		'l', MDB_OPT_SETBITS, TRUE, &lflag,
612*0Sstevel@tonic-gate 		'a', MDB_OPT_SETBITS, TRUE, &aflag,
613*0Sstevel@tonic-gate 		NULL) != argc) {
614*0Sstevel@tonic-gate 		return (DCMD_USAGE);
615*0Sstevel@tonic-gate 	}
616*0Sstevel@tonic-gate 
617*0Sstevel@tonic-gate 	/* -a only valid with -l */
618*0Sstevel@tonic-gate 	if (aflag && !lflag) {
619*0Sstevel@tonic-gate 		return (DCMD_USAGE);
620*0Sstevel@tonic-gate 	}
621*0Sstevel@tonic-gate 
622*0Sstevel@tonic-gate 	/* Print header? */
623*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) || lflag) {
624*0Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-?s %-8s %-*s %s%</u>\n", "TSBINFO",
625*0Sstevel@tonic-gate 		    "TSB", "SIZE", FLAGS_SIZE, "FLAGS", "TTE SIZES");
626*0Sstevel@tonic-gate 	}
627*0Sstevel@tonic-gate 
628*0Sstevel@tonic-gate 	if (mdb_vread(&tsbinfo, sizeof (struct tsb_info), addr) == -1) {
629*0Sstevel@tonic-gate 		mdb_warn("failed to read struct tsb_info at %p", addr);
630*0Sstevel@tonic-gate 		return (DCMD_ERR);
631*0Sstevel@tonic-gate 	}
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate 	mdb_printf("%0?lx ", addr);
634*0Sstevel@tonic-gate 
635*0Sstevel@tonic-gate 	/* Print a "-" if the TSB is swapped out. */
636*0Sstevel@tonic-gate 	if ((tsbinfo.tsb_flags & TSB_SWAPPED) == 0) {
637*0Sstevel@tonic-gate 		mdb_printf("%0?lx ", tsbinfo.tsb_va);
638*0Sstevel@tonic-gate 	} else {
639*0Sstevel@tonic-gate 		mdb_printf("%0?-s ", "-");
640*0Sstevel@tonic-gate 	}
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 	tsbbytes = TSB_BYTES(tsbinfo.tsb_szc);
643*0Sstevel@tonic-gate 
644*0Sstevel@tonic-gate #define	KB 1024
645*0Sstevel@tonic-gate #define	MB (KB*KB)
646*0Sstevel@tonic-gate 	if (tsbbytes >= MB) {
647*0Sstevel@tonic-gate 		mdb_snprintf(tsbsize, sizeof (tsbsize), "%dM", tsbbytes / MB);
648*0Sstevel@tonic-gate 	} else {
649*0Sstevel@tonic-gate 		mdb_snprintf(tsbsize, sizeof (tsbsize), "%dK", tsbbytes / KB);
650*0Sstevel@tonic-gate 	}
651*0Sstevel@tonic-gate #undef MB
652*0Sstevel@tonic-gate #undef KB
653*0Sstevel@tonic-gate 	mdb_printf("%-8s ", tsbsize);
654*0Sstevel@tonic-gate 
655*0Sstevel@tonic-gate 	if (tsbinfo.tsb_flags == 0) {
656*0Sstevel@tonic-gate 		mdb_printf("%-*s ", FLAGS_SIZE, "-");
657*0Sstevel@tonic-gate 	} else {
658*0Sstevel@tonic-gate 		mdb_snprintf(tsbflags, sizeof (tsbflags), "%b",
659*0Sstevel@tonic-gate 		    tsbinfo.tsb_flags, flags_bits);
660*0Sstevel@tonic-gate 		mdb_printf("%-*s ", FLAGS_SIZE, tsbflags);
661*0Sstevel@tonic-gate 	}
662*0Sstevel@tonic-gate 
663*0Sstevel@tonic-gate 	mdb_printf("%b\n", tsbinfo.tsb_ttesz_mask, ttesz_mask_bits);
664*0Sstevel@tonic-gate 
665*0Sstevel@tonic-gate 	/* Print TSB entries? */
666*0Sstevel@tonic-gate 	if (lflag) {
667*0Sstevel@tonic-gate 
668*0Sstevel@tonic-gate 		if ((tsbinfo.tsb_flags & TSB_SWAPPED) == 0) {
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate 			entries = TSB_ENTRIES(tsbinfo.tsb_szc);
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate 			tsbp = mdb_alloc(sizeof (struct tsbe) * entries,
673*0Sstevel@tonic-gate 			    UM_SLEEP);
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate 			if (mdb_vread(tsbp, sizeof (struct tsbe) * entries,
676*0Sstevel@tonic-gate 				(uintptr_t)tsbinfo.tsb_va) == -1) {
677*0Sstevel@tonic-gate 				mdb_warn("failed to read TSB at %p",
678*0Sstevel@tonic-gate 				    tsbinfo.tsb_va);
679*0Sstevel@tonic-gate 				return (DCMD_ERR);
680*0Sstevel@tonic-gate 			}
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate 			mdb_printf(
683*0Sstevel@tonic-gate 				"TSB @ %lx (%d entries)\n"
684*0Sstevel@tonic-gate 				    "%-?s %-17s %s\n"
685*0Sstevel@tonic-gate 				    "%<u>%-?s %1s %1s %-11s %1s %1s %1s "
686*0Sstevel@tonic-gate 				    "%1s %1s %2s %8s %1s %1s %1s %1s %1s %1s "
687*0Sstevel@tonic-gate 				    "%1s %1s %1s %1s %1s%</u>\n",
688*0Sstevel@tonic-gate 				    tsbinfo.tsb_va, entries,
689*0Sstevel@tonic-gate 				    "", "TAG", "TTE",
690*0Sstevel@tonic-gate 				    "ADDR", "I", "L", "VA 63:22", "V",
691*0Sstevel@tonic-gate 				    "S", "N", "I", "H", "LC", "PA 42:13", "R",
692*0Sstevel@tonic-gate 				    "W", "N", "X", "L", "P", "V", "E", "P",
693*0Sstevel@tonic-gate 				    "W", "G");
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 			tsbend = tsbp + entries;
696*0Sstevel@tonic-gate 			for (tsbstart = tsbp; tsbp < tsbend; tsbp++) {
697*0Sstevel@tonic-gate 				if (aflag ||
698*0Sstevel@tonic-gate 				    (tsbp->tte_tag.tag_invalid == 0)) {
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate 					va = (caddr_t)
701*0Sstevel@tonic-gate 					    (((uint64_t)tsbp->tte_tag.tag_vahi
702*0Sstevel@tonic-gate 						<< 32) +
703*0Sstevel@tonic-gate 						tsbp->tte_tag.tag_valo);
704*0Sstevel@tonic-gate 					pa = (tsbp->tte_data.tte_pahi << 19) +
705*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_palo;
706*0Sstevel@tonic-gate 					mdb_printf("%0?lx %-1u %-1u "
707*0Sstevel@tonic-gate 					    "%011lx %1u %-1u %-1u %-1u %-1u "
708*0Sstevel@tonic-gate 					    "%-2u %08x %1u %1u %1u %1u %1u "
709*0Sstevel@tonic-gate 					    "%1u %1u %1u %1u %1u %1u\n",
710*0Sstevel@tonic-gate 					    tsbinfo.tsb_va + (tsbp - tsbstart)
711*0Sstevel@tonic-gate 					    * sizeof (struct tsbe),
712*0Sstevel@tonic-gate 					    tsbp->tte_tag.tag_invalid,
713*0Sstevel@tonic-gate 					    tsbp->tte_tag.tag_locked, va,
714*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_val,
715*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_size,
716*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_nfo,
717*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_ie,
718*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_hmenum,
719*0Sstevel@tonic-gate #ifdef sun4v
720*0Sstevel@tonic-gate 					    0,
721*0Sstevel@tonic-gate #else
722*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_lckcnt,
723*0Sstevel@tonic-gate #endif
724*0Sstevel@tonic-gate 					    pa,
725*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_ref,
726*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_wr_perm,
727*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_no_sync,
728*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_exec_perm,
729*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_lock,
730*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_cp,
731*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_cv,
732*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_se,
733*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_priv,
734*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_hwwr,
735*0Sstevel@tonic-gate #ifdef sun4v
736*0Sstevel@tonic-gate 					    0
737*0Sstevel@tonic-gate #else
738*0Sstevel@tonic-gate 					    tsbp->tte_data.tte_glb
739*0Sstevel@tonic-gate #endif
740*0Sstevel@tonic-gate 					    /*CSTYLED*/
741*0Sstevel@tonic-gate 					    );
742*0Sstevel@tonic-gate 				}
743*0Sstevel@tonic-gate 			}
744*0Sstevel@tonic-gate 
745*0Sstevel@tonic-gate 			mdb_printf("\n"); /* blank line for readability */
746*0Sstevel@tonic-gate 
747*0Sstevel@tonic-gate 			mdb_free(tsbstart, sizeof (struct tsbe) * entries);
748*0Sstevel@tonic-gate 
749*0Sstevel@tonic-gate 		} else {
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate 			mdb_printf("TSB swapped out\n");
752*0Sstevel@tonic-gate 		}
753*0Sstevel@tonic-gate 	}
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	return (DCMD_OK);
756*0Sstevel@tonic-gate }
757