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