xref: /titanic_52/usr/src/cmd/mdb/common/modules/genunix/sysevent.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include "sysevent.h"
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate int
32*7c478bd9Sstevel@tonic-gate sysevent_buf(uintptr_t addr, uint_t flags, uint_t opt_flags)
33*7c478bd9Sstevel@tonic-gate {
34*7c478bd9Sstevel@tonic-gate 	sysevent_hdr_t evh;
35*7c478bd9Sstevel@tonic-gate 	sysevent_impl_t *ev;
36*7c478bd9Sstevel@tonic-gate 	int size;
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
39*7c478bd9Sstevel@tonic-gate 		if ((opt_flags & SYSEVENT_VERBOSE) == 0) {
40*7c478bd9Sstevel@tonic-gate 			mdb_printf("%<u>%-?s %-16s %-9s %-10s "
41*7c478bd9Sstevel@tonic-gate 			    "%-?s%</u>\n", "ADDRESS", "SEQUENCE ID",
42*7c478bd9Sstevel@tonic-gate 			    "CLASS", "SUBCLASS", "NVPAIR BUF ADDR");
43*7c478bd9Sstevel@tonic-gate 		}
44*7c478bd9Sstevel@tonic-gate 	}
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate 	/*
47*7c478bd9Sstevel@tonic-gate 	 * Read in the sysevent buffer header first.  After extracting
48*7c478bd9Sstevel@tonic-gate 	 * the size of the buffer, re-read the buffer in its entirety.
49*7c478bd9Sstevel@tonic-gate 	 */
50*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(&evh, sizeof (sysevent_hdr_t), addr) == -1) {
51*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read event header at %p", addr);
52*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
53*7c478bd9Sstevel@tonic-gate 	}
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate 	size = SE_SIZE((sysevent_impl_t *)&evh);
56*7c478bd9Sstevel@tonic-gate 	ev = mdb_alloc(size, UM_SLEEP | UM_GC);
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(ev, size, addr) == -1) {
59*7c478bd9Sstevel@tonic-gate 		mdb_warn("can not read sysevent at %p", addr);
60*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
61*7c478bd9Sstevel@tonic-gate 	}
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 	if ((opt_flags & SYSEVENT_VERBOSE) == 0) {
64*7c478bd9Sstevel@tonic-gate 		char ev_class[CLASS_FIELD_MAX];
65*7c478bd9Sstevel@tonic-gate 		char ev_subclass[SUBCLASS_FIELD_MAX];
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 		if (mdb_snprintf(ev_class, CLASS_FIELD_MAX, "%s",
68*7c478bd9Sstevel@tonic-gate 		    SE_CLASS_NAME(ev)) >= CLASS_FIELD_MAX - 1)
69*7c478bd9Sstevel@tonic-gate 			(void) strcpy(&ev_class[CLASS_FIELD_MAX - 4], "...");
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 		if (mdb_snprintf(ev_subclass, SUBCLASS_FIELD_MAX, "%s",
72*7c478bd9Sstevel@tonic-gate 		    SE_SUBCLASS_NAME(ev)) >= SUBCLASS_FIELD_MAX - 1)
73*7c478bd9Sstevel@tonic-gate 			(void) strcpy(&ev_subclass[SUBCLASS_FIELD_MAX - 4],
74*7c478bd9Sstevel@tonic-gate 			    "...");
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 		mdb_printf("%-?p %-16llu %-9s %-10s %-?p%\n",
77*7c478bd9Sstevel@tonic-gate 			addr, SE_SEQ(ev), ev_class, ev_subclass,
78*7c478bd9Sstevel@tonic-gate 			addr + SE_ATTR_OFF(ev));
79*7c478bd9Sstevel@tonic-gate 	} else {
80*7c478bd9Sstevel@tonic-gate 		mdb_printf("%<b>Sequence ID\t : %llu%</b>\n", SE_SEQ(ev));
81*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %s\n", "publisher", SE_PUB_NAME(ev));
82*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %p\n", "event address", (caddr_t)addr);
83*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %s\n", "class", SE_CLASS_NAME(ev));
84*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %s\n", "subclass", SE_SUBCLASS_NAME(ev));
85*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %llu\n", "time stamp", SE_TIME(ev));
86*7c478bd9Sstevel@tonic-gate 		mdb_printf("%16s : %p\n", "nvpair buf addr",
87*7c478bd9Sstevel@tonic-gate 		    addr + SE_ATTR_OFF(ev));
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate int
94*7c478bd9Sstevel@tonic-gate sysevent_subclass_list(uintptr_t addr, uint_t flags, int argc,
95*7c478bd9Sstevel@tonic-gate     const mdb_arg_t *argv)
96*7c478bd9Sstevel@tonic-gate {
97*7c478bd9Sstevel@tonic-gate 	int subclass_name_sz;
98*7c478bd9Sstevel@tonic-gate 	char subclass_name[CLASS_LIST_FIELD_MAX];
99*7c478bd9Sstevel@tonic-gate 	subclass_lst_t sclist;
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0)
102*7c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_LOOP) == 0) {
105*7c478bd9Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("sysevent_subclass_list",
106*7c478bd9Sstevel@tonic-gate 		    "sysevent_subclass_list", argc, argv, addr) == -1) {
107*7c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk sysevent subclass list");
108*7c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
111*7c478bd9Sstevel@tonic-gate 	}
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
114*7c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-24s %-?s%</u>\n",
115*7c478bd9Sstevel@tonic-gate 		    "ADDR", "NAME", "SUBSCRIBER DATA ADDR");
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(&sclist, sizeof (sclist), (uintptr_t)addr) == -1) {
118*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read subclass list at %p", addr);
119*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
120*7c478bd9Sstevel@tonic-gate 	}
121*7c478bd9Sstevel@tonic-gate 	if ((subclass_name_sz = mdb_readstr(subclass_name, CLASS_LIST_FIELD_MAX,
122*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)sclist.sl_name)) == -1) {
123*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read class name at %p",
124*7c478bd9Sstevel@tonic-gate 		    sclist.sl_name);
125*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	if (subclass_name_sz >= CLASS_LIST_FIELD_MAX - 1)
128*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&subclass_name[CLASS_LIST_FIELD_MAX - 4], "...");
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	mdb_printf("%-?p %-24s %-?p\n", addr, subclass_name,
131*7c478bd9Sstevel@tonic-gate 	    addr + offsetof(subclass_lst_t, sl_num));
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate int
138*7c478bd9Sstevel@tonic-gate sysevent_class_list(uintptr_t addr, uint_t flags, int argc,
139*7c478bd9Sstevel@tonic-gate     const mdb_arg_t *argv)
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate 	int class_name_sz;
142*7c478bd9Sstevel@tonic-gate 	char class_name[CLASS_LIST_FIELD_MAX];
143*7c478bd9Sstevel@tonic-gate 	class_lst_t clist;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0)
146*7c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_LOOP) == 0) {
149*7c478bd9Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("sysevent_class_list", "sysevent_class_list",
150*7c478bd9Sstevel@tonic-gate 		    argc, argv, addr) == -1) {
151*7c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk sysevent class list");
152*7c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
153*7c478bd9Sstevel@tonic-gate 		}
154*7c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
158*7c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-24s %-?s%</u>\n",
159*7c478bd9Sstevel@tonic-gate 		    "ADDR", "NAME", "SUBCLASS LIST ADDR");
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(&clist, sizeof (clist),
162*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)addr) == -1) {
163*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read class clist at %p", addr);
164*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
165*7c478bd9Sstevel@tonic-gate 	}
166*7c478bd9Sstevel@tonic-gate 	if ((class_name_sz = mdb_readstr(class_name, CLASS_LIST_FIELD_MAX,
167*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)clist.cl_name)) == -1) {
168*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read class name at %p",
169*7c478bd9Sstevel@tonic-gate 		    clist.cl_name);
170*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 	if (class_name_sz >= CLASS_LIST_FIELD_MAX - 1)
173*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&class_name[CLASS_LIST_FIELD_MAX - 4], "...");
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	mdb_printf("%-?p %-24s %-?p\n", addr, class_name,
176*7c478bd9Sstevel@tonic-gate 	    clist.cl_subclass_list);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate int
182*7c478bd9Sstevel@tonic-gate sysevent_subclass_list_walk_init(mdb_walk_state_t *wsp)
183*7c478bd9Sstevel@tonic-gate {
184*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
185*7c478bd9Sstevel@tonic-gate 		mdb_warn("sysevent_subclass_list does not support global "
186*7c478bd9Sstevel@tonic-gate 		    "walks");
187*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
188*7c478bd9Sstevel@tonic-gate 	}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (subclass_lst_t), UM_SLEEP);
191*7c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate int
195*7c478bd9Sstevel@tonic-gate sysevent_subclass_list_walk_step(mdb_walk_state_t *wsp)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	int status;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
200*7c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (subclass_lst_t),
203*7c478bd9Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
204*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read class list at %p", wsp->walk_addr);
205*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
209*7c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	wsp->walk_addr =
212*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)(((subclass_lst_t *)wsp->walk_data)->sl_next);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	return (status);
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate void
218*7c478bd9Sstevel@tonic-gate sysevent_subclass_list_walk_fini(mdb_walk_state_t *wsp)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (subclass_lst_t));
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate typedef struct class_walk_data {
224*7c478bd9Sstevel@tonic-gate 	int	hash_index;
225*7c478bd9Sstevel@tonic-gate 	class_lst_t *hash_tbl[CLASS_HASH_SZ + 1];
226*7c478bd9Sstevel@tonic-gate } class_walk_data_t;
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate int
229*7c478bd9Sstevel@tonic-gate sysevent_class_list_walk_init(mdb_walk_state_t *wsp)
230*7c478bd9Sstevel@tonic-gate {
231*7c478bd9Sstevel@tonic-gate 	class_walk_data_t *cl_walker;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
234*7c478bd9Sstevel@tonic-gate 		mdb_warn("sysevent_class_list does not support global walks");
235*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	cl_walker = mdb_zalloc(sizeof (class_walk_data_t), UM_SLEEP);
239*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(cl_walker->hash_tbl,
240*7c478bd9Sstevel@tonic-gate 	    sizeof (cl_walker->hash_tbl), wsp->walk_addr) == -1) {
241*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read class hash table at %p",
242*7c478bd9Sstevel@tonic-gate 		    wsp->walk_addr);
243*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)cl_walker->hash_tbl[0];
247*7c478bd9Sstevel@tonic-gate 	wsp->walk_data = cl_walker;
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate int
253*7c478bd9Sstevel@tonic-gate sysevent_class_list_walk_step(mdb_walk_state_t *wsp)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	int status = WALK_NEXT;
256*7c478bd9Sstevel@tonic-gate 	class_walk_data_t *cl_walker;
257*7c478bd9Sstevel@tonic-gate 	class_lst_t clist;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	cl_walker = (class_walk_data_t *)wsp->walk_data;
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	/* Skip over empty class table entries */
262*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr != NULL) {
263*7c478bd9Sstevel@tonic-gate 		if (mdb_vread(&clist, sizeof (class_lst_t),
264*7c478bd9Sstevel@tonic-gate 		    wsp->walk_addr) == -1) {
265*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read class list at %p",
266*7c478bd9Sstevel@tonic-gate 			    wsp->walk_addr);
267*7c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
268*7c478bd9Sstevel@tonic-gate 		}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 		status = wsp->walk_callback(wsp->walk_addr, NULL,
271*7c478bd9Sstevel@tonic-gate 		    wsp->walk_cbdata);
272*7c478bd9Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)clist.cl_next;
273*7c478bd9Sstevel@tonic-gate 	} else {
274*7c478bd9Sstevel@tonic-gate 		if (cl_walker->hash_index > CLASS_HASH_SZ) {
275*7c478bd9Sstevel@tonic-gate 			return (WALK_DONE);
276*7c478bd9Sstevel@tonic-gate 		} else {
277*7c478bd9Sstevel@tonic-gate 			wsp->walk_addr = (uintptr_t)
278*7c478bd9Sstevel@tonic-gate 			    cl_walker->hash_tbl[cl_walker->hash_index];
279*7c478bd9Sstevel@tonic-gate 			cl_walker->hash_index++;
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 	}
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	return (status);
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate void
288*7c478bd9Sstevel@tonic-gate sysevent_class_list_walk_fini(mdb_walk_state_t *wsp)
289*7c478bd9Sstevel@tonic-gate {
290*7c478bd9Sstevel@tonic-gate 	class_walk_data_t *cl_walker = wsp->walk_data;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	mdb_free(cl_walker, sizeof (cl_walker));
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
296*7c478bd9Sstevel@tonic-gate int
297*7c478bd9Sstevel@tonic-gate sysevent(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
298*7c478bd9Sstevel@tonic-gate {
299*7c478bd9Sstevel@tonic-gate 	uint_t sys_flags = FALSE;
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
302*7c478bd9Sstevel@tonic-gate 	    's', MDB_OPT_SETBITS, SYSEVENT_SENTQ, &sys_flags,
303*7c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, SYSEVENT_VERBOSE, &sys_flags, NULL) != argc)
304*7c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
307*7c478bd9Sstevel@tonic-gate 		if (sys_flags & SYSEVENT_SENTQ) {
308*7c478bd9Sstevel@tonic-gate 			if (mdb_walk_dcmd("sysevent_sent", "sysevent", argc,
309*7c478bd9Sstevel@tonic-gate 			    argv) == -1) {
310*7c478bd9Sstevel@tonic-gate 				mdb_warn("can not walk sent queue");
311*7c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
312*7c478bd9Sstevel@tonic-gate 			}
313*7c478bd9Sstevel@tonic-gate 		} else {
314*7c478bd9Sstevel@tonic-gate 			if (mdb_walk_dcmd("sysevent_pend", "sysevent", argc,
315*7c478bd9Sstevel@tonic-gate 			    argv) == -1) {
316*7c478bd9Sstevel@tonic-gate 				mdb_warn("can not walk pending queue");
317*7c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
318*7c478bd9Sstevel@tonic-gate 			}
319*7c478bd9Sstevel@tonic-gate 		}
320*7c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
321*7c478bd9Sstevel@tonic-gate 	}
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	return (sysevent_buf(addr, flags, sys_flags));
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate int
327*7c478bd9Sstevel@tonic-gate sysevent_channel(uintptr_t addr, uint_t flags, int argc,
328*7c478bd9Sstevel@tonic-gate     const mdb_arg_t *argv)
329*7c478bd9Sstevel@tonic-gate {
330*7c478bd9Sstevel@tonic-gate 	ssize_t channel_name_sz;
331*7c478bd9Sstevel@tonic-gate 	char channel_name[CHAN_FIELD_MAX];
332*7c478bd9Sstevel@tonic-gate 	sysevent_channel_descriptor_t chan_tbl;
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	if (argc != 0)
335*7c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
338*7c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("sysevent_channel", "sysevent_channel",
339*7c478bd9Sstevel@tonic-gate 		    argc, argv) == -1) {
340*7c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk sysevent channel");
341*7c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
342*7c478bd9Sstevel@tonic-gate 		}
343*7c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
348*7c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-16s %-8s %-?s%</u>\n",
349*7c478bd9Sstevel@tonic-gate 		    "ADDR", "NAME", "REF CNT", "CLASS LST ADDR");
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(&chan_tbl, sizeof (chan_tbl),
352*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)addr) == -1) {
353*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read channel table at %p", addr);
354*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
355*7c478bd9Sstevel@tonic-gate 	}
356*7c478bd9Sstevel@tonic-gate 	if ((channel_name_sz = mdb_readstr(channel_name, CHAN_FIELD_MAX,
357*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)chan_tbl.scd_channel_name)) == -1) {
358*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read channel name at %p",
359*7c478bd9Sstevel@tonic-gate 		    chan_tbl.scd_channel_name);
360*7c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
361*7c478bd9Sstevel@tonic-gate 	}
362*7c478bd9Sstevel@tonic-gate 	if (channel_name_sz >= CHAN_FIELD_MAX - 1)
363*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&channel_name[CHAN_FIELD_MAX - 4], "...");
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	mdb_printf("%-?p %-16s %-8lu %-?p\n",
366*7c478bd9Sstevel@tonic-gate 	    addr, channel_name, chan_tbl.scd_ref_cnt,
367*7c478bd9Sstevel@tonic-gate 	    addr + offsetof(sysevent_channel_descriptor_t,
368*7c478bd9Sstevel@tonic-gate 	    scd_class_list_tbl));
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
371*7c478bd9Sstevel@tonic-gate }
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate typedef struct channel_walk_data {
374*7c478bd9Sstevel@tonic-gate 	int hash_index;
375*7c478bd9Sstevel@tonic-gate 	sysevent_channel_descriptor_t *hash_tbl[CHAN_HASH_SZ];
376*7c478bd9Sstevel@tonic-gate } channel_walk_data_t;
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate int
379*7c478bd9Sstevel@tonic-gate sysevent_channel_walk_init(mdb_walk_state_t *wsp)
380*7c478bd9Sstevel@tonic-gate {
381*7c478bd9Sstevel@tonic-gate 	channel_walk_data_t *ch_walker;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr != NULL) {
384*7c478bd9Sstevel@tonic-gate 		mdb_warn("sysevent_channel supports only global walks");
385*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
386*7c478bd9Sstevel@tonic-gate 	}
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	ch_walker = mdb_zalloc(sizeof (channel_walk_data_t), UM_SLEEP);
389*7c478bd9Sstevel@tonic-gate 	if (mdb_readvar(ch_walker->hash_tbl, "registered_channels")
390*7c478bd9Sstevel@tonic-gate 	    == -1) {
391*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read 'registered_channels'");
392*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
393*7c478bd9Sstevel@tonic-gate 	}
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)ch_walker->hash_tbl[0];
396*7c478bd9Sstevel@tonic-gate 	wsp->walk_data = ch_walker;
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
399*7c478bd9Sstevel@tonic-gate }
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate int
402*7c478bd9Sstevel@tonic-gate sysevent_channel_walk_step(mdb_walk_state_t *wsp)
403*7c478bd9Sstevel@tonic-gate {
404*7c478bd9Sstevel@tonic-gate 	int status = WALK_NEXT;
405*7c478bd9Sstevel@tonic-gate 	channel_walk_data_t *ch_walker;
406*7c478bd9Sstevel@tonic-gate 	sysevent_channel_descriptor_t scd;
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	ch_walker = (channel_walk_data_t *)wsp->walk_data;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	/* Skip over empty hash table entries */
411*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr != NULL) {
412*7c478bd9Sstevel@tonic-gate 		if (mdb_vread(&scd, sizeof (sysevent_channel_descriptor_t),
413*7c478bd9Sstevel@tonic-gate 		    wsp->walk_addr) == -1) {
414*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read channel at %p",
415*7c478bd9Sstevel@tonic-gate 			    wsp->walk_addr);
416*7c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
417*7c478bd9Sstevel@tonic-gate 		}
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 		status = wsp->walk_callback(wsp->walk_addr, NULL,
420*7c478bd9Sstevel@tonic-gate 		    wsp->walk_cbdata);
421*7c478bd9Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)scd.scd_next;
422*7c478bd9Sstevel@tonic-gate 	} else {
423*7c478bd9Sstevel@tonic-gate 		if (ch_walker->hash_index == CHAN_HASH_SZ) {
424*7c478bd9Sstevel@tonic-gate 			return (WALK_DONE);
425*7c478bd9Sstevel@tonic-gate 		} else {
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 			wsp->walk_addr = (uintptr_t)
428*7c478bd9Sstevel@tonic-gate 			    ch_walker->hash_tbl[ch_walker->hash_index];
429*7c478bd9Sstevel@tonic-gate 			ch_walker->hash_index++;
430*7c478bd9Sstevel@tonic-gate 		}
431*7c478bd9Sstevel@tonic-gate 	}
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	return (status);
434*7c478bd9Sstevel@tonic-gate }
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate void
437*7c478bd9Sstevel@tonic-gate sysevent_channel_walk_fini(mdb_walk_state_t *wsp)
438*7c478bd9Sstevel@tonic-gate {
439*7c478bd9Sstevel@tonic-gate 	channel_walk_data_t *ch_walker = wsp->walk_data;
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	mdb_free(ch_walker, sizeof (ch_walker));
442*7c478bd9Sstevel@tonic-gate }
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate int
445*7c478bd9Sstevel@tonic-gate sysevent_pend_walk_init(mdb_walk_state_t *wsp)
446*7c478bd9Sstevel@tonic-gate {
447*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
448*7c478bd9Sstevel@tonic-gate 		if (mdb_readvar(&wsp->walk_addr, "log_eventq_head") == -1) {
449*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read 'log_eventq_head'");
450*7c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
451*7c478bd9Sstevel@tonic-gate 		}
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (log_eventq_t), UM_SLEEP);
455*7c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
456*7c478bd9Sstevel@tonic-gate }
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate int
459*7c478bd9Sstevel@tonic-gate sysevent_walk_step(mdb_walk_state_t *wsp)
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate 	int status;
462*7c478bd9Sstevel@tonic-gate 	uintptr_t ev_arg_addr;
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
465*7c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (log_eventq_t),
468*7c478bd9Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
469*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read event queue at %p", wsp->walk_addr);
470*7c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 	ev_arg_addr = wsp->walk_addr + offsetof(log_eventq_t, arg.buf);
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(ev_arg_addr, wsp->walk_data,
475*7c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
476*7c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((log_eventq_t *)wsp->walk_data)->next);
477*7c478bd9Sstevel@tonic-gate 	return (status);
478*7c478bd9Sstevel@tonic-gate }
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate int
481*7c478bd9Sstevel@tonic-gate sysevent_sent_walk_init(mdb_walk_state_t *wsp)
482*7c478bd9Sstevel@tonic-gate {
483*7c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
484*7c478bd9Sstevel@tonic-gate 		if (mdb_readvar(&wsp->walk_addr, "log_eventq_sent") == -1) {
485*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read 'log_eventq_sent'");
486*7c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
487*7c478bd9Sstevel@tonic-gate 		}
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (log_eventq_t), UM_SLEEP);
490*7c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate void
494*7c478bd9Sstevel@tonic-gate sysevent_walk_fini(mdb_walk_state_t *wsp)
495*7c478bd9Sstevel@tonic-gate {
496*7c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (log_eventq_t));
497*7c478bd9Sstevel@tonic-gate }
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate #endif
500