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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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