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