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