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