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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
31 #include <sys/xc_impl.h>
35 #include <sys/xc_impl.h>
38 #include <sys/traptrace.h>
39 #include <sys/machparam.h>
40 #include <sys/intreg.h>
41 #include <sys/ivintr.h>
42 #include <sys/mutex_impl.h>
44 #include <mdb/mdb_modapi.h>
45 #include <mdb/mdb_ctf.h>
46 #include <mdb/mdb_whatis.h>
50 #define SYSTRAP_TT 0x1300
53 typedef struct trap_trace_fullrec
{
54 struct trap_trace_record ttf_rec
;
56 } trap_trace_fullrec_t
;
59 typedef struct htrap_trace_fullrec
{
60 struct htrap_trace_record ttf_rec
;
62 } htrap_trace_fullrec_t
;
66 * These strings and accompanying macros allow our string table to look
67 * just like the real table in trap_table.s.
70 static const char NOT
[] = "reserved"; /* common reserved string */
71 static const char BAD
[] = "unused"; /* common unused string */
73 #define NOT4 NOT, NOT, NOT, NOT
74 #define BAD4 BAD, BAD, BAD, BAD
76 static const char *const ttdescr
[] = {
77 NOT
, /* 000 reserved */
78 "power-on", /* 001 power on reset */
79 "watchdog", /* 002 watchdog reset */
80 "xir", /* 003 externally initiated reset */
81 "sir", /* 004 software initiated reset */
82 "red", /* 005 red mode exception */
83 NOT
, NOT
, /* 006 - 007 reserved */
84 "immu-xcp", /* 008 instruction access exception */
85 "immu-miss", /* 009 instruction access MMU miss */
86 "immu-err", /* 00A instruction access error */
87 NOT
, NOT4
, /* 00B - 00F reserved */
88 "ill-inst", /* 010 illegal instruction */
89 "priv-inst", /* 011 privileged opcode */
90 "unimp-ldd", /* 012 unimplemented LDD */
91 "unimp-std", /* 013 unimplemented STD */
92 NOT4
, NOT4
, NOT4
, /* 014 - 01F reserved */
93 "fp-disable", /* 020 fp disabled */
94 "fp-ieee754", /* 021 fp exception ieee 754 */
95 "fp-xcp-other", /* 022 fp exception other */
96 "tag-oflow", /* 023 tag overflow */
97 "cleanwin", /* 024 clean window */
98 "cleanwin", /* 025 clean window */
99 "cleanwin", /* 026 clean window */
100 "cleanwin", /* 027 clean window */
101 "div-zero", /* 028 division by zero */
102 "internal-err", /* 029 internal processor error */
103 NOT
, NOT
, NOT4
, /* 02A - 02F reserved */
104 "dmmu-xcp", /* 030 data access exception */
105 "dmmu-miss", /* 031 data access MMU miss */
106 "dmmu-err", /* 032 data access error */
107 "dmmu-prot", /* 033 data access protection */
108 "unalign", /* 034 mem address not aligned */
109 "lddf-unalign", /* 035 LDDF mem address not aligned */
110 "stdf-unalign", /* 036 STDF mem address not aligned */
111 "priv-act", /* 037 privileged action */
112 "ldqf-unalign", /* 038 LDQF mem address not aligned */
113 "stqf-unalign", /* 039 STQF mem address not aligned */
114 NOT
, NOT
, NOT4
, /* 03A - 03F reserved */
115 "async-d-err", /* 040 async data error */
116 "level-1", /* 041 interrupt level 1 */
117 "level-2", /* 042 interrupt level 2 */
118 "level-3", /* 043 interrupt level 3 */
119 "level-4", /* 044 interrupt level 4 */
120 "level-5", /* 045 interrupt level 5 */
121 "level-6", /* 046 interrupt level 6 */
122 "level-7", /* 047 interrupt level 7 */
123 "level-8", /* 048 interrupt level 8 */
124 "level-9", /* 049 interrupt level 9 */
125 "level-10", /* 04A interrupt level 10 */
126 "level-11", /* 04B interrupt level 11 */
127 "level-12", /* 04C interrupt level 12 */
128 "level-13", /* 04D interrupt level 13 */
129 "level-14", /* 04E interrupt level 14 */
130 "level-15", /* 04F interrupt level 15 */
131 NOT4
, NOT4
, NOT4
, NOT4
, /* 050 - 05F reserved */
132 "int-vec", /* 060 interrupt vector */
133 "pa-watch", /* 061 PA watchpoint */
134 "va-watch", /* 062 VA watchpoint */
135 "ecc-err", /* 063 corrected ECC error */
136 "itlb-miss", /* 064 instruction access MMU miss */
137 "itlb-miss", /* 065 instruction access MMU miss */
138 "itlb-miss", /* 066 instruction access MMU miss */
139 "itlb-miss", /* 067 instruction access MMU miss */
140 "dtlb-miss", /* 068 data access MMU miss */
141 "dtlb-miss", /* 069 data access MMU miss */
142 "dtlb-miss", /* 06A data access MMU miss */
143 "dtlb-miss", /* 06B data access MMU miss */
144 "dtlb-prot", /* 06C data access protection */
145 "dtlb-prot", /* 06D data access protection */
146 "dtlb-prot", /* 06E data access protection */
147 "dtlb-prot", /* 06F data access protection */
148 "fast-ecc-err", /* 070 fast ecache ECC error */
149 "dp-err", /* 071 data cache parity error */
150 "ip-err", /* 072 instr cache parity error */
151 NOT
, NOT4
, NOT4
, /* 073 - 07B reserved */
153 "cpu-mondo", /* 07C CPU mondo */
154 "dev-mondo", /* 07D device mondo */
155 "res.-err", /* 07E resumable error */
156 "non-res.-err", /* 07F non-resumable error */
158 NOT4
, /* 07C - 07F reserved */
160 "spill-0-norm", /* 080 spill 0 normal */
161 "spill-0-norm", /* 081 spill 0 normal */
162 "spill-0-norm", /* 082 spill 0 normal */
163 "spill-0-norm", /* 083 spill 0 normal */
164 "spill-1-norm", /* 084 spill 1 normal */
165 "spill-1-norm", /* 085 spill 1 normal */
166 "spill-1-norm", /* 086 spill 1 normal */
167 "spill-1-norm", /* 087 spill 1 normal */
168 "spill-2-norm", /* 088 spill 2 normal */
169 "spill-2-norm", /* 089 spill 2 normal */
170 "spill-2-norm", /* 08A spill 2 normal */
171 "spill-2-norm", /* 08B spill 2 normal */
172 "spill-3-norm", /* 08C spill 3 normal */
173 "spill-3-norm", /* 08D spill 3 normal */
174 "spill-3-norm", /* 08E spill 3 normal */
175 "spill-3-norm", /* 08F spill 3 normal */
176 "spill-4-norm", /* 090 spill 4 normal */
177 "spill-4-norm", /* 091 spill 4 normal */
178 "spill-4-norm", /* 092 spill 4 normal */
179 "spill-4-norm", /* 093 spill 4 normal */
180 "spill-5-norm", /* 094 spill 5 normal */
181 "spill-5-norm", /* 095 spill 5 normal */
182 "spill-5-norm", /* 096 spill 5 normal */
183 "spill-5-norm", /* 097 spill 5 normal */
184 "spill-6-norm", /* 098 spill 6 normal */
185 "spill-6-norm", /* 099 spill 6 normal */
186 "spill-6-norm", /* 09A spill 6 normal */
187 "spill-6-norm", /* 09B spill 6 normal */
188 "spill-7-norm", /* 09C spill 7 normal */
189 "spill-7-norm", /* 09D spill 7 normal */
190 "spill-7-norm", /* 09E spill 7 normal */
191 "spill-7-norm", /* 09F spill 7 normal */
192 "spill-0-oth", /* 0A0 spill 0 other */
193 "spill-0-oth", /* 0A1 spill 0 other */
194 "spill-0-oth", /* 0A2 spill 0 other */
195 "spill-0-oth", /* 0A3 spill 0 other */
196 "spill-1-oth", /* 0A4 spill 1 other */
197 "spill-1-oth", /* 0A5 spill 1 other */
198 "spill-1-oth", /* 0A6 spill 1 other */
199 "spill-1-oth", /* 0A7 spill 1 other */
200 "spill-2-oth", /* 0A8 spill 2 other */
201 "spill-2-oth", /* 0A9 spill 2 other */
202 "spill-2-oth", /* 0AA spill 2 other */
203 "spill-2-oth", /* 0AB spill 2 other */
204 "spill-3-oth", /* 0AC spill 3 other */
205 "spill-3-oth", /* 0AD spill 3 other */
206 "spill-3-oth", /* 0AE spill 3 other */
207 "spill-3-oth", /* 0AF spill 3 other */
208 "spill-4-oth", /* 0B0 spill 4 other */
209 "spill-4-oth", /* 0B1 spill 4 other */
210 "spill-4-oth", /* 0B2 spill 4 other */
211 "spill-4-oth", /* 0B3 spill 4 other */
212 "spill-5-oth", /* 0B4 spill 5 other */
213 "spill-5-oth", /* 0B5 spill 5 other */
214 "spill-5-oth", /* 0B6 spill 5 other */
215 "spill-5-oth", /* 0B7 spill 5 other */
216 "spill-6-oth", /* 0B8 spill 6 other */
217 "spill-6-oth", /* 0B9 spill 6 other */
218 "spill-6-oth", /* 0BA spill 6 other */
219 "spill-6-oth", /* 0BB spill 6 other */
220 "spill-7-oth", /* 0BC spill 7 other */
221 "spill-7-oth", /* 0BD spill 7 other */
222 "spill-7-oth", /* 0BE spill 7 other */
223 "spill-7-oth", /* 0BF spill 7 other */
224 "fill-0-norm", /* 0C0 fill 0 normal */
225 "fill-0-norm", /* 0C1 fill 0 normal */
226 "fill-0-norm", /* 0C2 fill 0 normal */
227 "fill-0-norm", /* 0C3 fill 0 normal */
228 "fill-1-norm", /* 0C4 fill 1 normal */
229 "fill-1-norm", /* 0C5 fill 1 normal */
230 "fill-1-norm", /* 0C6 fill 1 normal */
231 "fill-1-norm", /* 0C7 fill 1 normal */
232 "fill-2-norm", /* 0C8 fill 2 normal */
233 "fill-2-norm", /* 0C9 fill 2 normal */
234 "fill-2-norm", /* 0CA fill 2 normal */
235 "fill-2-norm", /* 0CB fill 2 normal */
236 "fill-3-norm", /* 0CC fill 3 normal */
237 "fill-3-norm", /* 0CD fill 3 normal */
238 "fill-3-norm", /* 0CE fill 3 normal */
239 "fill-3-norm", /* 0CF fill 3 normal */
240 "fill-4-norm", /* 0D0 fill 4 normal */
241 "fill-4-norm", /* 0D1 fill 4 normal */
242 "fill-4-norm", /* 0D2 fill 4 normal */
243 "fill-4-norm", /* 0D3 fill 4 normal */
244 "fill-5-norm", /* 0D4 fill 5 normal */
245 "fill-5-norm", /* 0D5 fill 5 normal */
246 "fill-5-norm", /* 0D6 fill 5 normal */
247 "fill-5-norm", /* 0D7 fill 5 normal */
248 "fill-6-norm", /* 0D8 fill 6 normal */
249 "fill-6-norm", /* 0D9 fill 6 normal */
250 "fill-6-norm", /* 0DA fill 6 normal */
251 "fill-6-norm", /* 0DB fill 6 normal */
252 "fill-7-norm", /* 0DC fill 7 normal */
253 "fill-7-norm", /* 0DD fill 7 normal */
254 "fill-7-norm", /* 0DE fill 7 normal */
255 "fill-7-norm", /* 0DF fill 7 normal */
256 "fill-0-oth", /* 0E0 fill 0 other */
257 "fill-0-oth", /* 0E1 fill 0 other */
258 "fill-0-oth", /* 0E2 fill 0 other */
259 "fill-0-oth", /* 0E3 fill 0 other */
260 "fill-1-oth", /* 0E4 fill 1 other */
261 "fill-1-oth", /* 0E5 fill 1 other */
262 "fill-1-oth", /* 0E6 fill 1 other */
263 "fill-1-oth", /* 0E7 fill 1 other */
264 "fill-2-oth", /* 0E8 fill 2 other */
265 "fill-2-oth", /* 0E9 fill 2 other */
266 "fill-2-oth", /* 0EA fill 2 other */
267 "fill-2-oth", /* 0EB fill 2 other */
268 "fill-3-oth", /* 0EC fill 3 other */
269 "fill-3-oth", /* 0ED fill 3 other */
270 "fill-3-oth", /* 0EE fill 3 other */
271 "fill-3-oth", /* 0EF fill 3 other */
272 "fill-4-oth", /* 0F0 fill 4 other */
273 "fill-4-oth", /* 0F1 fill 4 other */
274 "fill-4-oth", /* 0F2 fill 4 other */
275 "fill-4-oth", /* 0F3 fill 4 other */
276 "fill-5-oth", /* 0F4 fill 5 other */
277 "fill-5-oth", /* 0F5 fill 5 other */
278 "fill-5-oth", /* 0F6 fill 5 other */
279 "fill-5-oth", /* 0F7 fill 5 other */
280 "fill-6-oth", /* 0F8 fill 6 other */
281 "fill-6-oth", /* 0F9 fill 6 other */
282 "fill-6-oth", /* 0FA fill 6 other */
283 "fill-6-oth", /* 0FB fill 6 other */
284 "fill-7-oth", /* 0FC fill 7 other */
285 "fill-7-oth", /* 0FD fill 7 other */
286 "fill-7-oth", /* 0FE fill 7 other */
287 "fill-7-oth", /* 0FF fill 7 other */
288 "syscall-4x", /* 100 old system call */
289 "usr-brkpt", /* 101 user breakpoint */
290 "usr-div-zero", /* 102 user divide by zero */
291 "flush-wins", /* 103 flush windows */
292 "clean-wins", /* 104 clean windows */
293 "range-chk", /* 105 range check ?? */
294 "fix-align", /* 106 do unaligned references */
295 BAD
, /* 107 unused */
296 "syscall-32", /* 108 ILP32 system call on LP64 */
297 "set-t0-addr", /* 109 set trap0 address */
298 BAD
, BAD
, BAD4
, /* 10A - 10F unused */
299 BAD4
, BAD4
, BAD4
, BAD4
, /* 110 - 11F unused (V9 user traps?) */
300 "get-cc", /* 120 get condition codes */
301 "set-cc", /* 121 set condition codes */
302 "get-psr", /* 122 get psr */
303 "set-psr", /* 123 set psr (some fields) */
304 "getts", /* 124 get timestamp */
305 "gethrvtime", /* 125 get lwp virtual time */
306 "self-xcall", /* 126 self xcall */
307 "gethrtime", /* 127 get hrestime */
308 BAD
, /* 128 unused (ST_SETV9STACK) */
309 "getlgrp", /* 129 get lgrpid */
310 BAD
, BAD
, BAD4
, /* 12A - 12F unused */
311 BAD4
, BAD4
, /* 130 - 137 unused */
312 "dtrace-pid", /* 138 DTrace pid provider */
313 BAD
, /* 139 unused */
314 "dtrace-return", /* 13A DTrace pid provider */
315 BAD
, BAD4
, /* 13B - 13F unused */
316 "syscall-64", /* 140 LP64 system call */
317 BAD
, /* 141 unused */
318 "tt-freeze", /* 142 freeze traptrace */
319 "tt-unfreeze", /* 143 unfreeze traptrace */
320 BAD4
, BAD4
, BAD4
, /* 144 - 14F unused */
321 BAD4
, BAD4
, BAD4
, BAD4
, /* 150 - 15F unused */
322 BAD4
, BAD4
, BAD4
, BAD4
, /* 160 - 16F unused */
323 BAD4
, BAD4
, BAD4
, /* 170 - 17B unused */
324 "ptl1-panic", /* 17C test ptl1_panic */
325 "kmdb-enter", /* 17D kmdb enter (L1-A) */
326 "kmdb-brkpt", /* 17E kmdb breakpoint */
327 "obp-brkpt", /* 17F obp breakpoint */
329 "fast_trap", /* 180 hypervisor fast trap */
330 "cpu_tick_npt", /* 181 cpu_tick_npt() hcall */
331 "cpu_stick_npt", /* 182 cpu_stick_npt() hcall */
332 "mmu_map_addr", /* 183 mmu_map_addr() hcall */
333 "mmu_unmap_addr", /* 184 mmu_unmap_addr() hcall */
334 "ttrace_addentry", /* 185 ttrace_addentry() hcall */
335 NOT
, NOT
, NOT4
, NOT4
, /* 186 - 18F reserved */
337 NOT4
, NOT4
, NOT4
, NOT4
, /* 180 - 18F reserved */
339 NOT4
, NOT4
, NOT4
, NOT4
, /* 190 - 19F reserved */
340 NOT4
, NOT4
, NOT4
, NOT4
, /* 1A0 - 1AF reserved */
341 NOT4
, NOT4
, NOT4
, NOT4
, /* 1B0 - 1BF reserved */
342 NOT4
, NOT4
, NOT4
, NOT4
, /* 1C0 - 1CF reserved */
343 NOT4
, NOT4
, NOT4
, NOT4
, /* 1D0 - 1DF reserved */
344 NOT4
, NOT4
, NOT4
, NOT4
, /* 1E0 - 1EF reserved */
345 NOT4
, NOT4
, NOT4
, NOT4
/* 1F0 - 1FF reserved */
347 static const size_t ttndescr
= sizeof (ttdescr
) / sizeof (ttdescr
[0]);
349 static GElf_Sym iv_sym
;
352 * Persistent data (shouldn't change).
354 static int ncpu
; /* _ncpu */
355 static ssize_t mbox_size
; /* size of xc_mbox */
356 static ulong_t mbox_stoff
; /* offset of xc_mbox.xc_state */
357 static mdb_ctf_id_t mbox_states
; /* xc_state enumeration */
363 if (mdb_readsym(&ncpu
, sizeof (ncpu
), "_ncpu") == -1) {
364 mdb_warn("symbol '_ncpu' not found");
373 if (mbox_size
<= 0) {
376 if (mdb_ctf_lookup_by_name("struct xc_mbox", &id
) == -1) {
377 mdb_warn("couldn't find type 'struct xc_mbox'");
382 * These two could be combined into a single call to
383 * mdb_ctf_member_info if xc_state was actually of type
386 if (mdb_ctf_lookup_by_name("enum xc_states",
387 &mbox_states
) == -1) {
388 mdb_warn("couldn't find type 'enum xc_states'");
391 if (mdb_ctf_offsetof(id
, "xc_state", &mbox_stoff
) == -1) {
392 mdb_warn("couldn't find 'xc_mbox.xc_state'");
397 if ((mbox_size
= mdb_ctf_type_size(id
)) == -1) {
398 mdb_warn("couldn't size 'struct xc_mbox'");
406 print_range(int start
, int end
, int separator
)
413 /* Unfortunately, mdb_printf returns void */
414 format
= separator
? ", %d" : "%d";
415 mdb_printf(format
, start
);
416 count
= mdb_snprintf(&tmp
, 1, format
, start
);
418 format
= separator
? ", %d-%d" : "%d-%d";
419 mdb_printf(format
, start
, end
);
420 count
= mdb_snprintf(&tmp
, 1, format
, start
, end
);
427 print_cpuset_range(ulong_t
*cs
, int words
, int width
)
437 for (i
= 0; i
< words
; i
++)
438 for (j
= 0, m
= 1; j
< BT_NBIPUL
; j
++, m
<<= 1)
441 start
= i
* BT_NBIPUL
+ j
;
446 end
= i
* BT_NBIPUL
+ j
- 1;
447 count
+= print_range(start
, end
, sep
);
453 end
= i
* BT_NBIPUL
- 1;
454 count
+= print_range(start
, end
, sep
);
457 while (count
++ < width
)
463 cmd_cpuset(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
465 uint_t rflag
= 0, lflag
= 0;
467 ulong_t
*setp
, set
= 0;
469 if (mdb_getopts(argc
, argv
,
470 'l', MDB_OPT_SETBITS
, TRUE
, &lflag
,
471 'r', MDB_OPT_SETBITS
, TRUE
, &rflag
, NULL
) != argc
)
480 if ((words
= BT_BITOUL(ncpu
)) == 1) {
482 mdb_vread(setp
, sizeof (ulong_t
), addr
);
484 setp
= mdb_alloc(words
* sizeof (ulong_t
), UM_SLEEP
| UM_GC
);
485 mdb_vread(setp
, words
* sizeof (ulong_t
), addr
);
492 for (i
= 0; i
< words
; i
++)
493 for (j
= 0, m
= 1; j
< BT_NBIPUL
; j
++, m
<<= 1)
495 mdb_printf("%r\n", i
* BT_NBIPUL
+ j
);
500 for (i
= 0; i
< words
; i
++) {
501 mdb_printf(sep
? " %?0lx" : "%?0lx", setp
[i
]);
505 print_cpuset_range(setp
, words
, 0);
513 ttctl(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
515 TRAP_TRACE_CTL
*ctls
, *ctl
;
516 int i
, traptrace_buf_inuse
= 0;
524 ctls
= mdb_alloc(sizeof (TRAP_TRACE_CTL
) * ncpu
, UM_SLEEP
| UM_GC
);
525 if (mdb_readsym(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
,
526 "trap_trace_ctl") == -1) {
527 mdb_warn("symbol 'trap_trace_ctl' not found");
531 for (ctl
= &ctls
[0], i
= 0; i
< ncpu
; i
++, ctl
++) {
532 if (ctl
->d
.vaddr_base
== 0)
535 traptrace_buf_inuse
= 1;
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
);
544 if (!traptrace_buf_inuse
) {
545 mdb_warn("traptrace not configured");
554 ttprint_short(uintptr_t addr
, const trap_trace_fullrec_t
*full
, int *cpu
)
557 const struct trap_trace_record
*ttp
= &full
->ttf_rec
;
560 mdb_printf("%3d ", full
->ttf_cpu
);
562 if (*cpu
!= full
->ttf_cpu
)
566 * Decoding the traptype field is a bit messy. First we check for
567 * several well-defined 16-bit values defined in <sys/traptrace.h>.
569 switch (ttp
->tt_tt
) {
576 case TT_SYS_RTT_PROM
:
579 case TT_SYS_RTT_PRIV
:
582 case TT_SYS_RTT_USER
:
586 ttstr
= "int-thr-exit";
590 * Next we consider several prefixes (which are
591 * typically OR'd with other information such as the
592 * %pil or %tt value at the time of the trace).
594 switch (ttp
->tt_tt
& 0xff00) {
596 ttstr
= "serve-intr";
602 ttstr
= "xcall-cont";
609 * Otherwise we try to convert the
610 * tt value to a string using our
611 * giant lookup table.
613 ttstr
= ttp
->tt_tt
< ttndescr
?
614 ttdescr
[ttp
->tt_tt
] : "?";
619 mdb_printf("%016llx %04hx %-12s %02x %02x %0?p %A\n", ttp
->tt_tick
,
620 ttp
->tt_tt
, ttstr
, ttp
->tt_tl
, ttp
->tt_gl
,
621 ttp
->tt_tpc
, ttp
->tt_tpc
);
623 mdb_printf("%016llx %04hx %-12s %04hx %0?p %A\n", ttp
->tt_tick
,
624 ttp
->tt_tt
, ttstr
, ttp
->tt_tl
, ttp
->tt_tpc
, ttp
->tt_tpc
);
632 ttprint_long(uintptr_t addr
, const trap_trace_fullrec_t
*full
, int *cpu
)
634 const struct trap_trace_record
*ttp
= &full
->ttf_rec
;
637 mdb_printf("%3d ", full
->ttf_cpu
);
638 else if (*cpu
!= full
->ttf_cpu
)
642 mdb_printf("%016llx %016llx %04hx %02x %02x %0?p %0?p %0?p "
644 ttp
->tt_tick
, ttp
->tt_tstate
, ttp
->tt_tt
, ttp
->tt_tl
, ttp
->tt_gl
,
645 ttp
->tt_tpc
, ttp
->tt_sp
, ttp
->tt_tr
,
646 ttp
->tt_f1
, ttp
->tt_f2
, ttp
->tt_f3
, ttp
->tt_f4
);
648 mdb_printf("%016llx %016llx %04hx %04hx %0?p %0?p %0?p [%p,%p,%p,%p]\n",
649 ttp
->tt_tick
, ttp
->tt_tstate
, ttp
->tt_tt
, ttp
->tt_tl
,
650 ttp
->tt_tpc
, ttp
->tt_sp
, ttp
->tt_tr
,
651 ttp
->tt_f1
, ttp
->tt_f2
, ttp
->tt_f3
, ttp
->tt_f4
);
657 typedef struct ttrace_cpu_data
{
658 struct trap_trace_record
*tc_buf
;
659 struct trap_trace_record
*tc_rec
;
660 struct trap_trace_record
*tc_stop
;
665 typedef struct ttrace_walk_data
{
667 ttrace_cpu_data_t
*tw_cpus
;
668 } ttrace_walk_data_t
;
671 ttrace_walk_init(mdb_walk_state_t
*wsp
)
673 TRAP_TRACE_CTL
*ctls
, *ctl
;
674 int i
, traptrace_buf_inuse
= 0;
675 ttrace_walk_data_t
*tw
;
676 ttrace_cpu_data_t
*tc
;
677 struct trap_trace_record
*buf
;
679 if (wsp
->walk_addr
!= NULL
) {
680 mdb_warn("ttrace only supports global walks\n");
687 ctls
= mdb_alloc(sizeof (TRAP_TRACE_CTL
) * ncpu
, UM_SLEEP
);
688 if (mdb_readsym(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
,
689 "trap_trace_ctl") == -1) {
690 mdb_warn("symbol 'trap_trace_ctl' not found");
691 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
695 tw
= mdb_zalloc(sizeof (ttrace_walk_data_t
), UM_SLEEP
);
697 tw
->tw_cpus
= mdb_zalloc(sizeof (ttrace_cpu_data_t
) * ncpu
, UM_SLEEP
);
699 for (i
= 0; i
< ncpu
; i
++) {
702 if (ctl
->d
.vaddr_base
== 0)
705 traptrace_buf_inuse
= 1;
706 tc
= &(tw
->tw_cpus
[i
]);
707 tc
->tc_bufsiz
= ctl
->d
.limit
-
708 sizeof (struct trap_trace_record
);
709 tc
->tc_buf
= buf
= mdb_alloc(tc
->tc_bufsiz
, UM_SLEEP
);
710 tc
->tc_base
= (uintptr_t)ctl
->d
.vaddr_base
;
712 if (mdb_vread(buf
, tc
->tc_bufsiz
, tc
->tc_base
) == -1) {
713 mdb_warn("failed to read trap trace buffer at %p",
715 mdb_free(buf
, tc
->tc_bufsiz
);
718 tc
->tc_rec
= (struct trap_trace_record
*)
719 ((uintptr_t)buf
+ (uintptr_t)ctl
->d
.last_offset
);
720 tc
->tc_stop
= (struct trap_trace_record
*)
721 ((uintptr_t)buf
+ (uintptr_t)ctl
->d
.offset
);
724 if (!traptrace_buf_inuse
) {
725 mdb_warn("traptrace not configured");
726 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
730 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
736 ttrace_walk_step(mdb_walk_state_t
*wsp
)
738 ttrace_walk_data_t
*tw
= wsp
->walk_data
;
739 ttrace_cpu_data_t
*tc
;
740 struct trap_trace_record
*rec
;
741 int oldest
, i
, status
;
742 uint64_t oldest_tick
= 0;
744 trap_trace_fullrec_t fullrec
;
746 for (i
= 0; i
< tw
->tw_ncpu
; i
++) {
747 tc
= &(tw
->tw_cpus
[i
]);
749 if (tc
->tc_rec
== NULL
)
753 if (tc
->tc_rec
->tt_tick
== 0)
754 mdb_warn("Warning: tt_tick == 0\n");
756 if (tc
->tc_rec
->tt_tick
> oldest_tick
) {
757 oldest_tick
= tc
->tc_rec
->tt_tick
;
765 tc
= &(tw
->tw_cpus
[oldest
]);
768 fullrec
.ttf_rec
= *rec
;
769 fullrec
.ttf_cpu
= oldest
;
771 if (oldest_tick
!= 0)
772 status
= wsp
->walk_callback((uintptr_t)rec
-
773 (uintptr_t)tc
->tc_buf
+ tc
->tc_base
, &fullrec
,
778 if (tc
->tc_rec
< tc
->tc_buf
)
779 tc
->tc_rec
= (struct trap_trace_record
*)((uintptr_t)
780 tc
->tc_buf
+ (uintptr_t)tc
->tc_bufsiz
-
781 sizeof (struct trap_trace_record
));
783 if (tc
->tc_rec
== tc
->tc_stop
) {
785 mdb_free(tc
->tc_buf
, tc
->tc_bufsiz
);
792 ttrace_walk_fini(mdb_walk_state_t
*wsp
)
794 ttrace_walk_data_t
*tw
= wsp
->walk_data
;
796 mdb_free(tw
->tw_cpus
, sizeof (ttrace_cpu_data_t
) * tw
->tw_ncpu
);
797 mdb_free(tw
, sizeof (ttrace_walk_data_t
));
801 ttrace(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
803 uint_t opt_x
= FALSE
;
805 mdb_walk_cb_t ttprint
;
807 if (mdb_getopts(argc
, argv
,
808 'x', MDB_OPT_SETBITS
, TRUE
, &opt_x
, NULL
) != argc
)
811 if (flags
& DCMD_ADDRSPEC
) {
815 mdb_warn("expected cpu between 0 and %d\n", ncpu
- 1);
826 mdb_printf("%-16s %-16s %-4s %-3s %-3s %-?s %-?s %-?s "
827 "F1-4\n", "%tick", "%tstate", "%tt", "%tl", "%gl",
828 "%tpc", "%sp", "TR");
830 mdb_printf("%-16s %-16s %-4s %-4s %-?s %-?s %-?s "
831 "F1-4\n", "%tick", "%tstate", "%tt", "%tl",
832 "%tpc", "%sp", "TR");
835 ttprint
= (mdb_walk_cb_t
)ttprint_long
;
838 mdb_printf("%-16s %-4s %-12s %-3s %-3s %s\n",
839 "%tick", "%tt", "", "%tl", "%gl", "%tpc");
841 mdb_printf("%-16s %-4s %-12s %-4s %s\n",
842 "%tick", "%tt", "", "%tl", "%tpc");
845 ttprint
= (mdb_walk_cb_t
)ttprint_short
;
848 if (mdb_walk("ttrace", ttprint
, &cpu
) == -1) {
849 mdb_warn("couldn't walk ttrace");
859 httctl(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
861 TRAP_TRACE_CTL
*ctls
, *ctl
;
862 int i
, htraptrace_buf_inuse
= 0;
863 htrap_trace_hdr_t hdr
;
871 ctls
= mdb_alloc(sizeof (TRAP_TRACE_CTL
) * ncpu
, UM_SLEEP
| UM_GC
);
872 if (mdb_readsym(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
,
873 "trap_trace_ctl") == -1) {
874 mdb_warn("symbol 'trap_trace_ctl' not found");
878 for (ctl
= &ctls
[0], i
= 0; i
< ncpu
; i
++, ctl
++) {
879 if (ctl
->d
.hvaddr_base
== 0)
882 htraptrace_buf_inuse
= 1;
883 mdb_vread(&hdr
, sizeof (htrap_trace_hdr_t
),
884 (uintptr_t)ctl
->d
.hvaddr_base
);
885 mdb_printf("htrap_trace_ctl[%d] = {\n", i
);
886 mdb_printf(" vaddr_base = 0x%lx\n", (long)ctl
->d
.hvaddr_base
);
887 mdb_printf(" last_offset = 0x%lx\n", hdr
.last_offset
);
888 mdb_printf(" offset = 0x%lx\n", hdr
.offset
);
889 mdb_printf(" limit = 0x%x\n", ctl
->d
.hlimit
);
890 mdb_printf(" paddr_base = 0x%llx\n}\n", ctl
->d
.hpaddr_base
);
892 if (!htraptrace_buf_inuse
) {
893 mdb_warn("hv traptrace not configured");
902 httprint_short(uintptr_t addr
, const htrap_trace_fullrec_t
*full
, int *cpu
)
905 const struct htrap_trace_record
*ttp
= &full
->ttf_rec
;
908 mdb_printf("%3d ", full
->ttf_cpu
);
910 if (*cpu
!= full
->ttf_cpu
)
914 * Convert the tt value to a string using our gaint lookuo table
916 ttstr
= ttp
->tt_tt
< ttndescr
? ttdescr
[ttp
->tt_tt
] : "?";
918 mdb_printf("%016llx %02x %04hx %04hx %-16s %02x %02x %0?p %A\n",
919 ttp
->tt_tick
, ttp
->tt_ty
, ttp
->tt_tag
, ttp
->tt_tt
, ttstr
,
920 ttp
->tt_tl
, ttp
->tt_gl
, ttp
->tt_tpc
, ttp
->tt_tpc
);
927 httprint_long(uintptr_t addr
, const htrap_trace_fullrec_t
*full
, int *cpu
)
929 const struct htrap_trace_record
*ttp
= &full
->ttf_rec
;
932 mdb_printf("%3d ", full
->ttf_cpu
);
933 else if (*cpu
!= full
->ttf_cpu
)
936 mdb_printf("%016llx %016llx %02x %02x %04hx %04hx %02x %02x %0?p "
938 ttp
->tt_tick
, ttp
->tt_tstate
, ttp
->tt_hpstate
, ttp
->tt_ty
,
939 ttp
->tt_tag
, ttp
->tt_tt
, ttp
->tt_tl
, ttp
->tt_gl
, ttp
->tt_tpc
,
940 ttp
->tt_f1
, ttp
->tt_f2
, ttp
->tt_f3
, ttp
->tt_f4
);
945 typedef struct httrace_cpu_data
{
946 struct htrap_trace_record
*tc_buf
;
947 struct htrap_trace_record
*tc_rec
;
948 struct htrap_trace_record
*tc_stop
;
951 } httrace_cpu_data_t
;
953 typedef struct httrace_walk_data
{
955 httrace_cpu_data_t
*tw_cpus
;
956 } httrace_walk_data_t
;
959 httrace_walk_init(mdb_walk_state_t
*wsp
)
961 TRAP_TRACE_CTL
*ctls
, *ctl
;
962 int i
, htraptrace_buf_inuse
= 0;
963 httrace_walk_data_t
*tw
;
964 httrace_cpu_data_t
*tc
;
965 struct htrap_trace_record
*buf
;
966 htrap_trace_hdr_t
*hdr
;
968 if (wsp
->walk_addr
!= NULL
) {
969 mdb_warn("httrace only supports global walks\n");
976 ctls
= mdb_alloc(sizeof (TRAP_TRACE_CTL
) * ncpu
, UM_SLEEP
);
977 if (mdb_readsym(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
,
978 "trap_trace_ctl") == -1) {
979 mdb_warn("symbol 'trap_trace_ctl' not found");
980 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
984 tw
= mdb_zalloc(sizeof (httrace_walk_data_t
), UM_SLEEP
);
986 tw
->tw_cpus
= mdb_zalloc(sizeof (httrace_cpu_data_t
) * ncpu
, UM_SLEEP
);
988 for (i
= 0; i
< ncpu
; i
++) {
991 if (ctl
->d
.hvaddr_base
== 0)
994 htraptrace_buf_inuse
= 1;
995 tc
= &(tw
->tw_cpus
[i
]);
996 tc
->tc_bufsiz
= ctl
->d
.hlimit
;
997 tc
->tc_buf
= buf
= mdb_alloc(tc
->tc_bufsiz
, UM_SLEEP
);
998 tc
->tc_base
= (uintptr_t)ctl
->d
.hvaddr_base
;
1000 if (mdb_vread(buf
, tc
->tc_bufsiz
, tc
->tc_base
) == -1) {
1001 mdb_warn("failed to read hv trap trace buffer at %p",
1002 ctl
->d
.hvaddr_base
);
1003 mdb_free(buf
, tc
->tc_bufsiz
);
1006 hdr
= (htrap_trace_hdr_t
*)buf
;
1007 tc
->tc_rec
= (struct htrap_trace_record
*)
1008 ((uintptr_t)buf
+ (uintptr_t)hdr
->last_offset
);
1009 tc
->tc_stop
= (struct htrap_trace_record
*)
1010 ((uintptr_t)buf
+ (uintptr_t)hdr
->offset
);
1013 if (!htraptrace_buf_inuse
) {
1014 mdb_warn("hv traptrace not configured");
1015 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
1019 mdb_free(ctls
, sizeof (TRAP_TRACE_CTL
) * ncpu
);
1020 wsp
->walk_data
= tw
;
1025 httrace_walk_step(mdb_walk_state_t
*wsp
)
1027 httrace_walk_data_t
*tw
= wsp
->walk_data
;
1028 httrace_cpu_data_t
*tc
;
1029 struct htrap_trace_record
*rec
;
1030 int oldest
, i
, status
;
1031 uint64_t oldest_tick
= 0;
1033 htrap_trace_fullrec_t fullrec
;
1035 for (i
= 0; i
< tw
->tw_ncpu
; i
++) {
1036 tc
= &(tw
->tw_cpus
[i
]);
1038 if (tc
->tc_rec
== NULL
)
1042 if (tc
->tc_rec
->tt_tick
== 0)
1043 mdb_warn("Warning: tt_tick == 0\n");
1045 if (tc
->tc_rec
->tt_tick
>= oldest_tick
) {
1046 oldest_tick
= tc
->tc_rec
->tt_tick
;
1054 tc
= &(tw
->tw_cpus
[oldest
]);
1057 fullrec
.ttf_rec
= *rec
;
1058 fullrec
.ttf_cpu
= oldest
;
1060 if (oldest_tick
!= 0)
1061 status
= wsp
->walk_callback((uintptr_t)rec
-
1062 (uintptr_t)tc
->tc_buf
+ tc
->tc_base
, &fullrec
,
1067 /* first record of the trap trace buffer is trap trace header */
1068 if (tc
->tc_rec
== tc
->tc_buf
)
1069 tc
->tc_rec
= (struct htrap_trace_record
*)((uintptr_t)
1070 tc
->tc_buf
+ (uintptr_t)tc
->tc_bufsiz
-
1071 sizeof (struct htrap_trace_record
));
1073 if (tc
->tc_rec
== tc
->tc_stop
) {
1075 mdb_free(tc
->tc_buf
, tc
->tc_bufsiz
);
1082 httrace_walk_fini(mdb_walk_state_t
*wsp
)
1084 httrace_walk_data_t
*tw
= wsp
->walk_data
;
1086 mdb_free(tw
->tw_cpus
, sizeof (httrace_cpu_data_t
) * tw
->tw_ncpu
);
1087 mdb_free(tw
, sizeof (httrace_walk_data_t
));
1091 httrace(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1093 uint_t opt_x
= FALSE
;
1095 mdb_walk_cb_t ttprint
;
1097 if (mdb_getopts(argc
, argv
,
1098 'x', MDB_OPT_SETBITS
, TRUE
, &opt_x
, NULL
) != argc
)
1099 return (DCMD_USAGE
);
1101 if (flags
& DCMD_ADDRSPEC
) {
1105 mdb_warn("expected cpu between 0 and %d\n", ncpu
- 1);
1115 mdb_printf("%-16s %-16s %-3s %-3s %-4s %-4s %-3s %-3s %-?s "
1116 "F1-4\n", "%tick", "%tstate", "%hp", "%ty", "%tag",
1117 "%tt", "%tl", "%gl", "%tpc");
1118 ttprint
= (mdb_walk_cb_t
)httprint_long
;
1120 mdb_printf("%-16s %-3s %-4s %-4s %-16s %-3s %-3s %s\n",
1121 "%tick", "%ty", "%tag", "%tt", "", "%tl", "%gl",
1123 ttprint
= (mdb_walk_cb_t
)httprint_short
;
1126 if (mdb_walk("httrace", ttprint
, &cpu
) == -1) {
1127 mdb_warn("couldn't walk httrace");
1139 { XT_ONE_SELF
, "xt-one-self" },
1140 { XT_ONE_OTHER
, "xt-one-other" },
1141 { XT_SOME_SELF
, "xt-some-self" },
1142 { XT_SOME_OTHER
, "xt-some-other" },
1143 { XT_ALL_SELF
, "xt-all-self" },
1144 { XT_ALL_OTHER
, "xt-all-other" },
1145 { XC_ONE_SELF
, "xc-one-self" },
1146 { XC_ONE_OTHER
, "xc-one-other" },
1147 { XC_ONE_OTHER_H
, "xc-one-other-h" },
1148 { XC_SOME_SELF
, "xc-some-self" },
1149 { XC_SOME_OTHER
, "xc-some-other" },
1150 { XC_SOME_OTHER_H
, "xc-some-other-h" },
1151 { XC_ALL_SELF
, "xc-all-self" },
1152 { XC_ALL_OTHER
, "xc-all-other" },
1153 { XC_ALL_OTHER_H
, "xc-all-other-h" },
1154 { XC_ATTENTION
, "xc-attention" },
1155 { XC_DISMISSED
, "xc-dismissed" },
1156 { XC_LOOP_ENTER
, "xc-loop-enter" },
1157 { XC_LOOP_DOIT
, "xc-loop-doit" },
1158 { XC_LOOP_EXIT
, "xc-loop-exit" },
1164 xctrace_walk(uintptr_t addr
, const trap_trace_fullrec_t
*full
, int *cpu
)
1166 const struct trap_trace_record
*ttp
= &full
->ttf_rec
;
1167 int i
, type
= ttp
->tt_tt
& 0xff;
1168 const char *str
= "???";
1170 if ((ttp
->tt_tt
& 0xff00) == TT_XCALL
) {
1171 for (i
= 0; xc_data
[i
].xc_str
!= NULL
; i
++) {
1172 if (xc_data
[i
].xc_type
== type
) {
1173 str
= xc_data
[i
].xc_str
;
1177 } else if ((ttp
->tt_tt
& 0xff00) == TT_XCALL_CONT
) {
1179 mdb_printf("%3d %016llx %-16s %08x %08x %08x %08x\n",
1180 full
->ttf_cpu
, ttp
->tt_tick
, str
, ttp
->tt_f1
, ttp
->tt_f2
,
1181 ttp
->tt_f3
, ttp
->tt_f4
);
1183 } else if (ttp
->tt_tt
== 0x60) {
1189 mdb_printf("%3d %016llx %-16s %08x %a\n", full
->ttf_cpu
,
1190 ttp
->tt_tick
, str
, ttp
->tt_sp
, ttp
->tt_tr
);
1197 xctrace(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1199 if ((flags
& DCMD_ADDRSPEC
) || argc
!= 0)
1200 return (DCMD_USAGE
);
1202 if (mdb_walk("ttrace", (mdb_walk_cb_t
)xctrace_walk
, NULL
) == -1) {
1203 mdb_warn("couldn't walk ttrace");
1211 * Grrr... xc_mbox isn't in an _impl header file; we define it here.
1213 typedef struct xc_mbox
{
1218 volatile uint_t xc_state
;
1221 typedef struct xc_mbox_walk
{
1228 xc_mbox_walk_init(mdb_walk_state_t
*wsp
)
1233 if (mdb_lookup_by_name("xc_mbox", &sym
) == -1) {
1234 mdb_warn("couldn't find 'xc_mbox'");
1238 if (fetch_ncpu() || fetch_mbox())
1241 xw
= mdb_zalloc(sizeof (xc_mbox_walk_t
), UM_SLEEP
);
1242 xw
->xw_mbox
= mdb_zalloc(mbox_size
* ncpu
, UM_SLEEP
);
1244 if (mdb_readsym(xw
->xw_mbox
, mbox_size
* ncpu
, "xc_mbox") == -1) {
1245 mdb_warn("couldn't read 'xc_mbox'");
1246 mdb_free(xw
->xw_mbox
, mbox_size
* ncpu
);
1247 mdb_free(xw
, sizeof (xc_mbox_walk_t
));
1251 xw
->xw_addr
= sym
.st_value
;
1252 wsp
->walk_data
= xw
;
1258 xc_mbox_walk_step(mdb_walk_state_t
*wsp
)
1260 xc_mbox_walk_t
*xw
= wsp
->walk_data
;
1263 if (xw
->xw_ndx
== ncpu
)
1266 status
= wsp
->walk_callback(xw
->xw_addr
,
1267 &xw
->xw_mbox
[xw
->xw_ndx
++], wsp
->walk_cbdata
);
1269 xw
->xw_addr
+= mbox_size
;
1274 xc_mbox_walk_fini(mdb_walk_state_t
*wsp
)
1276 xc_mbox_walk_t
*xw
= wsp
->walk_data
;
1278 mdb_free(xw
->xw_mbox
, mbox_size
* ncpu
);
1279 mdb_free(xw
, sizeof (xc_mbox_walk_t
));
1283 xc_mbox(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1290 return (DCMD_USAGE
);
1292 if (!(flags
& DCMD_ADDRSPEC
)) {
1293 if (mdb_walk_dcmd("xc_mbox", "xc_mbox", argc
, argv
) == -1) {
1294 mdb_warn("can't walk 'xc_mbox'");
1300 if (fetch_ncpu() || fetch_mbox())
1303 if (DCMD_HDRSPEC(flags
)) {
1304 mdb_printf("%3s %-8s %-8s %-9s %-16s %-16s %s\n",
1305 "CPU", "ADDR", "STATE", "CPUSET", "ARG1", "ARG2", "HNDLR");
1308 mbox
= mdb_alloc(mbox_size
, UM_SLEEP
| UM_GC
);
1309 if (mdb_vread(mbox
, mbox_size
, addr
) == -1) {
1310 mdb_warn("couldn't read xc_mbox at %p", addr
);
1314 if (mbox
->xc_func
== NULL
)
1317 if (mdb_lookup_by_name("xc_mbox", &sym
) == -1) {
1318 mdb_warn("couldn't read 'xc_mbox'");
1322 state
= mdb_ctf_enum_name(mbox_states
,
1323 /* LINTED - alignment */
1324 *(int *)((char *)mbox
+ mbox_stoff
));
1326 mdb_printf("%3d %08x %-8s [ ",
1327 (int)((addr
- sym
.st_value
) / mbox_size
), addr
,
1328 state
? state
: "XC_???");
1330 print_cpuset_range((ulong_t
*)&mbox
->xc_cpuset
, BT_BITOUL(ncpu
), 5);
1332 mdb_printf(" ] %-16a %-16a %a\n",
1333 mbox
->xc_arg1
, mbox
->xc_arg2
, mbox
->xc_func
);
1338 typedef struct vecint_walk_data
{
1339 intr_vec_t
**vec_table
;
1343 } vecint_walk_data_t
;
1346 vecint_walk_init(mdb_walk_state_t
*wsp
)
1348 vecint_walk_data_t
*vecint
;
1350 if (wsp
->walk_addr
!= NULL
) {
1351 mdb_warn("vecint walk only supports global walks\n");
1355 vecint
= mdb_zalloc(sizeof (vecint_walk_data_t
), UM_SLEEP
);
1357 vecint
->vec_size
= MAXIVNUM
* sizeof (intr_vec_t
*);
1358 vecint
->vec_base
= (uintptr_t)iv_sym
.st_value
;
1359 vecint
->vec_table
= mdb_zalloc(vecint
->vec_size
, UM_SLEEP
);
1361 if (mdb_vread(vecint
->vec_table
, vecint
->vec_size
,
1362 vecint
->vec_base
) == -1) {
1363 mdb_warn("couldn't read intr_vec_table");
1364 mdb_free(vecint
->vec_table
, vecint
->vec_size
);
1365 mdb_free(vecint
, sizeof (vecint_walk_data_t
));
1369 wsp
->walk_data
= vecint
;
1374 vecint_walk_step(mdb_walk_state_t
*wsp
)
1376 vecint_walk_data_t
*vecint
= (vecint_walk_data_t
*)wsp
->walk_data
;
1377 size_t max
= vecint
->vec_size
/ sizeof (intr_vec_t
*);
1381 if (wsp
->walk_addr
== NULL
) {
1382 while ((vecint
->vec_idx
< max
) && ((wsp
->walk_addr
=
1383 (uintptr_t)vecint
->vec_table
[vecint
->vec_idx
++]) == NULL
))
1387 if (wsp
->walk_addr
== NULL
)
1390 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
1393 if (mdb_vread(&iv
, sizeof (intr_vec_t
),
1394 (uintptr_t)wsp
->walk_addr
) == -1) {
1395 mdb_warn("failed to read iv_p %p\n", wsp
->walk_addr
);
1399 wsp
->walk_addr
= (uintptr_t)iv
.iv_vec_next
;
1404 vecint_walk_fini(mdb_walk_state_t
*wsp
)
1406 vecint_walk_data_t
*vecint
= wsp
->walk_data
;
1408 mdb_free(vecint
->vec_table
, vecint
->vec_size
);
1409 mdb_free(vecint
, sizeof (vecint_walk_data_t
));
1413 vecint_dcmd(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1417 if (!(flags
& DCMD_ADDRSPEC
)) {
1418 if (mdb_walk_dcmd("vecint", "vecint", argc
, argv
) == -1) {
1419 mdb_warn("can't walk vecint");
1425 if (DCMD_HDRSPEC(flags
)) {
1426 mdb_printf("%4s %?s %4s %?s %?s %s\n", "INUM", "ADDR",
1427 "PIL", "ARG1", "ARG2", "HANDLER");
1430 if (mdb_vread(&iv
, sizeof (iv
), addr
) == -1) {
1431 mdb_warn("couldn't read intr_vec_table at %p", addr
);
1435 mdb_printf("%4x %?p %4d %?p %?p %a\n", iv
.iv_inum
, addr
,
1436 iv
.iv_pil
, iv
.iv_arg1
, iv
.iv_arg2
, iv
.iv_handler
);
1442 softint_walk_init(mdb_walk_state_t
*wsp
)
1446 if (wsp
->walk_addr
!= NULL
) {
1447 mdb_warn("softint walk only supports global walks\n");
1451 /* Read global softint linked list pointer */
1452 if (mdb_readvar(&list
, "softint_list") == -1) {
1453 mdb_warn("failed to read the global softint_list pointer\n");
1457 wsp
->walk_addr
= (uintptr_t)list
;
1463 softint_walk_fini(mdb_walk_state_t
*wsp
)
1465 /* Nothing to do here */
1469 softint_walk_step(mdb_walk_state_t
*wsp
)
1474 if (wsp
->walk_addr
== NULL
)
1477 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
1480 if (mdb_vread(&iv
, sizeof (intr_vec_t
),
1481 (uintptr_t)wsp
->walk_addr
) == -1) {
1482 mdb_warn("failed to read iv_p %p\n", wsp
->walk_addr
);
1486 wsp
->walk_addr
= (uintptr_t)iv
.iv_vec_next
;
1491 softint_dcmd(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1495 if (!(flags
& DCMD_ADDRSPEC
)) {
1496 if (mdb_walk_dcmd("softint", "softint", argc
, argv
) == -1) {
1497 mdb_warn("can't walk softint");
1503 if (DCMD_HDRSPEC(flags
)) {
1504 mdb_printf("%?s %4s %4s %4s %?s %?s %s\n", "ADDR", "TYPE",
1505 "PEND", "PIL", "ARG1", "ARG2", "HANDLER");
1508 if (mdb_vread(&iv
, sizeof (iv
), addr
) == -1) {
1509 mdb_warn("couldn't read softint at %p", addr
);
1513 mdb_printf("%?p %4s %4d %4d %?p %?p %a\n", addr
,
1514 (iv
.iv_flags
& IV_SOFTINT_MT
) ? "M" : "S",
1515 iv
.iv_flags
& IV_SOFTINT_PEND
, iv
.iv_pil
,
1516 iv
.iv_arg1
, iv
.iv_arg2
, iv
.iv_handler
);
1522 whatis_walk_tt(uintptr_t taddr
, const trap_trace_fullrec_t
*ttf
,
1527 while (mdb_whatis_match(w
, taddr
, sizeof (struct trap_trace_record
),
1529 mdb_whatis_report_object(w
, cur
, taddr
,
1530 "trap trace record for cpu %d\n", ttf
->ttf_cpu
);
1532 return (WHATIS_WALKRET(w
));
1537 whatis_run_traptrace(mdb_whatis_t
*w
, void *ignored
)
1541 if (mdb_lookup_by_name("trap_trace_ctl", &sym
) == -1)
1544 if (mdb_walk("ttrace", (mdb_walk_cb_t
)whatis_walk_tt
, w
) == -1)
1545 mdb_warn("failed to walk 'ttrace'");
1552 mutex_owner_init(mdb_walk_state_t
*wsp
)
1558 mutex_owner_step(mdb_walk_state_t
*wsp
)
1560 uintptr_t addr
= wsp
->walk_addr
;
1565 if (mdb_vread(&mtx
, sizeof (mtx
), addr
) == -1)
1568 if (!MUTEX_TYPE_ADAPTIVE(&mtx
))
1571 if ((owner
= (uintptr_t)MUTEX_OWNER(&mtx
)) == NULL
)
1574 if (mdb_vread(&thr
, sizeof (thr
), owner
) != -1)
1575 (void) wsp
->walk_callback(owner
, &thr
, wsp
->walk_cbdata
);
1580 static const mdb_dcmd_t dcmds
[] = {
1581 { "cpuset", ":[-l|-r]", "dump a cpuset_t", cmd_cpuset
},
1582 { "ttctl", NULL
, "dump trap trace ctl records", ttctl
},
1583 { "ttrace", "[-x]", "dump trap trace buffer for a cpu", ttrace
},
1585 { "httctl", NULL
, "dump hv trap trace ctl records", httctl
},
1586 { "httrace", "[-x]", "dump hv trap trace buffer for a cpu", httrace
},
1588 { "xc_mbox", "?", "dump xcall mboxes", xc_mbox
},
1589 { "xctrace", NULL
, "dump xcall trace buffer", xctrace
},
1590 { "vecint", NULL
, "display a registered hardware interrupt",
1592 { "softint", NULL
, "display a registered software interrupt",
1594 { "sfmmu_vtop", ":[[-v] -a as]", "print virtual to physical mapping",
1596 { "memseg_list", ":", "show memseg list", memseg_list
},
1597 { "tsbinfo", ":[-l [-a]]", "show tsbinfo", tsbinfo_list
,
1602 static const mdb_walker_t walkers
[] = {
1603 { "mutex_owner", "walks the owner of a mutex",
1604 mutex_owner_init
, mutex_owner_step
},
1605 { "ttrace", "walks the trap trace buffer for a CPU",
1606 ttrace_walk_init
, ttrace_walk_step
, ttrace_walk_fini
},
1608 { "httrace", "walks the hv trap trace buffer for a CPU",
1609 httrace_walk_init
, httrace_walk_step
, httrace_walk_fini
},
1611 { "xc_mbox", "walks the cross call mail boxes",
1612 xc_mbox_walk_init
, xc_mbox_walk_step
, xc_mbox_walk_fini
},
1613 { "vecint", "walk the list of registered hardware interrupts",
1614 vecint_walk_init
, vecint_walk_step
, vecint_walk_fini
},
1615 { "softint", "walk the list of registered software interrupts",
1616 softint_walk_init
, softint_walk_step
, softint_walk_fini
},
1617 { "memseg", "walk the memseg structures",
1618 memseg_walk_init
, memseg_walk_step
, memseg_walk_fini
},
1622 static const mdb_modinfo_t modinfo
= { MDB_API_VERSION
, dcmds
, walkers
};
1624 const mdb_modinfo_t
*
1627 if (mdb_lookup_by_name("intr_vec_table", &iv_sym
) == -1) {
1628 mdb_warn("couldn't find intr_vec_table");
1632 mdb_whatis_register("traptrace", whatis_run_traptrace
, NULL
,
1633 WHATIS_PRIO_EARLY
, WHATIS_REG_NO_ID
);