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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 31 #ifndef DEBUG 32 #define DEBUG 33 #define _SYS_DEBUG_H 34 #include <sys/xc_impl.h> 35 #undef DEBUG 36 #else 37 #define _SYS_DEBUG_H 38 #include <sys/xc_impl.h> 39 #endif 40 41 #include <sys/traptrace.h> 42 #include <sys/machparam.h> 43 #include <sys/ivintr.h> 44 #include <sys/mutex_impl.h> 45 46 #include <mdb/mdb_modapi.h> 47 #include <mdb/mdb_ctf.h> 48 #include "sfmmu.h" 49 50 #ifndef SYSTRAP_TT 51 #define SYSTRAP_TT 0x1300 52 #endif 53 54 typedef struct trap_trace_fullrec { 55 struct trap_trace_record ttf_rec; 56 int ttf_cpu; 57 } trap_trace_fullrec_t; 58 59 #ifdef sun4v 60 typedef struct htrap_trace_fullrec { 61 struct htrap_trace_record ttf_rec; 62 int ttf_cpu; 63 } htrap_trace_fullrec_t; 64 #endif 65 66 /* 67 * These strings and accompanying macros allow our string table to look 68 * just like the real table in trap_table.s. 69 */ 70 71 static const char NOT[] = "reserved"; /* common reserved string */ 72 static const char BAD[] = "unused"; /* common unused string */ 73 74 #define NOT4 NOT, NOT, NOT, NOT 75 #define BAD4 BAD, BAD, BAD, BAD 76 77 static const char *const ttdescr[] = { 78 NOT, /* 000 reserved */ 79 "power-on", /* 001 power on reset */ 80 "watchdog", /* 002 watchdog reset */ 81 "xir", /* 003 externally initiated reset */ 82 "sir", /* 004 software initiated reset */ 83 "red", /* 005 red mode exception */ 84 NOT, NOT, /* 006 - 007 reserved */ 85 "immu-xcp", /* 008 instruction access exception */ 86 "immu-miss", /* 009 instruction access MMU miss */ 87 "immu-err", /* 00A instruction access error */ 88 NOT, NOT4, /* 00B - 00F reserved */ 89 "ill-inst", /* 010 illegal instruction */ 90 "priv-inst", /* 011 privileged opcode */ 91 "unimp-ldd", /* 012 unimplemented LDD */ 92 "unimp-std", /* 013 unimplemented STD */ 93 NOT4, NOT4, NOT4, /* 014 - 01F reserved */ 94 "fp-disable", /* 020 fp disabled */ 95 "fp-ieee754", /* 021 fp exception ieee 754 */ 96 "fp-xcp-other", /* 022 fp exception other */ 97 "tag-oflow", /* 023 tag overflow */ 98 "cleanwin", /* 024 clean window */ 99 "cleanwin", /* 025 clean window */ 100 "cleanwin", /* 026 clean window */ 101 "cleanwin", /* 027 clean window */ 102 "div-zero", /* 028 division by zero */ 103 "internal-err", /* 029 internal processor error */ 104 NOT, NOT, NOT4, /* 02A - 02F reserved */ 105 "dmmu-xcp", /* 030 data access exception */ 106 "dmmu-miss", /* 031 data access MMU miss */ 107 "dmmu-err", /* 032 data access error */ 108 "dmmu-prot", /* 033 data access protection */ 109 "unalign", /* 034 mem address not aligned */ 110 "lddf-unalign", /* 035 LDDF mem address not aligned */ 111 "stdf-unalign", /* 036 STDF mem address not aligned */ 112 "priv-act", /* 037 privileged action */ 113 "ldqf-unalign", /* 038 LDQF mem address not aligned */ 114 "stqf-unalign", /* 039 STQF mem address not aligned */ 115 NOT, NOT, NOT4, /* 03A - 03F reserved */ 116 "async-d-err", /* 040 async data error */ 117 "level-1", /* 041 interrupt level 1 */ 118 "level-2", /* 042 interrupt level 2 */ 119 "level-3", /* 043 interrupt level 3 */ 120 "level-4", /* 044 interrupt level 4 */ 121 "level-5", /* 045 interrupt level 5 */ 122 "level-6", /* 046 interrupt level 6 */ 123 "level-7", /* 047 interrupt level 7 */ 124 "level-8", /* 048 interrupt level 8 */ 125 "level-9", /* 049 interrupt level 9 */ 126 "level-10", /* 04A interrupt level 10 */ 127 "level-11", /* 04B interrupt level 11 */ 128 "level-12", /* 04C interrupt level 12 */ 129 "level-13", /* 04D interrupt level 13 */ 130 "level-14", /* 04E interrupt level 14 */ 131 "level-15", /* 04F interrupt level 15 */ 132 NOT4, NOT4, NOT4, NOT4, /* 050 - 05F reserved */ 133 "int-vec", /* 060 interrupt vector */ 134 "pa-watch", /* 061 PA watchpoint */ 135 "va-watch", /* 062 VA watchpoint */ 136 "ecc-err", /* 063 corrected ECC error */ 137 "itlb-miss", /* 064 instruction access MMU miss */ 138 "itlb-miss", /* 065 instruction access MMU miss */ 139 "itlb-miss", /* 066 instruction access MMU miss */ 140 "itlb-miss", /* 067 instruction access MMU miss */ 141 "dtlb-miss", /* 068 data access MMU miss */ 142 "dtlb-miss", /* 069 data access MMU miss */ 143 "dtlb-miss", /* 06A data access MMU miss */ 144 "dtlb-miss", /* 06B data access MMU miss */ 145 "dtlb-prot", /* 06C data access protection */ 146 "dtlb-prot", /* 06D data access protection */ 147 "dtlb-prot", /* 06E data access protection */ 148 "dtlb-prot", /* 06F data access protection */ 149 "fast-ecc-err", /* 070 fast ecache ECC error */ 150 "dp-err", /* 071 data cache parity error */ 151 "ip-err", /* 072 instr cache parity error */ 152 NOT, NOT4, NOT4, /* 073 - 07B reserved */ 153 #ifdef sun4v 154 "cpu-mondo", /* 07C CPU mondo */ 155 "dev-mondo", /* 07D device mondo */ 156 "res.-err", /* 07E resumable error */ 157 "non-res.-err", /* 07F non-resumable error */ 158 #else 159 NOT4, /* 07C - 07F reserved */ 160 #endif 161 "spill-0-norm", /* 080 spill 0 normal */ 162 "spill-0-norm", /* 081 spill 0 normal */ 163 "spill-0-norm", /* 082 spill 0 normal */ 164 "spill-0-norm", /* 083 spill 0 normal */ 165 "spill-1-norm", /* 084 spill 1 normal */ 166 "spill-1-norm", /* 085 spill 1 normal */ 167 "spill-1-norm", /* 086 spill 1 normal */ 168 "spill-1-norm", /* 087 spill 1 normal */ 169 "spill-2-norm", /* 088 spill 2 normal */ 170 "spill-2-norm", /* 089 spill 2 normal */ 171 "spill-2-norm", /* 08A spill 2 normal */ 172 "spill-2-norm", /* 08B spill 2 normal */ 173 "spill-3-norm", /* 08C spill 3 normal */ 174 "spill-3-norm", /* 08D spill 3 normal */ 175 "spill-3-norm", /* 08E spill 3 normal */ 176 "spill-3-norm", /* 08F spill 3 normal */ 177 "spill-4-norm", /* 090 spill 4 normal */ 178 "spill-4-norm", /* 091 spill 4 normal */ 179 "spill-4-norm", /* 092 spill 4 normal */ 180 "spill-4-norm", /* 093 spill 4 normal */ 181 "spill-5-norm", /* 094 spill 5 normal */ 182 "spill-5-norm", /* 095 spill 5 normal */ 183 "spill-5-norm", /* 096 spill 5 normal */ 184 "spill-5-norm", /* 097 spill 5 normal */ 185 "spill-6-norm", /* 098 spill 6 normal */ 186 "spill-6-norm", /* 099 spill 6 normal */ 187 "spill-6-norm", /* 09A spill 6 normal */ 188 "spill-6-norm", /* 09B spill 6 normal */ 189 "spill-7-norm", /* 09C spill 7 normal */ 190 "spill-7-norm", /* 09D spill 7 normal */ 191 "spill-7-norm", /* 09E spill 7 normal */ 192 "spill-7-norm", /* 09F spill 7 normal */ 193 "spill-0-oth", /* 0A0 spill 0 other */ 194 "spill-0-oth", /* 0A1 spill 0 other */ 195 "spill-0-oth", /* 0A2 spill 0 other */ 196 "spill-0-oth", /* 0A3 spill 0 other */ 197 "spill-1-oth", /* 0A4 spill 1 other */ 198 "spill-1-oth", /* 0A5 spill 1 other */ 199 "spill-1-oth", /* 0A6 spill 1 other */ 200 "spill-1-oth", /* 0A7 spill 1 other */ 201 "spill-2-oth", /* 0A8 spill 2 other */ 202 "spill-2-oth", /* 0A9 spill 2 other */ 203 "spill-2-oth", /* 0AA spill 2 other */ 204 "spill-2-oth", /* 0AB spill 2 other */ 205 "spill-3-oth", /* 0AC spill 3 other */ 206 "spill-3-oth", /* 0AD spill 3 other */ 207 "spill-3-oth", /* 0AE spill 3 other */ 208 "spill-3-oth", /* 0AF spill 3 other */ 209 "spill-4-oth", /* 0B0 spill 4 other */ 210 "spill-4-oth", /* 0B1 spill 4 other */ 211 "spill-4-oth", /* 0B2 spill 4 other */ 212 "spill-4-oth", /* 0B3 spill 4 other */ 213 "spill-5-oth", /* 0B4 spill 5 other */ 214 "spill-5-oth", /* 0B5 spill 5 other */ 215 "spill-5-oth", /* 0B6 spill 5 other */ 216 "spill-5-oth", /* 0B7 spill 5 other */ 217 "spill-6-oth", /* 0B8 spill 6 other */ 218 "spill-6-oth", /* 0B9 spill 6 other */ 219 "spill-6-oth", /* 0BA spill 6 other */ 220 "spill-6-oth", /* 0BB spill 6 other */ 221 "spill-7-oth", /* 0BC spill 7 other */ 222 "spill-7-oth", /* 0BD spill 7 other */ 223 "spill-7-oth", /* 0BE spill 7 other */ 224 "spill-7-oth", /* 0BF spill 7 other */ 225 "fill-0-norm", /* 0C0 fill 0 normal */ 226 "fill-0-norm", /* 0C1 fill 0 normal */ 227 "fill-0-norm", /* 0C2 fill 0 normal */ 228 "fill-0-norm", /* 0C3 fill 0 normal */ 229 "fill-1-norm", /* 0C4 fill 1 normal */ 230 "fill-1-norm", /* 0C5 fill 1 normal */ 231 "fill-1-norm", /* 0C6 fill 1 normal */ 232 "fill-1-norm", /* 0C7 fill 1 normal */ 233 "fill-2-norm", /* 0C8 fill 2 normal */ 234 "fill-2-norm", /* 0C9 fill 2 normal */ 235 "fill-2-norm", /* 0CA fill 2 normal */ 236 "fill-2-norm", /* 0CB fill 2 normal */ 237 "fill-3-norm", /* 0CC fill 3 normal */ 238 "fill-3-norm", /* 0CD fill 3 normal */ 239 "fill-3-norm", /* 0CE fill 3 normal */ 240 "fill-3-norm", /* 0CF fill 3 normal */ 241 "fill-4-norm", /* 0D0 fill 4 normal */ 242 "fill-4-norm", /* 0D1 fill 4 normal */ 243 "fill-4-norm", /* 0D2 fill 4 normal */ 244 "fill-4-norm", /* 0D3 fill 4 normal */ 245 "fill-5-norm", /* 0D4 fill 5 normal */ 246 "fill-5-norm", /* 0D5 fill 5 normal */ 247 "fill-5-norm", /* 0D6 fill 5 normal */ 248 "fill-5-norm", /* 0D7 fill 5 normal */ 249 "fill-6-norm", /* 0D8 fill 6 normal */ 250 "fill-6-norm", /* 0D9 fill 6 normal */ 251 "fill-6-norm", /* 0DA fill 6 normal */ 252 "fill-6-norm", /* 0DB fill 6 normal */ 253 "fill-7-norm", /* 0DC fill 7 normal */ 254 "fill-7-norm", /* 0DD fill 7 normal */ 255 "fill-7-norm", /* 0DE fill 7 normal */ 256 "fill-7-norm", /* 0DF fill 7 normal */ 257 "fill-0-oth", /* 0E0 fill 0 other */ 258 "fill-0-oth", /* 0E1 fill 0 other */ 259 "fill-0-oth", /* 0E2 fill 0 other */ 260 "fill-0-oth", /* 0E3 fill 0 other */ 261 "fill-1-oth", /* 0E4 fill 1 other */ 262 "fill-1-oth", /* 0E5 fill 1 other */ 263 "fill-1-oth", /* 0E6 fill 1 other */ 264 "fill-1-oth", /* 0E7 fill 1 other */ 265 "fill-2-oth", /* 0E8 fill 2 other */ 266 "fill-2-oth", /* 0E9 fill 2 other */ 267 "fill-2-oth", /* 0EA fill 2 other */ 268 "fill-2-oth", /* 0EB fill 2 other */ 269 "fill-3-oth", /* 0EC fill 3 other */ 270 "fill-3-oth", /* 0ED fill 3 other */ 271 "fill-3-oth", /* 0EE fill 3 other */ 272 "fill-3-oth", /* 0EF fill 3 other */ 273 "fill-4-oth", /* 0F0 fill 4 other */ 274 "fill-4-oth", /* 0F1 fill 4 other */ 275 "fill-4-oth", /* 0F2 fill 4 other */ 276 "fill-4-oth", /* 0F3 fill 4 other */ 277 "fill-5-oth", /* 0F4 fill 5 other */ 278 "fill-5-oth", /* 0F5 fill 5 other */ 279 "fill-5-oth", /* 0F6 fill 5 other */ 280 "fill-5-oth", /* 0F7 fill 5 other */ 281 "fill-6-oth", /* 0F8 fill 6 other */ 282 "fill-6-oth", /* 0F9 fill 6 other */ 283 "fill-6-oth", /* 0FA fill 6 other */ 284 "fill-6-oth", /* 0FB fill 6 other */ 285 "fill-7-oth", /* 0FC fill 7 other */ 286 "fill-7-oth", /* 0FD fill 7 other */ 287 "fill-7-oth", /* 0FE fill 7 other */ 288 "fill-7-oth", /* 0FF fill 7 other */ 289 "syscall-4x", /* 100 old system call */ 290 "usr-brkpt", /* 101 user breakpoint */ 291 "usr-div-zero", /* 102 user divide by zero */ 292 "flush-wins", /* 103 flush windows */ 293 "clean-wins", /* 104 clean windows */ 294 "range-chk", /* 105 range check ?? */ 295 "fix-align", /* 106 do unaligned references */ 296 BAD, /* 107 unused */ 297 "syscall-32", /* 108 ILP32 system call on LP64 */ 298 "set-t0-addr", /* 109 set trap0 address */ 299 BAD, BAD, BAD4, /* 10A - 10F unused */ 300 BAD4, BAD4, BAD4, BAD4, /* 110 - 11F unused (V9 user traps?) */ 301 "get-cc", /* 120 get condition codes */ 302 "set-cc", /* 121 set condition codes */ 303 "get-psr", /* 122 get psr */ 304 "set-psr", /* 123 set psr (some fields) */ 305 "getts", /* 124 get timestamp */ 306 "gethrvtime", /* 125 get lwp virtual time */ 307 "self-xcall", /* 126 self xcall */ 308 "gethrtime", /* 127 get hrestime */ 309 BAD, /* 128 unused (ST_SETV9STACK) */ 310 "getlgrp", /* 129 get lgrpid */ 311 BAD, BAD, BAD4, /* 12A - 12F unused */ 312 BAD4, BAD4, /* 130 - 137 unused */ 313 "dtrace-pid", /* 138 DTrace pid provider */ 314 "dtrace-fasttrap", /* 139 DTrace pid provider */ 315 "dtrace-return", /* 13A DTrace pid provider */ 316 BAD, BAD4, /* 13B - 13F unused */ 317 "syscall-64", /* 140 LP64 system call */ 318 BAD, /* 141 unused */ 319 "tt-freeze", /* 142 freeze traptrace */ 320 "tt-unfreeze", /* 143 unfreeze traptrace */ 321 BAD4, BAD4, BAD4, /* 144 - 14F unused */ 322 BAD4, BAD4, BAD4, BAD4, /* 150 - 15F unused */ 323 BAD4, BAD4, BAD4, BAD4, /* 160 - 16F unused */ 324 BAD4, BAD4, BAD4, /* 170 - 17B unused */ 325 "ptl1-panic", /* 17C test ptl1_panic */ 326 "kmdb-enter", /* 17D kmdb enter (L1-A) */ 327 "kmdb-brkpt", /* 17E kmdb breakpoint */ 328 "obp-brkpt", /* 17F obp breakpoint */ 329 #ifdef sun4v 330 "fast_trap", /* 180 hypervisor fast trap */ 331 "cpu_tick_npt", /* 181 cpu_tick_npt() hcall */ 332 "cpu_stick_npt", /* 182 cpu_stick_npt() hcall */ 333 "mmu_map_addr", /* 183 mmu_map_addr() hcall */ 334 "mmu_unmap_addr", /* 184 mmu_unmap_addr() hcall */ 335 "ttrace_addentry", /* 185 ttrace_addentry() hcall */ 336 NOT, NOT, NOT4, NOT4, /* 186 - 18F reserved */ 337 #else 338 NOT4, NOT4, NOT4, NOT4, /* 180 - 18F reserved */ 339 #endif 340 NOT4, NOT4, NOT4, NOT4, /* 190 - 19F reserved */ 341 NOT4, NOT4, NOT4, NOT4, /* 1A0 - 1AF reserved */ 342 NOT4, NOT4, NOT4, NOT4, /* 1B0 - 1BF reserved */ 343 NOT4, NOT4, NOT4, NOT4, /* 1C0 - 1CF reserved */ 344 NOT4, NOT4, NOT4, NOT4, /* 1D0 - 1DF reserved */ 345 NOT4, NOT4, NOT4, NOT4, /* 1E0 - 1EF reserved */ 346 NOT4, NOT4, NOT4, NOT4 /* 1F0 - 1FF reserved */ 347 }; 348 static const size_t ttndescr = sizeof (ttdescr) / sizeof (ttdescr[0]); 349 350 static GElf_Sym iv_sym; 351 static GElf_Sym iv_nohandler_sym; 352 353 /* 354 * Persistent data (shouldn't change). 355 */ 356 static int ncpu; /* _ncpu */ 357 static ssize_t mbox_size; /* size of xc_mbox */ 358 static ulong_t mbox_stoff; /* offset of xc_mbox.xc_state */ 359 static mdb_ctf_id_t mbox_states; /* xc_state enumeration */ 360 361 static int 362 fetch_ncpu(void) 363 { 364 if (ncpu == 0) 365 if (mdb_readsym(&ncpu, sizeof (ncpu), "_ncpu") == -1) { 366 mdb_warn("symbol '_ncpu' not found"); 367 return (1); 368 } 369 return (0); 370 } 371 372 static int 373 fetch_mbox(void) 374 { 375 if (mbox_size <= 0) { 376 mdb_ctf_id_t id; 377 378 if (mdb_ctf_lookup_by_name("struct xc_mbox", &id) == -1) { 379 mdb_warn("couldn't find type 'struct xc_mbox'"); 380 return (1); 381 } 382 383 /* 384 * These two could be combined into a single call to 385 * mdb_ctf_member_info if xc_state was actually of type 386 * enum xc_states. 387 */ 388 if (mdb_ctf_lookup_by_name("enum xc_states", 389 &mbox_states) == -1) { 390 mdb_warn("couldn't find type 'enum xc_states'"); 391 return (1); 392 } 393 if (mdb_ctf_offsetof(id, "xc_state", &mbox_stoff) == -1) { 394 mdb_warn("couldn't find 'xc_mbox.xc_state'"); 395 return (1); 396 } 397 mbox_stoff /= NBBY; 398 399 if ((mbox_size = mdb_ctf_type_size(id)) == -1) { 400 mdb_warn("couldn't size 'struct xc_mbox'"); 401 return (1); 402 } 403 } 404 return (0); 405 } 406 407 static int 408 print_range(int start, int end, int separator) 409 { 410 int count; 411 char tmp; 412 char *format; 413 414 if (start == end) { 415 /* Unfortunately, mdb_printf returns void */ 416 format = separator ? ", %d" : "%d"; 417 mdb_printf(format, start); 418 count = mdb_snprintf(&tmp, 1, format, start); 419 } else { 420 format = separator ? ", %d-%d" : "%d-%d"; 421 mdb_printf(format, start, end); 422 count = mdb_snprintf(&tmp, 1, format, start, end); 423 } 424 425 return (count); 426 } 427 428 static void 429 print_cpuset_range(ulong_t *cs, int words, int width) 430 { 431 int i, j; 432 ulong_t m; 433 int in = 0; 434 int start; 435 int end; 436 int count = 0; 437 int sep = 0; 438 439 for (i = 0; i < words; i++) 440 for (j = 0, m = 1; j < BT_NBIPUL; j++, m <<= 1) 441 if (cs[i] & m) { 442 if (in == 0) { 443 start = i * BT_NBIPUL + j; 444 in = 1; 445 } 446 } else { 447 if (in == 1) { 448 end = i * BT_NBIPUL + j - 1; 449 count += print_range(start, end, sep); 450 sep = 1; 451 in = 0; 452 } 453 } 454 if (in == 1) { 455 end = i * BT_NBIPUL - 1; 456 count += print_range(start, end, sep); 457 } 458 459 while (count++ < width) 460 mdb_printf(" "); 461 } 462 463 /*ARGSUSED*/ 464 static int 465 cmd_cpuset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 466 { 467 uint_t rflag = 0, lflag = 0; 468 int words; 469 ulong_t *set; 470 471 if (mdb_getopts(argc, argv, 472 'l', MDB_OPT_SETBITS, TRUE, &lflag, 473 'r', MDB_OPT_SETBITS, TRUE, &rflag, NULL) != argc) 474 return (DCMD_USAGE); 475 476 if (lflag && rflag) 477 return (DCMD_USAGE); 478 479 if (fetch_ncpu()) 480 return (DCMD_ERR); 481 482 if ((words = BT_BITOUL(ncpu)) == 1) { 483 set = &addr; 484 } else { 485 set = mdb_alloc(words * sizeof (ulong_t), UM_SLEEP | UM_GC); 486 mdb_vread(set, words * sizeof (ulong_t), addr); 487 } 488 489 if (lflag) { 490 int i, j; 491 ulong_t m; 492 493 for (i = 0; i < words; i++) 494 for (j = 0, m = 1; j < BT_NBIPUL; j++, m <<= 1) 495 if (set[i] & m) 496 mdb_printf("%r\n", i * BT_NBIPUL + j); 497 } else if (rflag) { 498 int i; 499 int sep = 0; 500 501 for (i = 0; i < words; i++) { 502 mdb_printf(sep ? " %?0lx" : "%?0lx", set[i]); 503 sep = 1; 504 } 505 } else { 506 print_cpuset_range(set, words, 0); 507 } 508 509 return (DCMD_OK); 510 } 511 512 /*ARGSUSED*/ 513 int 514 ttctl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 515 { 516 TRAP_TRACE_CTL *ctls, *ctl; 517 int i; 518 519 if (argc != 0) 520 return (DCMD_USAGE); 521 522 if (fetch_ncpu()) 523 return (DCMD_ERR); 524 525 ctls = mdb_alloc(sizeof (TRAP_TRACE_CTL) * ncpu, UM_SLEEP | UM_GC); 526 if (mdb_readsym(ctls, sizeof (TRAP_TRACE_CTL) * ncpu, 527 "trap_trace_ctl") == -1) { 528 mdb_warn("symbol 'trap_trace_ctl' not found"); 529 return (DCMD_ERR); 530 } 531 532 for (ctl = &ctls[0], i = 0; i < ncpu; i++, ctl++) { 533 if (ctl->d.vaddr_base == 0) 534 continue; 535 536 mdb_printf("trap_trace_ctl[%d] = {\n", i); 537 mdb_printf(" vaddr_base = 0x%lx\n", (long)ctl->d.vaddr_base); 538 mdb_printf(" last_offset = 0x%x\n", ctl->d.last_offset); 539 mdb_printf(" offset = 0x%x\n", ctl->d.offset); 540 mdb_printf(" limit = 0x%x\n", ctl->d.limit); 541 mdb_printf(" paddr_base = 0x%llx\n", ctl->d.paddr_base); 542 mdb_printf(" asi = 0x%02x\n}\n", ctl->d.asi); 543 } 544 545 return (DCMD_OK); 546 } 547 548 /*ARGSUSED*/ 549 static int 550 ttprint_short(uintptr_t addr, const trap_trace_fullrec_t *full, int *cpu) 551 { 552 const char *ttstr; 553 const struct trap_trace_record *ttp = &full->ttf_rec; 554 555 if (*cpu == -1) 556 mdb_printf("%3d ", full->ttf_cpu); 557 else 558 if (*cpu != full->ttf_cpu) 559 return (0); 560 561 /* 562 * Decoding the traptype field is a bit messy. First we check for 563 * several well-defined 16-bit values defined in <sys/traptrace.h>. 564 */ 565 switch (ttp->tt_tt) { 566 case TT_SC_ENTR: 567 ttstr = "sys-enter"; 568 break; 569 case TT_SC_RET: 570 ttstr = "sys-exit"; 571 break; 572 case TT_SYS_RTT_PROM: 573 ttstr = "prom_rtt"; 574 break; 575 case TT_SYS_RTT_PRIV: 576 ttstr = "priv_rtt"; 577 break; 578 case TT_SYS_RTT_USER: 579 ttstr = "user_rtt"; 580 break; 581 case TT_INTR_EXIT: 582 ttstr = "int-thr-exit"; 583 break; 584 default: 585 /* 586 * Next we consider several prefixes (which are 587 * typically OR'd with other information such as the 588 * %pil or %tt value at the time of the trace). 589 */ 590 switch (ttp->tt_tt & 0xff00) { 591 case TT_SERVE_INTR: 592 ttstr = "serve-intr"; 593 break; 594 case TT_XCALL: 595 ttstr = "xcall"; 596 break; 597 case TT_XCALL_CONT: 598 ttstr = "xcall-cont"; 599 break; 600 case SYSTRAP_TT: 601 ttstr = "sys_trap"; 602 break; 603 default: 604 /* 605 * Otherwise we try to convert the 606 * tt value to a string using our 607 * giant lookup table. 608 */ 609 ttstr = ttp->tt_tt < ttndescr ? 610 ttdescr[ttp->tt_tt] : "?"; 611 } 612 } 613 614 #ifdef sun4v 615 mdb_printf("%016llx %04hx %-12s %02x %02x %0?p %A\n", ttp->tt_tick, 616 ttp->tt_tt, ttstr, ttp->tt_tl, ttp->tt_gl, 617 ttp->tt_tpc, ttp->tt_tpc); 618 #else 619 mdb_printf("%016llx %04hx %-12s %04hx %0?p %A\n", ttp->tt_tick, 620 ttp->tt_tt, ttstr, ttp->tt_tl, ttp->tt_tpc, ttp->tt_tpc); 621 #endif 622 623 return (WALK_NEXT); 624 } 625 626 /*ARGSUSED*/ 627 static int 628 ttprint_long(uintptr_t addr, const trap_trace_fullrec_t *full, int *cpu) 629 { 630 const struct trap_trace_record *ttp = &full->ttf_rec; 631 632 if (*cpu == -1) 633 mdb_printf("%3d ", full->ttf_cpu); 634 else if (*cpu != full->ttf_cpu) 635 return (WALK_NEXT); 636 637 #ifdef sun4v 638 mdb_printf("%016llx %016llx %04hx %02x %02x %0?p %0?p %0?p " 639 "[%p,%p,%p,%p]\n", 640 ttp->tt_tick, ttp->tt_tstate, ttp->tt_tt, ttp->tt_tl, ttp->tt_gl, 641 ttp->tt_tpc, ttp->tt_sp, ttp->tt_tr, 642 ttp->tt_f1, ttp->tt_f2, ttp->tt_f3, ttp->tt_f4); 643 #else 644 mdb_printf("%016llx %016llx %04hx %04hx %0?p %0?p %0?p [%p,%p,%p,%p]\n", 645 ttp->tt_tick, ttp->tt_tstate, ttp->tt_tt, ttp->tt_tl, 646 ttp->tt_tpc, ttp->tt_sp, ttp->tt_tr, 647 ttp->tt_f1, ttp->tt_f2, ttp->tt_f3, ttp->tt_f4); 648 #endif 649 650 return (WALK_NEXT); 651 } 652 653 typedef struct ttrace_cpu_data { 654 struct trap_trace_record *tc_buf; 655 struct trap_trace_record *tc_rec; 656 struct trap_trace_record *tc_stop; 657 size_t tc_bufsiz; 658 uintptr_t tc_base; 659 } ttrace_cpu_data_t; 660 661 typedef struct ttrace_walk_data { 662 int tw_ncpu; 663 ttrace_cpu_data_t *tw_cpus; 664 } ttrace_walk_data_t; 665 666 int 667 ttrace_walk_init(mdb_walk_state_t *wsp) 668 { 669 TRAP_TRACE_CTL *ctls, *ctl; 670 int i; 671 ttrace_walk_data_t *tw; 672 ttrace_cpu_data_t *tc; 673 struct trap_trace_record *buf; 674 675 if (wsp->walk_addr != NULL) { 676 mdb_warn("ttrace only supports global walks\n"); 677 return (WALK_ERR); 678 } 679 680 if (fetch_ncpu()) 681 return (WALK_ERR); 682 683 ctls = mdb_alloc(sizeof (TRAP_TRACE_CTL) * ncpu, UM_SLEEP); 684 if (mdb_readsym(ctls, sizeof (TRAP_TRACE_CTL) * ncpu, 685 "trap_trace_ctl") == -1) { 686 mdb_warn("symbol 'trap_trace_ctl' not found"); 687 mdb_free(ctls, sizeof (TRAP_TRACE_CTL) * ncpu); 688 return (WALK_ERR); 689 } 690 691 tw = mdb_zalloc(sizeof (ttrace_walk_data_t), UM_SLEEP); 692 tw->tw_ncpu = ncpu; 693 tw->tw_cpus = mdb_zalloc(sizeof (ttrace_cpu_data_t) * ncpu, UM_SLEEP); 694 695 for (i = 0; i < ncpu; i++) { 696 ctl = &ctls[i]; 697 698 if (ctl->d.vaddr_base == 0) 699 continue; 700 701 tc = &(tw->tw_cpus[i]); 702 tc->tc_bufsiz = ctl->d.limit - 703 sizeof (struct trap_trace_record); 704 tc->tc_buf = buf = mdb_alloc(tc->tc_bufsiz, UM_SLEEP); 705 tc->tc_base = (uintptr_t)ctl->d.vaddr_base; 706 707 if (mdb_vread(buf, tc->tc_bufsiz, tc->tc_base) == -1) { 708 mdb_warn("failed to read trap trace buffer at %p", 709 ctl->d.vaddr_base); 710 mdb_free(buf, tc->tc_bufsiz); 711 tc->tc_buf = NULL; 712 } else { 713 tc->tc_rec = (struct trap_trace_record *) 714 ((uintptr_t)buf + (uintptr_t)ctl->d.last_offset); 715 tc->tc_stop = (struct trap_trace_record *) 716 ((uintptr_t)buf + (uintptr_t)ctl->d.offset); 717 } 718 } 719 720 mdb_free(ctls, sizeof (TRAP_TRACE_CTL) * ncpu); 721 wsp->walk_data = tw; 722 return (WALK_NEXT); 723 } 724 725 int 726 ttrace_walk_step(mdb_walk_state_t *wsp) 727 { 728 ttrace_walk_data_t *tw = wsp->walk_data; 729 ttrace_cpu_data_t *tc; 730 struct trap_trace_record *rec; 731 int oldest, i, status; 732 uint64_t oldest_tick = 0; 733 int done = 1; 734 trap_trace_fullrec_t fullrec; 735 736 for (i = 0; i < tw->tw_ncpu; i++) { 737 tc = &(tw->tw_cpus[i]); 738 739 if (tc->tc_rec == NULL) 740 continue; 741 done = 0; 742 743 if (tc->tc_rec->tt_tick == 0) 744 mdb_warn("Warning: tt_tick == 0\n"); 745 746 if (tc->tc_rec->tt_tick > oldest_tick) { 747 oldest_tick = tc->tc_rec->tt_tick; 748 oldest = i; 749 } 750 } 751 752 if (done) 753 return (-1); 754 755 tc = &(tw->tw_cpus[oldest]); 756 rec = tc->tc_rec; 757 758 fullrec.ttf_rec = *rec; 759 fullrec.ttf_cpu = oldest; 760 761 if (oldest_tick != 0) 762 status = wsp->walk_callback((uintptr_t)rec - 763 (uintptr_t)tc->tc_buf + tc->tc_base, &fullrec, 764 wsp->walk_cbdata); 765 766 tc->tc_rec--; 767 768 if (tc->tc_rec < tc->tc_buf) 769 tc->tc_rec = (struct trap_trace_record *)((uintptr_t) 770 tc->tc_buf + (uintptr_t)tc->tc_bufsiz - 771 sizeof (struct trap_trace_record)); 772 773 if (tc->tc_rec == tc->tc_stop) { 774 tc->tc_rec = NULL; 775 mdb_free(tc->tc_buf, tc->tc_bufsiz); 776 } 777 778 return (status); 779 } 780 781 void 782 ttrace_walk_fini(mdb_walk_state_t *wsp) 783 { 784 ttrace_walk_data_t *tw = wsp->walk_data; 785 786 mdb_free(tw->tw_cpus, sizeof (ttrace_cpu_data_t) * tw->tw_ncpu); 787 mdb_free(tw, sizeof (ttrace_walk_data_t)); 788 } 789 790 int 791 ttrace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 792 { 793 uint_t opt_x = FALSE; 794 int cpu = -1; 795 mdb_walk_cb_t ttprint; 796 797 if (mdb_getopts(argc, argv, 798 'x', MDB_OPT_SETBITS, TRUE, &opt_x, NULL) != argc) 799 return (DCMD_USAGE); 800 801 if (flags & DCMD_ADDRSPEC) { 802 if (fetch_ncpu()) 803 return (DCMD_ERR); 804 if (addr >= ncpu) { 805 mdb_warn("expected cpu between 0 and %d\n", ncpu - 1); 806 return (DCMD_ERR); 807 } 808 cpu = (int)addr; 809 } 810 811 if (cpu == -1) 812 mdb_printf("CPU "); 813 814 if (opt_x) { 815 #ifdef sun4v 816 mdb_printf("%-16s %-16s %-4s %-3s %-3s %-?s %-?s %-?s " 817 "F1-4\n", "%tick", "%tstate", "%tt", "%tl", "%gl", 818 "%tpc", "%sp", "TR"); 819 #else 820 mdb_printf("%-16s %-16s %-4s %-4s %-?s %-?s %-?s " 821 "F1-4\n", "%tick", "%tstate", "%tt", "%tl", 822 "%tpc", "%sp", "TR"); 823 #endif 824 825 ttprint = (mdb_walk_cb_t)ttprint_long; 826 } else { 827 #ifdef sun4v 828 mdb_printf("%-16s %-4s %-12s %-3s %-3s %s\n", 829 "%tick", "%tt", "", "%tl", "%gl", "%tpc"); 830 #else 831 mdb_printf("%-16s %-4s %-12s %-4s %s\n", 832 "%tick", "%tt", "", "%tl", "%tpc"); 833 #endif 834 835 ttprint = (mdb_walk_cb_t)ttprint_short; 836 } 837 838 if (mdb_walk("ttrace", ttprint, &cpu) == -1) { 839 mdb_warn("couldn't walk ttrace"); 840 return (DCMD_ERR); 841 } 842 843 return (DCMD_OK); 844 } 845 846 #ifdef sun4v 847 /*ARGSUSED*/ 848 int 849 httctl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 850 { 851 TRAP_TRACE_CTL *ctls, *ctl; 852 int i; 853 htrap_trace_hdr_t hdr; 854 855 if (argc != 0) 856 return (DCMD_USAGE); 857 858 if (fetch_ncpu()) 859 return (DCMD_ERR); 860 861 ctls = mdb_alloc(sizeof (TRAP_TRACE_CTL) * ncpu, UM_SLEEP | UM_GC); 862 if (mdb_readsym(ctls, sizeof (TRAP_TRACE_CTL) * ncpu, 863 "trap_trace_ctl") == -1) { 864 mdb_warn("symbol 'trap_trace_ctl' not found"); 865 return (DCMD_ERR); 866 } 867 868 for (ctl = &ctls[0], i = 0; i < ncpu; i++, ctl++) { 869 if (ctl->d.hvaddr_base == 0) 870 continue; 871 872 mdb_vread(&hdr, sizeof (htrap_trace_hdr_t), 873 (uintptr_t)ctl->d.hvaddr_base); 874 mdb_printf("htrap_trace_ctl[%d] = {\n", i); 875 mdb_printf(" vaddr_base = 0x%lx\n", (long)ctl->d.hvaddr_base); 876 mdb_printf(" last_offset = 0x%lx\n", hdr.last_offset); 877 mdb_printf(" offset = 0x%lx\n", hdr.offset); 878 mdb_printf(" limit = 0x%x\n", ctl->d.hlimit); 879 mdb_printf(" paddr_base = 0x%llx\n}\n", ctl->d.hpaddr_base); 880 } 881 882 return (DCMD_OK); 883 } 884 885 /*ARGSUSED*/ 886 static int 887 httprint_short(uintptr_t addr, const htrap_trace_fullrec_t *full, int *cpu) 888 { 889 const char *ttstr; 890 const struct htrap_trace_record *ttp = &full->ttf_rec; 891 892 if (*cpu == -1) 893 mdb_printf("%3d ", full->ttf_cpu); 894 else 895 if (*cpu != full->ttf_cpu) 896 return (0); 897 898 /* 899 * Convert the tt value to a string using our gaint lookuo table 900 */ 901 ttstr = ttp->tt_tt < ttndescr ? ttdescr[ttp->tt_tt] : "?"; 902 903 mdb_printf("%016llx %02x %04hx %04hx %-16s %02x %02x %0?p %A\n", 904 ttp->tt_tick, ttp->tt_ty, ttp->tt_tag, ttp->tt_tt, ttstr, 905 ttp->tt_tl, ttp->tt_gl, ttp->tt_tpc, ttp->tt_tpc); 906 907 return (WALK_NEXT); 908 } 909 910 /*ARGSUSED*/ 911 static int 912 httprint_long(uintptr_t addr, const htrap_trace_fullrec_t *full, int *cpu) 913 { 914 const struct htrap_trace_record *ttp = &full->ttf_rec; 915 916 if (*cpu == -1) 917 mdb_printf("%3d ", full->ttf_cpu); 918 else if (*cpu != full->ttf_cpu) 919 return (WALK_NEXT); 920 921 mdb_printf("%016llx %016llx %02x %02x %04hx %04hx %02x %02x %0?p " 922 "[%p,%p,%p,%p]\n", 923 ttp->tt_tick, ttp->tt_tstate, ttp->tt_hpstate, ttp->tt_ty, 924 ttp->tt_tag, ttp->tt_tt, ttp->tt_tl, ttp->tt_gl, ttp->tt_tpc, 925 ttp->tt_f1, ttp->tt_f2, ttp->tt_f3, ttp->tt_f4); 926 927 return (WALK_NEXT); 928 } 929 930 typedef struct httrace_cpu_data { 931 struct htrap_trace_record *tc_buf; 932 struct htrap_trace_record *tc_rec; 933 struct htrap_trace_record *tc_stop; 934 size_t tc_bufsiz; 935 uintptr_t tc_base; 936 } httrace_cpu_data_t; 937 938 typedef struct httrace_walk_data { 939 int tw_ncpu; 940 httrace_cpu_data_t *tw_cpus; 941 } httrace_walk_data_t; 942 943 int 944 httrace_walk_init(mdb_walk_state_t *wsp) 945 { 946 TRAP_TRACE_CTL *ctls, *ctl; 947 int i; 948 httrace_walk_data_t *tw; 949 httrace_cpu_data_t *tc; 950 struct htrap_trace_record *buf; 951 htrap_trace_hdr_t hdr; 952 953 if (wsp->walk_addr != NULL) { 954 mdb_warn("httrace only supports global walks\n"); 955 return (WALK_ERR); 956 } 957 958 if (fetch_ncpu()) 959 return (WALK_ERR); 960 961 ctls = mdb_alloc(sizeof (TRAP_TRACE_CTL) * ncpu, UM_SLEEP); 962 if (mdb_readsym(ctls, sizeof (TRAP_TRACE_CTL) * ncpu, 963 "trap_trace_ctl") == -1) { 964 mdb_warn("symbol 'trap_trace_ctl' not found"); 965 mdb_free(ctls, sizeof (TRAP_TRACE_CTL) * ncpu); 966 return (WALK_ERR); 967 } 968 969 tw = mdb_zalloc(sizeof (httrace_walk_data_t), UM_SLEEP); 970 tw->tw_ncpu = ncpu; 971 tw->tw_cpus = mdb_zalloc(sizeof (httrace_cpu_data_t) * ncpu, UM_SLEEP); 972 973 for (i = 0; i < ncpu; i++) { 974 ctl = &ctls[i]; 975 976 if (ctl->d.hvaddr_base == 0) 977 continue; 978 979 tc = &(tw->tw_cpus[i]); 980 tc->tc_bufsiz = ctl->d.hlimit - 981 sizeof (struct htrap_trace_record); 982 tc->tc_buf = buf = mdb_alloc(tc->tc_bufsiz, UM_SLEEP); 983 tc->tc_base = (uintptr_t)ctl->d.hvaddr_base; 984 985 if (mdb_vread(buf, tc->tc_bufsiz, tc->tc_base) == -1) { 986 mdb_warn("failed to read hv trap trace buffer at %p", 987 ctl->d.hvaddr_base); 988 mdb_free(buf, tc->tc_bufsiz); 989 tc->tc_buf = NULL; 990 } else { 991 mdb_vread(&hdr, sizeof (htrap_trace_hdr_t), 992 (uintptr_t)ctl->d.hvaddr_base); 993 tc->tc_rec = (struct htrap_trace_record *) 994 ((uintptr_t)buf + (uintptr_t)hdr.last_offset); 995 tc->tc_stop = (struct htrap_trace_record *) 996 ((uintptr_t)buf + (uintptr_t)hdr.offset); 997 } 998 } 999 1000 mdb_free(ctls, sizeof (TRAP_TRACE_CTL) * ncpu); 1001 wsp->walk_data = tw; 1002 return (WALK_NEXT); 1003 } 1004 1005 int 1006 httrace_walk_step(mdb_walk_state_t *wsp) 1007 { 1008 httrace_walk_data_t *tw = wsp->walk_data; 1009 httrace_cpu_data_t *tc; 1010 struct htrap_trace_record *rec; 1011 int oldest, i, status; 1012 uint64_t oldest_tick = 0; 1013 int done = 1; 1014 htrap_trace_fullrec_t fullrec; 1015 1016 for (i = 0; i < tw->tw_ncpu; i++) { 1017 tc = &(tw->tw_cpus[i]); 1018 1019 if (tc->tc_rec == NULL) 1020 continue; 1021 done = 0; 1022 1023 if (tc->tc_rec->tt_tick == 0) 1024 mdb_warn("Warning: tt_tick == 0\n"); 1025 1026 if (tc->tc_rec->tt_tick > oldest_tick) { 1027 oldest_tick = tc->tc_rec->tt_tick; 1028 oldest = i; 1029 } 1030 } 1031 1032 if (done) 1033 return (-1); 1034 1035 tc = &(tw->tw_cpus[oldest]); 1036 rec = tc->tc_rec; 1037 1038 fullrec.ttf_rec = *rec; 1039 fullrec.ttf_cpu = oldest; 1040 1041 if (oldest_tick != 0) 1042 status = wsp->walk_callback((uintptr_t)rec - 1043 (uintptr_t)tc->tc_buf + tc->tc_base, &fullrec, 1044 wsp->walk_cbdata); 1045 1046 tc->tc_rec--; 1047 1048 /* first record of the trap trace buffer is trap trace header */ 1049 if (tc->tc_rec == tc->tc_buf) 1050 tc->tc_rec = (struct htrap_trace_record *)((uintptr_t) 1051 tc->tc_buf + (uintptr_t)tc->tc_bufsiz - 1052 sizeof (struct htrap_trace_record)); 1053 1054 if (tc->tc_rec == tc->tc_stop) { 1055 tc->tc_rec = NULL; 1056 mdb_free(tc->tc_buf, tc->tc_bufsiz); 1057 } 1058 1059 return (status); 1060 } 1061 1062 void 1063 httrace_walk_fini(mdb_walk_state_t *wsp) 1064 { 1065 httrace_walk_data_t *tw = wsp->walk_data; 1066 1067 mdb_free(tw->tw_cpus, sizeof (httrace_cpu_data_t) * tw->tw_ncpu); 1068 mdb_free(tw, sizeof (httrace_walk_data_t)); 1069 } 1070 1071 int 1072 httrace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1073 { 1074 uint_t opt_x = FALSE; 1075 int cpu = -1; 1076 mdb_walk_cb_t ttprint; 1077 1078 if (mdb_getopts(argc, argv, 1079 'x', MDB_OPT_SETBITS, TRUE, &opt_x, NULL) != argc) 1080 return (DCMD_USAGE); 1081 1082 if (flags & DCMD_ADDRSPEC) { 1083 if (fetch_ncpu()) 1084 return (DCMD_ERR); 1085 if (addr >= ncpu) { 1086 mdb_warn("expected cpu between 0 and %d\n", ncpu - 1); 1087 return (DCMD_ERR); 1088 } 1089 cpu = (int)addr; 1090 } 1091 1092 if (cpu == -1) 1093 mdb_printf("CPU "); 1094 1095 if (opt_x) { 1096 mdb_printf("%-16s %-16s %-3s %-3s %-4s %-4s %-3s %-3s %-?s " 1097 "F1-4\n", "%tick", "%tstate", "%hp", "%ty", "%tag", 1098 "%tt", "%tl", "%gl", "%tpc"); 1099 ttprint = (mdb_walk_cb_t)httprint_long; 1100 } else { 1101 mdb_printf("%-16s %-3s %-4s %-4s %-16s %-3s %-3s %s\n", 1102 "%tick", "%ty", "%tag", "%tt", "", "%tl", "%gl", 1103 "%tpc"); 1104 ttprint = (mdb_walk_cb_t)httprint_short; 1105 } 1106 1107 if (mdb_walk("httrace", ttprint, &cpu) == -1) { 1108 mdb_warn("couldn't walk httrace"); 1109 return (DCMD_ERR); 1110 } 1111 1112 return (DCMD_OK); 1113 } 1114 #endif 1115 1116 struct { 1117 int xc_type; 1118 const char *xc_str; 1119 } xc_data[] = { 1120 { XT_ONE_SELF, "xt-one-self" }, 1121 { XT_ONE_OTHER, "xt-one-other" }, 1122 { XT_SOME_SELF, "xt-some-self" }, 1123 { XT_SOME_OTHER, "xt-some-other" }, 1124 { XT_ALL_SELF, "xt-all-self" }, 1125 { XT_ALL_OTHER, "xt-all-other" }, 1126 { XC_ONE_SELF, "xc-one-self" }, 1127 { XC_ONE_OTHER, "xc-one-other" }, 1128 { XC_ONE_OTHER_H, "xc-one-other-h" }, 1129 { XC_SOME_SELF, "xc-some-self" }, 1130 { XC_SOME_OTHER, "xc-some-other" }, 1131 { XC_SOME_OTHER_H, "xc-some-other-h" }, 1132 { XC_ALL_SELF, "xc-all-self" }, 1133 { XC_ALL_OTHER, "xc-all-other" }, 1134 { XC_ALL_OTHER_H, "xc-all-other-h" }, 1135 { XC_ATTENTION, "xc-attention" }, 1136 { XC_DISMISSED, "xc-dismissed" }, 1137 { XC_LOOP_ENTER, "xc-loop-enter" }, 1138 { XC_LOOP_DOIT, "xc-loop-doit" }, 1139 { XC_LOOP_EXIT, "xc-loop-exit" }, 1140 { 0, NULL } 1141 }; 1142 1143 /*ARGSUSED*/ 1144 int 1145 xctrace_walk(uintptr_t addr, const trap_trace_fullrec_t *full, int *cpu) 1146 { 1147 const struct trap_trace_record *ttp = &full->ttf_rec; 1148 int i, type = ttp->tt_tt & 0xff; 1149 const char *str = "???"; 1150 1151 if ((ttp->tt_tt & 0xff00) == TT_XCALL) { 1152 for (i = 0; xc_data[i].xc_str != NULL; i++) { 1153 if (xc_data[i].xc_type == type) { 1154 str = xc_data[i].xc_str; 1155 break; 1156 } 1157 } 1158 } else if ((ttp->tt_tt & 0xff00) == TT_XCALL_CONT) { 1159 str = "xcall-cont"; 1160 mdb_printf("%3d %016llx %-16s %08x %08x %08x %08x\n", 1161 full->ttf_cpu, ttp->tt_tick, str, ttp->tt_f1, ttp->tt_f2, 1162 ttp->tt_f3, ttp->tt_f4); 1163 return (WALK_NEXT); 1164 } else if (ttp->tt_tt == 0x60) { 1165 str = "int-vec"; 1166 } else { 1167 return (WALK_NEXT); 1168 } 1169 1170 mdb_printf("%3d %016llx %-16s %08x %a\n", full->ttf_cpu, 1171 ttp->tt_tick, str, ttp->tt_sp, ttp->tt_tr); 1172 1173 return (WALK_NEXT); 1174 } 1175 1176 /*ARGSUSED*/ 1177 int 1178 xctrace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1179 { 1180 if ((flags & DCMD_ADDRSPEC) || argc != 0) 1181 return (DCMD_USAGE); 1182 1183 if (mdb_walk("ttrace", (mdb_walk_cb_t)xctrace_walk, NULL) == -1) { 1184 mdb_warn("couldn't walk ttrace"); 1185 return (DCMD_ERR); 1186 } 1187 1188 return (DCMD_OK); 1189 } 1190 1191 /* 1192 * Grrr... xc_mbox isn't in an _impl header file; we define it here. 1193 */ 1194 typedef struct xc_mbox { 1195 xcfunc_t *xc_func; 1196 uint64_t xc_arg1; 1197 uint64_t xc_arg2; 1198 cpuset_t xc_cpuset; 1199 volatile uint_t xc_state; 1200 } xc_mbox_t; 1201 1202 typedef struct xc_mbox_walk { 1203 int xw_ndx; 1204 uintptr_t xw_addr; 1205 xc_mbox_t *xw_mbox; 1206 } xc_mbox_walk_t; 1207 1208 static int 1209 xc_mbox_walk_init(mdb_walk_state_t *wsp) 1210 { 1211 GElf_Sym sym; 1212 xc_mbox_walk_t *xw; 1213 1214 if (mdb_lookup_by_name("xc_mbox", &sym) == -1) { 1215 mdb_warn("couldn't find 'xc_mbox'"); 1216 return (WALK_ERR); 1217 } 1218 1219 if (fetch_ncpu() || fetch_mbox()) 1220 return (WALK_ERR); 1221 1222 xw = mdb_zalloc(sizeof (xc_mbox_walk_t), UM_SLEEP); 1223 xw->xw_mbox = mdb_zalloc(mbox_size * ncpu, UM_SLEEP); 1224 1225 if (mdb_readsym(xw->xw_mbox, mbox_size * ncpu, "xc_mbox") == -1) { 1226 mdb_warn("couldn't read 'xc_mbox'"); 1227 mdb_free(xw->xw_mbox, mbox_size * ncpu); 1228 mdb_free(xw, sizeof (xc_mbox_walk_t)); 1229 return (WALK_ERR); 1230 } 1231 1232 xw->xw_addr = sym.st_value; 1233 wsp->walk_data = xw; 1234 1235 return (WALK_NEXT); 1236 } 1237 1238 static int 1239 xc_mbox_walk_step(mdb_walk_state_t *wsp) 1240 { 1241 xc_mbox_walk_t *xw = wsp->walk_data; 1242 int status; 1243 1244 if (xw->xw_ndx == ncpu) 1245 return (WALK_DONE); 1246 1247 status = wsp->walk_callback(xw->xw_addr, 1248 &xw->xw_mbox[xw->xw_ndx++], wsp->walk_cbdata); 1249 1250 xw->xw_addr += mbox_size; 1251 return (status); 1252 } 1253 1254 static void 1255 xc_mbox_walk_fini(mdb_walk_state_t *wsp) 1256 { 1257 xc_mbox_walk_t *xw = wsp->walk_data; 1258 1259 mdb_free(xw->xw_mbox, mbox_size * ncpu); 1260 mdb_free(xw, sizeof (xc_mbox_walk_t)); 1261 } 1262 1263 static int 1264 xc_mbox(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1265 { 1266 xc_mbox_t *mbox; 1267 GElf_Sym sym; 1268 const char *state; 1269 1270 if (argc != 0) 1271 return (DCMD_USAGE); 1272 1273 if (!(flags & DCMD_ADDRSPEC)) { 1274 if (mdb_walk_dcmd("xc_mbox", "xc_mbox", argc, argv) == -1) { 1275 mdb_warn("can't walk 'xc_mbox'"); 1276 return (DCMD_ERR); 1277 } 1278 return (DCMD_OK); 1279 } 1280 1281 if (fetch_ncpu() || fetch_mbox()) 1282 return (DCMD_ERR); 1283 1284 if (DCMD_HDRSPEC(flags)) { 1285 mdb_printf("%3s %-8s %-8s %-9s %-16s %-16s %s\n", 1286 "CPU", "ADDR", "STATE", "CPUSET", "ARG1", "ARG2", "HNDLR"); 1287 } 1288 1289 mbox = mdb_alloc(mbox_size, UM_SLEEP | UM_GC); 1290 if (mdb_vread(mbox, mbox_size, addr) == -1) { 1291 mdb_warn("couldn't read xc_mbox at %p", addr); 1292 return (DCMD_ERR); 1293 } 1294 1295 if (mbox->xc_func == NULL) 1296 return (DCMD_OK); 1297 1298 if (mdb_lookup_by_name("xc_mbox", &sym) == -1) { 1299 mdb_warn("couldn't read 'xc_mbox'"); 1300 return (DCMD_ERR); 1301 } 1302 1303 state = mdb_ctf_enum_name(mbox_states, 1304 /* LINTED - alignment */ 1305 *(int *)((char *)mbox + mbox_stoff)); 1306 1307 mdb_printf("%3d %08x %-8s [ ", 1308 (int)((addr - sym.st_value) / mbox_size), addr, 1309 state ? state : "XC_???"); 1310 1311 print_cpuset_range(&mbox->xc_cpuset, BT_BITOUL(ncpu), 5); 1312 1313 mdb_printf(" ] %-16a %-16a %a\n", 1314 mbox->xc_arg1, mbox->xc_arg2, mbox->xc_func); 1315 1316 return (DCMD_OK); 1317 } 1318 1319 typedef struct softint_walk_data { 1320 struct intr_vector *sw_table; 1321 uintptr_t sw_base; 1322 size_t sw_ndx; 1323 size_t sw_size; 1324 } softint_walk_data_t; 1325 1326 int 1327 softint_walk_init(mdb_walk_state_t *wsp) 1328 { 1329 softint_walk_data_t *sw; 1330 1331 if (wsp->walk_addr != NULL) { 1332 mdb_warn("softint walk only supports global walks\n"); 1333 return (WALK_ERR); 1334 } 1335 1336 /* 1337 * If this fails, we'll just end up printing all the entries. 1338 */ 1339 if (mdb_lookup_by_name("nohandler", &iv_nohandler_sym) == -1) 1340 mdb_warn("couldn't find iv nohandler"); 1341 1342 sw = mdb_zalloc(sizeof (softint_walk_data_t), UM_SLEEP); 1343 1344 sw->sw_size = iv_sym.st_size; 1345 sw->sw_base = (uintptr_t)iv_sym.st_value; 1346 sw->sw_table = mdb_zalloc(sw->sw_size, UM_SLEEP); 1347 1348 if (mdb_vread(sw->sw_table, sw->sw_size, sw->sw_base) == -1) { 1349 mdb_warn("couldn't read intr_vector table"); 1350 mdb_free(sw->sw_table, sw->sw_size); 1351 mdb_free(sw, sizeof (softint_walk_data_t)); 1352 return (WALK_ERR); 1353 } 1354 1355 wsp->walk_data = sw; 1356 return (WALK_NEXT); 1357 } 1358 1359 int 1360 softint_walk_step(mdb_walk_state_t *wsp) 1361 { 1362 softint_walk_data_t *sw = (softint_walk_data_t *)wsp->walk_data; 1363 size_t max = sw->sw_size / sizeof (struct intr_vector); 1364 1365 while (sw->sw_ndx < max) { 1366 struct intr_vector *iv = &(sw->sw_table[sw->sw_ndx++]); 1367 1368 if (iv->iv_handler == (intrfunc)iv_nohandler_sym.st_value) 1369 continue; 1370 1371 return (wsp->walk_callback((uintptr_t)iv - 1372 (uintptr_t)sw->sw_table + sw->sw_base, iv, 1373 wsp->walk_cbdata)); 1374 } 1375 1376 return (WALK_DONE); 1377 } 1378 1379 void 1380 softint_walk_fini(mdb_walk_state_t *wsp) 1381 { 1382 softint_walk_data_t *sw = wsp->walk_data; 1383 1384 mdb_free(sw->sw_table, sw->sw_size); 1385 mdb_free(sw, sizeof (softint_walk_data_t)); 1386 } 1387 1388 int 1389 softint_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1390 { 1391 int inum; 1392 struct intr_vector iv; 1393 1394 if (!(flags & DCMD_ADDRSPEC)) { 1395 if (mdb_walk_dcmd("softint", "softint", argc, argv) == -1) { 1396 mdb_warn("can't walk softint"); 1397 return (DCMD_ERR); 1398 } 1399 return (DCMD_OK); 1400 } 1401 1402 inum = (int)((addr - (uintptr_t)iv_sym.st_value) / 1403 sizeof (struct intr_vector)); 1404 1405 if (DCMD_HDRSPEC(flags)) { 1406 mdb_printf("%4s %?s %4s %4s %?s %s\n", "INUM", "ADDR", "PEND", 1407 "PIL", "ARG", "HANDLER"); 1408 } 1409 1410 if (mdb_vread(&iv, sizeof (iv), addr) == -1) { 1411 mdb_warn("couldn't read intr_vector at %p", addr); 1412 return (DCMD_ERR); 1413 } 1414 1415 mdb_printf("%4d %0?p %4d %4d %?p %?p %a\n", inum, addr, iv.iv_pending, 1416 iv.iv_pil, iv.iv_arg, iv.iv_softint_arg2, iv.iv_handler); 1417 1418 return (DCMD_OK); 1419 } 1420 1421 static int 1422 whatis_walk_tt(uintptr_t taddr, const trap_trace_fullrec_t *ttf, uintptr_t *ap) 1423 { 1424 uintptr_t addr = *ap; 1425 1426 if (addr < taddr || addr > taddr + sizeof (struct trap_trace_record)) 1427 return (WALK_NEXT); 1428 1429 mdb_printf("%p is %p+%p, trap trace record for cpu %d\n", 1430 addr, taddr, addr - taddr, ttf->ttf_cpu); 1431 1432 mdb_set_dot(1); 1433 return (WALK_DONE); 1434 } 1435 1436 /*ARGSUSED*/ 1437 int 1438 whatis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1439 { 1440 GElf_Sym sym; 1441 1442 if (!(flags & DCMD_ADDRSPEC)) 1443 return (DCMD_USAGE); 1444 1445 if (mdb_lookup_by_name("trap_trace_ctl", &sym) == -1) 1446 return (DCMD_NEXT); 1447 1448 mdb_set_dot(0); 1449 1450 if (mdb_walk("ttrace", (mdb_walk_cb_t)whatis_walk_tt, &addr) == -1) 1451 mdb_warn("failed to walk 'ttrace'"); 1452 1453 return (DCMD_NEXT); 1454 } 1455 1456 /*ARGSUSED*/ 1457 int 1458 mutex_owner_init(mdb_walk_state_t *wsp) 1459 { 1460 return (WALK_NEXT); 1461 } 1462 1463 int 1464 mutex_owner_step(mdb_walk_state_t *wsp) 1465 { 1466 uintptr_t addr = wsp->walk_addr; 1467 mutex_impl_t mtx; 1468 uintptr_t owner; 1469 kthread_t thr; 1470 1471 if (mdb_vread(&mtx, sizeof (mtx), addr) == -1) 1472 return (WALK_ERR); 1473 1474 if (!MUTEX_TYPE_ADAPTIVE(&mtx)) 1475 return (WALK_DONE); 1476 1477 if ((owner = (uintptr_t)MUTEX_OWNER(&mtx)) == NULL) 1478 return (WALK_DONE); 1479 1480 if (mdb_vread(&thr, sizeof (thr), owner) != -1) 1481 (void) wsp->walk_callback(owner, &thr, wsp->walk_cbdata); 1482 1483 return (WALK_DONE); 1484 } 1485 1486 static const mdb_dcmd_t dcmds[] = { 1487 { "cpuset", ":[-l|-r]", "dump a cpuset_t", cmd_cpuset }, 1488 { "ttctl", NULL, "dump trap trace ctl records", ttctl }, 1489 { "ttrace", "[-x]", "dump trap trace buffer for a cpu", ttrace }, 1490 #ifdef sun4v 1491 { "httctl", NULL, "dump hv trap trace ctl records", httctl }, 1492 { "httrace", "[-x]", "dump hv trap trace buffer for a cpu", httrace }, 1493 #endif 1494 { "xc_mbox", "?", "dump xcall mboxes", xc_mbox }, 1495 { "xctrace", NULL, "dump xcall trace buffer", xctrace }, 1496 { "softint", NULL, "dumps interrupt vector table", softint_dcmd }, 1497 { "whatis", ":[-abv]", "given an address, return information", whatis }, 1498 { "sfmmu_vtop", ":[[-v] -a as]", "print virtual to physical mapping", 1499 sfmmu_vtop }, 1500 { "page_num2pp", ":", "page frame number to page structure", 1501 page_num2pp }, 1502 { "memseg_list", ":", "show memseg list", memseg_list }, 1503 { "tsbinfo", ":[-l [-a]]", "show tsbinfo", tsbinfo_list, 1504 tsbinfo_help }, 1505 { NULL } 1506 }; 1507 1508 static const mdb_walker_t walkers[] = { 1509 { "mutex_owner", "walks the owner of a mutex", 1510 mutex_owner_init, mutex_owner_step }, 1511 { "ttrace", "walks the trap trace buffer for a CPU", 1512 ttrace_walk_init, ttrace_walk_step, ttrace_walk_fini }, 1513 #ifdef sun4v 1514 { "httrace", "walks the hv trap trace buffer for a CPU", 1515 httrace_walk_init, httrace_walk_step, httrace_walk_fini }, 1516 #endif 1517 { "xc_mbox", "walks the cross call mail boxes", 1518 xc_mbox_walk_init, xc_mbox_walk_step, xc_mbox_walk_fini }, 1519 { "softint", "walks the interrupt vector table", 1520 softint_walk_init, softint_walk_step, softint_walk_fini }, 1521 { "memseg", "walk the memseg structures", 1522 memseg_walk_init, memseg_walk_step, memseg_walk_fini }, 1523 { NULL } 1524 }; 1525 1526 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1527 1528 const mdb_modinfo_t * 1529 _mdb_init(void) 1530 { 1531 if (mdb_lookup_by_name("intr_vector", &iv_sym) == -1) { 1532 mdb_warn("couldn't find intr_vector"); 1533 return (NULL); 1534 } 1535 1536 return (&modinfo); 1537 } 1538