xref: /titanic_51/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c (revision cbdcbd056f15c9c9fd82d5543b3a502677c4d391)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*cbdcbd05SJonathan Adams  * Common Development and Distribution License (the "License").
6*cbdcbd05SJonathan Adams  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*cbdcbd05SJonathan Adams  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
287c478bd9Sstevel@tonic-gate #include <vm/as.h>
297c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
327c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h>
337c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * sfmmu mdb support
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_SYMBOL	1
407c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_VERBOSE	2
417c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_DEBUG	4
427c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_ALL	(SFMMU_VTOP_DBG_SYMBOL|SFMMU_VTOP_DBG_VERBOSE|\
437c478bd9Sstevel@tonic-gate 				SFMMU_VTOP_DBG_DEBUG)
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_SYM	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_SYMBOL) \
467c478bd9Sstevel@tonic-gate 				    mdb_printf
477c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_VRB	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_VERBOSE) \
487c478bd9Sstevel@tonic-gate 				    mdb_printf
497c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_DBG_DBG	if (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_DEBUG) \
507c478bd9Sstevel@tonic-gate 				    mdb_printf
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	SFMMU_VTOP_READSYM(dest, synm, where) \
537c478bd9Sstevel@tonic-gate 	if (mdb_readsym(&(dest), sizeof (dest), (synm)) == -1) \
547c478bd9Sstevel@tonic-gate 		mdb_warn("%s: couldn't find or read '%s'\n", (where), (synm));
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate struct hme_blks_max {
577c478bd9Sstevel@tonic-gate 	struct hme_blk	hmx_hmeblk;
587c478bd9Sstevel@tonic-gate 	struct sf_hment	hmx_hmes[NHMENTS - 1];
597c478bd9Sstevel@tonic-gate };
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate int sfmmu_vtop(uintptr_t, uint_t, int, const mdb_arg_t *);
627c478bd9Sstevel@tonic-gate static int sfmmu_vtop_common(struct as *, uintptr_t, physaddr_t *);
637c478bd9Sstevel@tonic-gate static int sfmmu_vtop_impl(uintptr_t, sfmmu_t *, sfmmu_t *, physaddr_t *);
647c478bd9Sstevel@tonic-gate static void sfmmu_vtop_print_hmeblk(struct hme_blk *);
657c478bd9Sstevel@tonic-gate static struct sf_hment *mdb_sfmmu_hblktohme(struct hme_blk *, caddr_t, int *);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate int sfmmu_vtop_dbg_wanted = 0;	/* set this as desired */
687c478bd9Sstevel@tonic-gate int sfmmu_vtop_dbg = 0;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * ::sfmmu_vtop [[-v] -a as]
727c478bd9Sstevel@tonic-gate  * Extended version of the vtop builtin. The optional <as> argument is
737c478bd9Sstevel@tonic-gate  * used as base address space for translating a virtual address into a
747c478bd9Sstevel@tonic-gate  * physical address. The verbose option ("-v") shows intermediate
757c478bd9Sstevel@tonic-gate  * translation steps. If <as> or kas is ommitted, the builtin ::vtop
767c478bd9Sstevel@tonic-gate  * dcmd is called.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate int
797c478bd9Sstevel@tonic-gate sfmmu_vtop(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	int ret;
827c478bd9Sstevel@tonic-gate 	struct as *asp = NULL;
837c478bd9Sstevel@tonic-gate 	char *asnmp = NULL;
847c478bd9Sstevel@tonic-gate 	int verbose = 0;
857c478bd9Sstevel@tonic-gate 	physaddr_t paddr;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	sfmmu_vtop_dbg = sfmmu_vtop_dbg_wanted;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
907c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
917c478bd9Sstevel@tonic-gate 	    'a', MDB_OPT_STR, &asnmp,
927c478bd9Sstevel@tonic-gate 	    NULL) != argc)
937c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	if (verbose != 0 && asnmp == NULL) {
967c478bd9Sstevel@tonic-gate 		mdb_warn("-v requires -a option\n");
977c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	if (verbose != 0 && (sfmmu_vtop_dbg & SFMMU_VTOP_DBG_VERBOSE) == 0) {
1017c478bd9Sstevel@tonic-gate 		sfmmu_vtop_dbg |= SFMMU_VTOP_DBG_VERBOSE;
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (asnmp != NULL) {
1057c478bd9Sstevel@tonic-gate 		GElf_Sym sym;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("asnmp=%p asnm=%s\n", asnmp, asnmp);
1087c478bd9Sstevel@tonic-gate 		if (strcmp(asnmp, "kas") == 0) {
1097c478bd9Sstevel@tonic-gate 			if (mdb_lookup_by_name("kas", &sym) == -1) {
1107c478bd9Sstevel@tonic-gate 				mdb_warn("couldn't find 'kas'\n");
1117c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
1127c478bd9Sstevel@tonic-gate 			} else {
1137c478bd9Sstevel@tonic-gate 				asp = (struct as *)sym.st_value;
1147c478bd9Sstevel@tonic-gate 				SFMMU_VTOP_DBG_SYM("kas &sym=%p\n", &sym);
1157c478bd9Sstevel@tonic-gate 			}
1167c478bd9Sstevel@tonic-gate 		} else {
1177c478bd9Sstevel@tonic-gate 			asp = (struct as *)mdb_strtoull(asnmp);
1187c478bd9Sstevel@tonic-gate 		}
1197c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("asp=0x%p\n", asp);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	if (asp == 0) {
1237c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("sfmmu_vtop: call standard vtop\n");
1247c478bd9Sstevel@tonic-gate 		return (mdb_call_dcmd("vtop", addr, flags, argc, argv));
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if ((ret = sfmmu_vtop_common(asp, addr, &paddr)) == -1L) {
1287c478bd9Sstevel@tonic-gate 		mdb_printf("no mapping found for addr=%p\n", addr);
1297c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	if (ret == 0) {
1337c478bd9Sstevel@tonic-gate 		mdb_printf("address space %p: virtual %lr mapped to physical "
1347c478bd9Sstevel@tonic-gate 			"%llr", asp, addr, paddr);
1357c478bd9Sstevel@tonic-gate 	} else {
1367c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate static int
1437c478bd9Sstevel@tonic-gate sfmmu_vtop_common(struct as *asp, uintptr_t addr, physaddr_t *pap)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	struct as mas;
1467c478bd9Sstevel@tonic-gate 	struct as *masp = &mas;
1477c478bd9Sstevel@tonic-gate 	sfmmu_t *hatp;
1487c478bd9Sstevel@tonic-gate 	sfmmu_t mhat;
1497c478bd9Sstevel@tonic-gate 	sfmmu_t *mhatp = &mhat;
1507c478bd9Sstevel@tonic-gate 	int ret;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if (mdb_vread(masp, sizeof (mas), (uintptr_t)asp) == -1) {
1537c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read as at %p\n", asp);
1547c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	hatp = masp->a_hat;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("hatp=%p addr=%p masp=%p\n", hatp, addr, masp);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	if (mdb_vread(mhatp, sizeof (mhat), (uintptr_t)hatp) == -1) {
1627c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read hat at %p\n", hatp);
1637c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	if (mhatp->sfmmu_as != asp) {
1667c478bd9Sstevel@tonic-gate 		mdb_warn("%p is not a valid address space\n", asp);
1677c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	ret = sfmmu_vtop_impl(addr, hatp, mhatp, pap);
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	return (ret);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static int
1767c478bd9Sstevel@tonic-gate sfmmu_vtop_impl(uintptr_t addr, sfmmu_t *sfmmup, sfmmu_t *msfmmup,
1777c478bd9Sstevel@tonic-gate 	    physaddr_t *pap)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	struct hmehash_bucket *uhme_hash;
1807c478bd9Sstevel@tonic-gate 	struct hmehash_bucket *khme_hash;
1817c478bd9Sstevel@tonic-gate 	int uhmehash_num;
1827c478bd9Sstevel@tonic-gate 	int khmehash_num;
1837c478bd9Sstevel@tonic-gate 	sfmmu_t *ksfmmup;
1847c478bd9Sstevel@tonic-gate 	struct hmehash_bucket mbucket;
1857c478bd9Sstevel@tonic-gate 	struct hmehash_bucket *hmebp;
1867c478bd9Sstevel@tonic-gate 	struct hmehash_bucket *shmebp;
1877c478bd9Sstevel@tonic-gate 	hmeblk_tag hblktag;
1887c478bd9Sstevel@tonic-gate 	int hmeshift;
1897c478bd9Sstevel@tonic-gate 	int hashno = 1;
1907c478bd9Sstevel@tonic-gate 	struct hme_blk *hmeblkp = NULL;
1917c478bd9Sstevel@tonic-gate 	struct hme_blks_max mhmeblkmax;
1927c478bd9Sstevel@tonic-gate 	intptr_t thmeblkp;
1937c478bd9Sstevel@tonic-gate 	struct sf_hment *sfhmep;
1947c478bd9Sstevel@tonic-gate 	int i;
1957c478bd9Sstevel@tonic-gate 	ism_blk_t mism_blk;
1967c478bd9Sstevel@tonic-gate 	ism_map_t *ism_map;
1977c478bd9Sstevel@tonic-gate 	ism_blk_t *ism_blkp;
1987c478bd9Sstevel@tonic-gate 	ism_blk_t *sism_blkp;
1997c478bd9Sstevel@tonic-gate 	sfmmu_t *ism_hatid = NULL;
2007c478bd9Sstevel@tonic-gate 	int sfhmeinx = 0;
2017c478bd9Sstevel@tonic-gate 	tte_t tte;
2027c478bd9Sstevel@tonic-gate 	pfn_t pfn;
2037c478bd9Sstevel@tonic-gate 	pfn_t start_pfn;
2047c478bd9Sstevel@tonic-gate 	page_t *pp;
2057c478bd9Sstevel@tonic-gate 	int ret = -1;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(uhme_hash, "uhme_hash", "sfmmu_vtop_impl");
2087c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("uhme_hash=%p\t", uhme_hash);
2097c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(uhmehash_num, "uhmehash_num", "sfmmu_vtop_impl");
2107c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("uhmehash_num=%lx\n", uhmehash_num);
2117c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(khme_hash, "khme_hash", "sfmmu_vtop_impl");
2127c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("khme_hash=%p\t", khme_hash);
2137c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(khmehash_num, "khmehash_num", "sfmmu_vtop_impl");
2147c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("khmehash_num=%lx\n", khmehash_num);
2157c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_READSYM(ksfmmup, "ksfmmup", "sfmmu_vtop_impl");
2167c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("ksfmmup=%p\n", ksfmmup);
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	ism_blkp = sism_blkp = msfmmup->sfmmu_iblk;
2197c478bd9Sstevel@tonic-gate 	while (ism_blkp != NULL && ism_hatid == NULL) {
2207c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("ism_blkp=%p\n", ism_blkp);
2217c478bd9Sstevel@tonic-gate 		if (mdb_vread(&mism_blk, sizeof (mism_blk),
2227c478bd9Sstevel@tonic-gate 		    (uintptr_t)ism_blkp) == -1) {
2237c478bd9Sstevel@tonic-gate 			mdb_warn("couldn't read ism_blk at %p\n", ism_blkp);
2247c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 		ism_blkp = &mism_blk;
2277c478bd9Sstevel@tonic-gate 		ism_map = ism_blkp->iblk_maps;
2287c478bd9Sstevel@tonic-gate 		for (i = 0; ism_map[i].imap_ismhat && i < ISM_MAP_SLOTS; i++) {
2297c478bd9Sstevel@tonic-gate 			if ((caddr_t)addr >= ism_start(ism_map[i]) &&
2307c478bd9Sstevel@tonic-gate 			    (caddr_t)addr < ism_end(ism_map[i])) {
2317c478bd9Sstevel@tonic-gate 				sfmmup = ism_hatid = ism_map[i].imap_ismhat;
2327c478bd9Sstevel@tonic-gate 				addr = (caddr_t)addr - ism_start(ism_map[i]);
2337c478bd9Sstevel@tonic-gate 				SFMMU_VTOP_DBG_VRB("ism_blkp=%p inx=%d\n",
2347c478bd9Sstevel@tonic-gate 				    sism_blkp, i);
2357c478bd9Sstevel@tonic-gate 				SFMMU_VTOP_DBG_DBG("ism map=%p ism hat=%p "
2367c478bd9Sstevel@tonic-gate 				    "addr=%llx\n",
2377c478bd9Sstevel@tonic-gate 				    (caddr_t)&ism_map[i] - (caddr_t)ism_blkp
2387c478bd9Sstevel@tonic-gate 				    + (caddr_t)sism_blkp, sfmmup, addr);
2397c478bd9Sstevel@tonic-gate 				break;
2407c478bd9Sstevel@tonic-gate 			}
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 		ism_blkp = sism_blkp = ism_blkp->iblk_next;
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	hblktag.htag_id = sfmmup;
2467c478bd9Sstevel@tonic-gate 	do {
2477c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("-hashno=%d-\n", hashno);
2487c478bd9Sstevel@tonic-gate 		hmeshift = HME_HASH_SHIFT(hashno);
2497c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hmeshift=%d\n", hmeshift);
2507c478bd9Sstevel@tonic-gate 		hblktag.htag_bspage = HME_HASH_BSPAGE(addr, hmeshift);
2517c478bd9Sstevel@tonic-gate 		hblktag.htag_rehash = hashno;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate #ifdef __sparcv9
2547c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hblktag=%lx %lx\n",
2557c478bd9Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag[0],
2567c478bd9Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag[1]);
2577c478bd9Sstevel@tonic-gate #else
2587c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hblktag=%llx\n",
2597c478bd9Sstevel@tonic-gate 				(uint64_t)hblktag.htag_tag);
2607c478bd9Sstevel@tonic-gate #endif
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		hmebp = shmebp = HME_HASH_FUNCTION(sfmmup, addr, hmeshift);
2637c478bd9Sstevel@tonic-gate 		SFMMU_VTOP_DBG_DBG("hmebp=%p\n", hmebp);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		if (mdb_vread(&mbucket, sizeof (mbucket),
2667c478bd9Sstevel@tonic-gate 				(uintptr_t)hmebp) == -1) {
2677c478bd9Sstevel@tonic-gate 			mdb_warn("couldn't read mbucket at %p\n", hmebp);
2687c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 		hmebp = &mbucket;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		for (hmeblkp = hmebp->hmeblkp; hmeblkp;
2747c478bd9Sstevel@tonic-gate 			hmeblkp = hmeblkp->hblk_next) {
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 			SFMMU_VTOP_DBG_DBG("hmeblkp=%p\n", hmeblkp);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 			if (hmeblkp == NULL)
2797c478bd9Sstevel@tonic-gate 				break;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 			if (mdb_vread(&mhmeblkmax, sizeof (struct hme_blk),
2827c478bd9Sstevel@tonic-gate 					(uintptr_t)hmeblkp) == -1) {
2837c478bd9Sstevel@tonic-gate 				mdb_warn("couldn't read hme_blk at %p\n",
2847c478bd9Sstevel@tonic-gate 					hmeblkp);
2857c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
2867c478bd9Sstevel@tonic-gate 			}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 			thmeblkp = (uintptr_t)hmeblkp;
2897c478bd9Sstevel@tonic-gate 			hmeblkp = &mhmeblkmax.hmx_hmeblk;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 			if (HTAGS_EQ(hmeblkp->hblk_tag, hblktag)) {
2927c478bd9Sstevel@tonic-gate 				/* found hme_blk */
2937c478bd9Sstevel@tonic-gate 				break;
2947c478bd9Sstevel@tonic-gate 			}
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 		if (hmeblkp != NULL) {
2987c478bd9Sstevel@tonic-gate 			sfmmu_vtop_print_hmeblk(hmeblkp);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 			sfhmep = mdb_sfmmu_hblktohme(hmeblkp, (caddr_t)addr,
3017c478bd9Sstevel@tonic-gate 					&sfhmeinx);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 			SFMMU_VTOP_DBG_DBG("sfhmeinx=%d ", sfhmeinx);
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 			if (sfhmeinx > 0) {
3067c478bd9Sstevel@tonic-gate 				thmeblkp += sizeof (struct hme_blk) +
3077c478bd9Sstevel@tonic-gate 				    sizeof (struct sf_hment) * (sfhmeinx - 1);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 				if (mdb_vread(sfhmep, sizeof (struct sf_hment),
3107c478bd9Sstevel@tonic-gate 						thmeblkp) == -1) {
3117c478bd9Sstevel@tonic-gate 					mdb_warn("couldn't read msfhme at %p\n",
3127c478bd9Sstevel@tonic-gate 						sfhmep);
3137c478bd9Sstevel@tonic-gate 					return (DCMD_ERR);
3147c478bd9Sstevel@tonic-gate 				}
3157c478bd9Sstevel@tonic-gate 			}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 			SFMMU_VTOP_DBG_VRB("sfmmup=%p hmebp=%p hmeblkp=%p\n",
3187c478bd9Sstevel@tonic-gate 					sfmmup, shmebp, thmeblkp);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 			tte = sfhmep->hme_tte;
3217c478bd9Sstevel@tonic-gate 			SFMMU_VTOP_DBG_VRB("tte=%llx ", tte.ll);
3227c478bd9Sstevel@tonic-gate 			if (TTE_IS_VALID(&tte)) {
3237c478bd9Sstevel@tonic-gate 				start_pfn = TTE_TO_TTEPFN(&tte);
3247c478bd9Sstevel@tonic-gate 				*pap = (start_pfn << MMU_PAGESHIFT) +
3257c478bd9Sstevel@tonic-gate 					(addr & TTE_PAGE_OFFSET(tte.tte_size));
3267c478bd9Sstevel@tonic-gate 				pfn = *pap >> MMU_PAGESHIFT;
3277c478bd9Sstevel@tonic-gate 				pp = (sfhmep->hme_page != 0) ?
3287c478bd9Sstevel@tonic-gate 					sfhmep->hme_page + (pfn - start_pfn) :
3297c478bd9Sstevel@tonic-gate 					0;
3307c478bd9Sstevel@tonic-gate 				SFMMU_VTOP_DBG_VRB("pfn=%lx pp=%p\n",
3317c478bd9Sstevel@tonic-gate 					pfn, pp);
3327c478bd9Sstevel@tonic-gate 				ret = 0;
3337c478bd9Sstevel@tonic-gate 			}
3347c478bd9Sstevel@tonic-gate 			break;
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		hashno++;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	} while (HME_REHASH(msfmmup) && (hashno <= MAX_HASHCNT));
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	return (ret);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate static void
3457c478bd9Sstevel@tonic-gate sfmmu_vtop_print_hmeblk(struct hme_blk *hmeblkp)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if ((sfmmu_vtop_dbg & SFMMU_VTOP_DBG_DEBUG) == NULL)
3497c478bd9Sstevel@tonic-gate 		return;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	mdb_printf("    hblk_nextpa=%llx\n", hmeblkp->hblk_nextpa);
3527c478bd9Sstevel@tonic-gate #ifdef __sparcv9
3537c478bd9Sstevel@tonic-gate 	mdb_printf("    hblktag=%lx %lx\n", hmeblkp->hblk_tag.htag_tag[0],
3547c478bd9Sstevel@tonic-gate 			hmeblkp->hblk_tag.htag_tag[1]);
3557c478bd9Sstevel@tonic-gate #else
3567c478bd9Sstevel@tonic-gate 	mdb_printf("    hblktag=%llx\n", hmeblkp->hblk_tag.htag_tag);
3577c478bd9Sstevel@tonic-gate #endif
3587c478bd9Sstevel@tonic-gate 	mdb_printf("    hblk_next=%p\n", hmeblkp->hblk_next);
3597c478bd9Sstevel@tonic-gate 	mdb_printf("    hblk_shadow=%p\n", hmeblkp->hblk_shadow);
3607c478bd9Sstevel@tonic-gate 	mdb_printf("    hblk_span=%d\n", hmeblkp->hblk_span);
3617c478bd9Sstevel@tonic-gate 	mdb_printf("    hblk_ttesz=%d\n", hmeblkp->hblk_ttesz);
3627c478bd9Sstevel@tonic-gate 	if (hmeblkp->hblk_shw_bit == 0) {
3637c478bd9Sstevel@tonic-gate 		mdb_printf("    hblk_hmecnt=%d\n", hmeblkp->hblk_hmecnt);
3647c478bd9Sstevel@tonic-gate 		mdb_printf("    hblk_vcnt=%d\n", hmeblkp->hblk_vcnt);
3657c478bd9Sstevel@tonic-gate 	} else {
3667c478bd9Sstevel@tonic-gate 		mdb_printf("    hblk_shw_mask=%x\n", hmeblkp->hblk_shw_mask);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate static struct sf_hment *
3717c478bd9Sstevel@tonic-gate mdb_sfmmu_hblktohme(struct hme_blk *hmeblkp, caddr_t addr, int *hmenump)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	int index = 0;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	if (get_hblk_ttesz(hmeblkp) == TTE8K) {
3767c478bd9Sstevel@tonic-gate 		index = (((uintptr_t)addr >> MMU_PAGESHIFT) & (NHMENTS-1));
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (hmenump) {
3807c478bd9Sstevel@tonic-gate 		*hmenump = index;
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	return (&hmeblkp->hblk_hme[index]);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * ::memseg_list dcmd
3887c478bd9Sstevel@tonic-gate  */
3897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3907c478bd9Sstevel@tonic-gate int
3917c478bd9Sstevel@tonic-gate memseg_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	struct memseg ms;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
3967c478bd9Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("memseg", "memseg_list",
3977c478bd9Sstevel@tonic-gate 		    0, NULL, 0) == -1) {
3987c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk memseg");
3997c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
4007c478bd9Sstevel@tonic-gate 		}
4017c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
4057c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%?s %?s %?s %?s %?s%</u>\n", "ADDR",
4067c478bd9Sstevel@tonic-gate 			"PAGES", "EPAGES", "BASE", "END");
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	if (mdb_vread(&ms, sizeof (struct memseg), addr) == -1) {
4097c478bd9Sstevel@tonic-gate 		mdb_warn("can't read memseg at %#lx", addr);
4107c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	mdb_printf("%0?lx %0?lx %0?lx %0?lx %0?lx\n", addr,
4147c478bd9Sstevel@tonic-gate 		ms.pages, ms.epages, ms.pages_base, ms.pages_end);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate /*
4207c478bd9Sstevel@tonic-gate  * walk the memseg structures
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate int
4237c478bd9Sstevel@tonic-gate memseg_walk_init(mdb_walk_state_t *wsp)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr != NULL) {
4267c478bd9Sstevel@tonic-gate 		mdb_warn("memseg only supports global walks\n");
4277c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&wsp->walk_addr, "memsegs") == -1) {
4317c478bd9Sstevel@tonic-gate 		mdb_warn("symbol 'memsegs' not found");
4327c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4337c478bd9Sstevel@tonic-gate 	}
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (struct memseg), UM_SLEEP);
4367c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate int
4417c478bd9Sstevel@tonic-gate memseg_walk_step(mdb_walk_state_t *wsp)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	int status;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == 0) {
4467c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (struct memseg),
4507c478bd9Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
4517c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read struct memseg at %p", wsp->walk_addr);
4527c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
4567c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((struct memseg *)wsp->walk_data)->next);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	return (status);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate void
4647c478bd9Sstevel@tonic-gate memseg_walk_fini(mdb_walk_state_t *wsp)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (struct memseg));
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate int
4707c478bd9Sstevel@tonic-gate platform_vtop(uintptr_t addr, struct as *asp, physaddr_t *pap)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	int rv;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	sfmmu_vtop_dbg = sfmmu_vtop_dbg_wanted;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	SFMMU_VTOP_DBG_DBG("platform_vtop: called.\n");
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	if (asp == NULL) {
4797c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	if ((rv = sfmmu_vtop_common(asp, addr, pap)) == 0) {
4837c478bd9Sstevel@tonic-gate 		mdb_printf("address space %p: ", asp);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	return (rv);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate  * ::tsbinfo help
4917c478bd9Sstevel@tonic-gate  */
4927c478bd9Sstevel@tonic-gate void
4937c478bd9Sstevel@tonic-gate tsbinfo_help(void)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	mdb_printf("-l\tlist valid TSB entries.\n"
4967c478bd9Sstevel@tonic-gate 	    "-a\tlist all TSB entries.  Can only be used with -l.\n");
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate  * ::tsbinfo dcmd
5017c478bd9Sstevel@tonic-gate  */
5027c478bd9Sstevel@tonic-gate int
5037c478bd9Sstevel@tonic-gate tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate 	uint_t lflag = 0, aflag = 0;
5067c478bd9Sstevel@tonic-gate 	struct tsb_info tsbinfo;
5077c478bd9Sstevel@tonic-gate 	unsigned int entries = 0;
5087c478bd9Sstevel@tonic-gate 	struct tsbe *tsbp, *tsbend, *tsbstart;
5097c478bd9Sstevel@tonic-gate 	caddr_t va;
5107c478bd9Sstevel@tonic-gate 	uintptr_t pa;
5117c478bd9Sstevel@tonic-gate 	uint_t tsbbytes;
5127c478bd9Sstevel@tonic-gate 	char tsbsize[16];
5137c478bd9Sstevel@tonic-gate #define	FLAGS_SIZE	sizeof ("RELOC,FLUSH,SWAPPED")
5147c478bd9Sstevel@tonic-gate 	char tsbflags[FLAGS_SIZE + 1];
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	static const mdb_bitmask_t ttesz_mask_bits[] = {
5177c478bd9Sstevel@tonic-gate 		{ "8K", TSB8K, TSB8K },
5187c478bd9Sstevel@tonic-gate 		{ "64K", TSB64K, TSB64K },
5197c478bd9Sstevel@tonic-gate 		{ "512K", TSB512K, TSB512K },
5207c478bd9Sstevel@tonic-gate 		{ "4M", TSB4M, TSB4M },
5211bd453f3Ssusans 		{ "32M", TSB32M, TSB32M },
5221bd453f3Ssusans 		{ "256M", TSB256M, TSB256M },
5237c478bd9Sstevel@tonic-gate 		{ NULL, 0, 0 }
5247c478bd9Sstevel@tonic-gate 	};
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	static const mdb_bitmask_t flags_bits[] = {
5277c478bd9Sstevel@tonic-gate 		{ "RELOC", TSB_RELOC_FLAG, TSB_RELOC_FLAG },
5287c478bd9Sstevel@tonic-gate 		{ "FLUSH", TSB_FLUSH_NEEDED, TSB_FLUSH_NEEDED },
5297c478bd9Sstevel@tonic-gate 		{ "SWAPPED", TSB_SWAPPED, TSB_SWAPPED },
5307c478bd9Sstevel@tonic-gate 		{ NULL, 0, 0 }
5317c478bd9Sstevel@tonic-gate 	};
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
5347c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
5387c478bd9Sstevel@tonic-gate 		'l', MDB_OPT_SETBITS, TRUE, &lflag,
5397c478bd9Sstevel@tonic-gate 		'a', MDB_OPT_SETBITS, TRUE, &aflag,
5407c478bd9Sstevel@tonic-gate 		NULL) != argc) {
5417c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5427c478bd9Sstevel@tonic-gate 	}
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	/* -a only valid with -l */
5457c478bd9Sstevel@tonic-gate 	if (aflag && !lflag) {
5467c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	/* Print header? */
5507c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) || lflag) {
5517c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-?s %-8s %-*s %s%</u>\n", "TSBINFO",
5527c478bd9Sstevel@tonic-gate 		    "TSB", "SIZE", FLAGS_SIZE, "FLAGS", "TTE SIZES");
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if (mdb_vread(&tsbinfo, sizeof (struct tsb_info), addr) == -1) {
5567c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read struct tsb_info at %p", addr);
5577c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	mdb_printf("%0?lx ", addr);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	/* Print a "-" if the TSB is swapped out. */
5637c478bd9Sstevel@tonic-gate 	if ((tsbinfo.tsb_flags & TSB_SWAPPED) == 0) {
5647c478bd9Sstevel@tonic-gate 		mdb_printf("%0?lx ", tsbinfo.tsb_va);
5657c478bd9Sstevel@tonic-gate 	} else {
5667c478bd9Sstevel@tonic-gate 		mdb_printf("%0?-s ", "-");
5677c478bd9Sstevel@tonic-gate 	}
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	tsbbytes = TSB_BYTES(tsbinfo.tsb_szc);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate #define	KB 1024
5727c478bd9Sstevel@tonic-gate #define	MB (KB*KB)
5737c478bd9Sstevel@tonic-gate 	if (tsbbytes >= MB) {
5747c478bd9Sstevel@tonic-gate 		mdb_snprintf(tsbsize, sizeof (tsbsize), "%dM", tsbbytes / MB);
5757c478bd9Sstevel@tonic-gate 	} else {
5767c478bd9Sstevel@tonic-gate 		mdb_snprintf(tsbsize, sizeof (tsbsize), "%dK", tsbbytes / KB);
5777c478bd9Sstevel@tonic-gate 	}
5787c478bd9Sstevel@tonic-gate #undef MB
5797c478bd9Sstevel@tonic-gate #undef KB
5807c478bd9Sstevel@tonic-gate 	mdb_printf("%-8s ", tsbsize);
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (tsbinfo.tsb_flags == 0) {
5837c478bd9Sstevel@tonic-gate 		mdb_printf("%-*s ", FLAGS_SIZE, "-");
5847c478bd9Sstevel@tonic-gate 	} else {
5857c478bd9Sstevel@tonic-gate 		mdb_snprintf(tsbflags, sizeof (tsbflags), "%b",
5867c478bd9Sstevel@tonic-gate 		    tsbinfo.tsb_flags, flags_bits);
5877c478bd9Sstevel@tonic-gate 		mdb_printf("%-*s ", FLAGS_SIZE, tsbflags);
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	mdb_printf("%b\n", tsbinfo.tsb_ttesz_mask, ttesz_mask_bits);
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	/* Print TSB entries? */
5937c478bd9Sstevel@tonic-gate 	if (lflag) {
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 		if ((tsbinfo.tsb_flags & TSB_SWAPPED) == 0) {
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 			entries = TSB_ENTRIES(tsbinfo.tsb_szc);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 			tsbp = mdb_alloc(sizeof (struct tsbe) * entries,
6007c478bd9Sstevel@tonic-gate 			    UM_SLEEP);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			if (mdb_vread(tsbp, sizeof (struct tsbe) * entries,
6037c478bd9Sstevel@tonic-gate 				(uintptr_t)tsbinfo.tsb_va) == -1) {
6047c478bd9Sstevel@tonic-gate 				mdb_warn("failed to read TSB at %p",
6057c478bd9Sstevel@tonic-gate 				    tsbinfo.tsb_va);
6067c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
6077c478bd9Sstevel@tonic-gate 			}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 			mdb_printf(
6107c478bd9Sstevel@tonic-gate 				"TSB @ %lx (%d entries)\n"
6117c478bd9Sstevel@tonic-gate 				    "%-?s %-17s %s\n"
6121bd453f3Ssusans 				    "%<u>%-?s %1s %1s %-11s "
6131bd453f3Ssusans 				    "%1s %1s %1s %1s %1s %1s %8s "
6141bd453f3Ssusans 				    "%1s %1s %1s %1s %1s %1s %1s "
6151bd453f3Ssusans 				    "%1s %1s %1s %1s %1s %1s%</u>\n",
6161bd453f3Ssusans 				    tsbinfo.tsb_va, entries, "", "TAG", "TTE",
6171bd453f3Ssusans 				    "ADDR", "I", "L", "VA 63:22",
6181bd453f3Ssusans 				    "V", "S", "N", "I", "H", "S", "PA 42:13",
6191bd453f3Ssusans 				    "N", "U", "R", "W", "E", "X", "L",
6201bd453f3Ssusans 				    "P", "V", "E", "P", "W", "G");
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 			tsbend = tsbp + entries;
6237c478bd9Sstevel@tonic-gate 			for (tsbstart = tsbp; tsbp < tsbend; tsbp++) {
6247c478bd9Sstevel@tonic-gate 				if (aflag ||
6257c478bd9Sstevel@tonic-gate 				    (tsbp->tte_tag.tag_invalid == 0)) {
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 					va = (caddr_t)
6287c478bd9Sstevel@tonic-gate 					    (((uint64_t)tsbp->tte_tag.tag_vahi
6297c478bd9Sstevel@tonic-gate 						<< 32) +
6307c478bd9Sstevel@tonic-gate 						tsbp->tte_tag.tag_valo);
6317c478bd9Sstevel@tonic-gate 					pa = (tsbp->tte_data.tte_pahi << 19) +
6327c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_palo;
6331bd453f3Ssusans 					mdb_printf("%0?lx %-1u %-1u %011lx "
6341bd453f3Ssusans 					    "%1u %-1u %-1u %-1u %-1u %1u %08x "
6351bd453f3Ssusans 					    "%1u %1u %1u %1u %1u %1u %1u "
6367c478bd9Sstevel@tonic-gate 					    "%1u %1u %1u %1u %1u %1u\n",
6377c478bd9Sstevel@tonic-gate 					    tsbinfo.tsb_va + (tsbp - tsbstart)
6387c478bd9Sstevel@tonic-gate 					    * sizeof (struct tsbe),
6397c478bd9Sstevel@tonic-gate 					    tsbp->tte_tag.tag_invalid,
6407c478bd9Sstevel@tonic-gate 					    tsbp->tte_tag.tag_locked, va,
6417c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_val,
6427c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_size,
6437c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_nfo,
6447c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_ie,
6457c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_hmenum,
6467c478bd9Sstevel@tonic-gate #ifdef sun4v
6477c478bd9Sstevel@tonic-gate 					    0,
6487c478bd9Sstevel@tonic-gate #else
6491bd453f3Ssusans 					    tsbp->tte_data.tte_size2,
6507c478bd9Sstevel@tonic-gate #endif
6517c478bd9Sstevel@tonic-gate 					    pa,
6521bd453f3Ssusans 					    tsbp->tte_data.tte_no_sync,
6531bd453f3Ssusans 					    tsbp->tte_data.tte_suspend,
6547c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_ref,
6557c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_wr_perm,
6561bd453f3Ssusans #ifdef sun4v
6571bd453f3Ssusans 					    0,
6581bd453f3Ssusans #else
6591bd453f3Ssusans 					    tsbp->tte_data.tte_exec_synth,
6601bd453f3Ssusans #endif
6617c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_exec_perm,
6627c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_lock,
6637c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_cp,
6647c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_cv,
6657c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_se,
6667c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_priv,
6677c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_hwwr,
6687c478bd9Sstevel@tonic-gate #ifdef sun4v
6697c478bd9Sstevel@tonic-gate 					    0
6707c478bd9Sstevel@tonic-gate #else
6717c478bd9Sstevel@tonic-gate 					    tsbp->tte_data.tte_glb
6727c478bd9Sstevel@tonic-gate #endif
6737c478bd9Sstevel@tonic-gate 					    /*CSTYLED*/
6747c478bd9Sstevel@tonic-gate 					    );
6757c478bd9Sstevel@tonic-gate 				}
6767c478bd9Sstevel@tonic-gate 			}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 			mdb_printf("\n"); /* blank line for readability */
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 			mdb_free(tsbstart, sizeof (struct tsbe) * entries);
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 		} else {
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 			mdb_printf("TSB swapped out\n");
6857c478bd9Sstevel@tonic-gate 		}
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
6897c478bd9Sstevel@tonic-gate }
690