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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 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 /* 30 * This module provides debugging tools for the LDoms channels (ldc) 31 */ 32 33 #include <sys/mdb_modapi.h> 34 #include <sys/ldc.h> 35 #include <sys/ldc_impl.h> 36 #include <sys/hypervisor_api.h> 37 38 #define ALLBITS (u_longlong_t)-1 39 40 const mdb_bitmask_t ldc_mode_bits[] = { 41 { "raw ", ALLBITS, LDC_MODE_RAW }, 42 { "unrel ", ALLBITS, LDC_MODE_UNRELIABLE }, 43 { "stream", ALLBITS, LDC_MODE_STREAM }, 44 { NULL, 0, 0} 45 }; 46 47 const mdb_bitmask_t ldc_status_bits[] = { 48 { "init ", ALLBITS, LDC_INIT }, 49 { "open ", ALLBITS, LDC_OPEN }, 50 { "ready ", ALLBITS, LDC_READY }, 51 { "up ", ALLBITS, LDC_UP }, 52 { NULL, 0, 0} 53 }; 54 55 const mdb_bitmask_t ldc_tstate_bits[] = { 56 { "txq", TS_TXQ_RDY, TS_TXQ_RDY }, 57 { "rxq", TS_RXQ_RDY, TS_RXQ_RDY }, 58 { "hv_qconf", TS_QCONF_RDY, TS_QCONF_RDY }, 59 { "cnex_reg", TS_CNEX_RDY, TS_CNEX_RDY }, 60 { "hv_link_rdy", TS_LINK_READY, TS_LINK_READY }, 61 { "ver_done", TS_VER_DONE, TS_VER_DONE }, 62 { "hs_done", TS_HSHAKE_DONE, TS_HSHAKE_DONE }, 63 { NULL, 0, 0} 64 }; 65 66 const mdb_bitmask_t ldc_hstate_bits[] = { 67 { "snt_ver", TS_SENT_VER, TS_SENT_VER }, 68 { "snt_rts", TS_SENT_RTS, TS_SENT_RTS }, 69 { "rcv_rtr", TS_RCVD_RTR, TS_RCVD_RTR }, 70 { "snt_rdx", TS_SENT_RDX, TS_SENT_RDX }, 71 { "rcv_ver", TS_RCVD_VER, TS_RCVD_VER }, 72 { "rcv_rts", TS_RCVD_RTS, TS_RCVD_RTS }, 73 { "snt_rtr", TS_SENT_RTR, TS_SENT_RTR }, 74 { "rcv_rdx", TS_RCVD_RDX, TS_RCVD_RDX }, 75 { NULL, 0, 0} 76 }; 77 78 const mdb_bitmask_t ldc_class_bits[] = { 79 { "generic ", ALLBITS, LDC_DEV_GENERIC }, 80 { "blk ", ALLBITS, LDC_DEV_BLK }, 81 { "blk_svc ", ALLBITS, LDC_DEV_BLK_SVC }, 82 { "net ", ALLBITS, LDC_DEV_NT }, 83 { "net_svc ", ALLBITS, LDC_DEV_NT_SVC }, 84 { "serial ", ALLBITS, LDC_DEV_SERIAL }, 85 { NULL, 0, 0} 86 }; 87 88 const mdb_bitmask_t ldc_intrstate_bits[] = { 89 { "none ", ALLBITS, LDC_INTR_NONE }, 90 { "active ", ALLBITS, LDC_INTR_ACTIVE }, 91 { "pending", ALLBITS, LDC_INTR_PEND }, 92 { NULL, 0, 0} 93 }; 94 95 const mdb_bitmask_t ldc_linkstate_bits[] = { 96 { "down ", ALLBITS, LDC_CHANNEL_DOWN }, 97 { "reset", ALLBITS, LDC_CHANNEL_RESET }, 98 { "up ", ALLBITS, LDC_CHANNEL_UP }, 99 { NULL, 0, 0} 100 }; 101 102 const mdb_bitmask_t msg_type_bits[] = { 103 { "ctrl", ALLBITS, LDC_CTRL }, 104 { "data", ALLBITS, LDC_DATA }, 105 { "err ", ALLBITS, LDC_ERR }, 106 { NULL, 0, 0} 107 }; 108 109 const mdb_bitmask_t msg_stype_bits[] = { 110 { "info ", ALLBITS, LDC_INFO }, 111 { "ack ", ALLBITS, LDC_ACK }, 112 { "nack ", ALLBITS, LDC_NACK }, 113 { NULL, 0, 0} 114 }; 115 116 const mdb_bitmask_t msg_ctrl_bits[] = { 117 { "ver ", ALLBITS, LDC_VER }, 118 { "rts ", ALLBITS, LDC_RTS }, 119 { "rtr ", ALLBITS, LDC_RTR }, 120 { "rdx ", ALLBITS, LDC_RDX }, 121 { NULL, 0, 0} 122 }; 123 124 const mdb_bitmask_t mhdl_status_bits[] = { 125 { "unbound", ALLBITS, LDC_UNBOUND }, 126 { "bound ", LDC_BOUND, LDC_BOUND }, 127 { "mapped ", LDC_MAPPED, LDC_MAPPED }, 128 { NULL, 0, 0} 129 }; 130 131 const mdb_bitmask_t mhdl_type_bits[] = { 132 { "shadow ", ALLBITS, LDC_SHADOW_MAP }, 133 { "direct ", ALLBITS, LDC_DIRECT_MAP }, 134 { "io ", ALLBITS, LDC_IO_MAP }, 135 { NULL, 0, 0} 136 }; 137 138 const mdb_bitmask_t mhdl_perm_bits[] = { 139 { "r-- ", ALLBITS, LDC_MEM_R }, 140 { "-w- ", ALLBITS, LDC_MEM_W }, 141 { "--x ", ALLBITS, LDC_MEM_X }, 142 { "rw- ", ALLBITS, LDC_MEM_RW }, 143 { "rwx ", ALLBITS, LDC_MEM_RWX }, 144 { NULL, 0, 0} 145 }; 146 147 148 /* 149 * Print LDC channel information 150 */ 151 int 152 ldcinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 153 { 154 uint_t verbose = FALSE; 155 ldc_chan_t ldcp; 156 157 /* 158 * If no ldc_chan_t address was specified on the command line, 159 * we can print out all ldc channels by invoking the 160 * walker, using this dcmd itself as the callback. 161 */ 162 if (!(flags & DCMD_ADDRSPEC)) { 163 if (mdb_walk_dcmd("ldcinfo", "ldcinfo", argc, argv) == -1) { 164 mdb_warn("failed to walk 'ldcinfo'"); 165 return (DCMD_ERR); 166 } 167 return (DCMD_OK); 168 } 169 170 171 if (mdb_vread(&ldcp, sizeof (ldcp), addr) != sizeof (ldcp)) { 172 mdb_warn("failed to read ldc_chan_t at %p", addr); 173 return (DCMD_ERR); 174 } 175 176 177 if (mdb_getopts(argc, argv, 178 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) { 179 return (DCMD_USAGE); 180 } 181 182 if (DCMD_HDRSPEC(flags)) { 183 mdb_printf("%-5s %-13s %-6s %-8s %-6s %-6s %-6s %-8s\n", 184 "ID", "ADDR", "MODE", "DEVCLASS", "STATUS", "TSTATE", 185 "HSTATE", "HV_LINK"); 186 } 187 188 mdb_printf("0x%-3x 0x%p %b %b %b 0x%-4x 0x%-4x %b\n", 189 ldcp.id, addr, ldcp.mode, ldc_mode_bits, 190 ldcp.devclass, ldc_class_bits, 191 ldcp.status, ldc_status_bits, ldcp.tstate, ldcp.hstate, 192 ldcp.link_state, ldc_linkstate_bits); 193 194 if (verbose) { 195 mdb_printf("Link State: %b\n", ldcp.tstate, ldc_tstate_bits); 196 mdb_printf("Hshake State: %b\n", ldcp.hstate, ldc_hstate_bits); 197 mdb_printf("Callback: %a(0x%p) - %s\n", 198 ldcp.cb, ldcp.cb_arg, 199 (ldcp.cb_enabled == 1) ? "enabled" : "disabled"); 200 mdb_printf("Tx Info: 0x%p len=0x%lx hd=0x%lx tl=0x%lx " 201 "intr=%b\n", ldcp.tx_q_va, ldcp.tx_q_entries, ldcp.tx_head, 202 ldcp.tx_tail, ldcp.tx_intr_state, ldc_intrstate_bits); 203 mdb_printf("Rx Info: 0x%p len=0x%lx intr=%b\n", 204 ldcp.rx_q_va, ldcp.rx_q_entries, 205 ldcp.rx_intr_state, ldc_intrstate_bits); 206 if (ldcp.mode == LDC_MODE_STREAM) { 207 mdb_printf("Rx Dq Info: 0x%p len=0x%lx hd=0x%lx " 208 "tl=0x%lx ackhd=0x%lx", ldcp.rx_dq_va, 209 ldcp.rx_dq_entries, ldcp.rx_dq_head, 210 ldcp.rx_dq_tail, ldcp.rx_ack_head); 211 mdb_printf("Stream: buf=0x%p off=0x%lx remains=0x%lx\n", 212 ldcp.stream_bufferp, ldcp.stream_offset, 213 ldcp.stream_remains); 214 } 215 if (ldcp.mtbl != NULL || ldcp.mhdl_list != NULL) 216 mdb_printf("Memory: mtbl=0x%p mhdl_list=0x%p\n", 217 ldcp.mtbl, ldcp.mhdl_list); 218 if (ldcp.exp_dring_list != NULL || ldcp.imp_dring_list != NULL) 219 mdb_printf("Desc Ring: exported=0x%p imported=0x%p\n", 220 ldcp.exp_dring_list, ldcp.imp_dring_list); 221 mdb_printf("\n"); 222 } 223 return (DCMD_OK); 224 } 225 226 227 /* 228 * ldcinfo walker initialization 229 */ 230 int 231 ldc_walk_init(mdb_walk_state_t *wsp) 232 { 233 ldc_soft_state_t softstate; 234 235 /* Must have a start addr. */ 236 if (wsp->walk_addr == NULL) { 237 if (mdb_readvar(&wsp->walk_addr, "ldcssp") == -1) { 238 mdb_warn("failed to read 'ldcssp'"); 239 return (WALK_ERR); 240 } 241 242 if (wsp->walk_addr == NULL) 243 return (WALK_DONE); 244 245 if (mdb_vread(&softstate, sizeof (softstate), wsp->walk_addr) 246 != sizeof (softstate)) { 247 mdb_warn("failed to read softstate %p", wsp->walk_addr); 248 return (WALK_ERR); 249 } 250 251 wsp->walk_addr = (uintptr_t)softstate.chan_list; 252 } 253 254 return (WALK_NEXT); 255 } 256 257 /* 258 * ldcinfo walker step routine. 259 */ 260 int 261 ldc_walk_step(mdb_walk_state_t *wsp) 262 { 263 int status; 264 ldc_chan_t ldcp; 265 266 if (wsp->walk_addr == NULL) 267 return (WALK_DONE); 268 269 if (mdb_vread(&ldcp, sizeof (ldc_chan_t), wsp->walk_addr) == -1) { 270 mdb_warn("failed to read at %p", wsp->walk_addr); 271 272 return (WALK_ERR); 273 } 274 275 status = wsp->walk_callback(wsp->walk_addr, &ldcp, 276 wsp->walk_cbdata); 277 wsp->walk_addr = (uintptr_t)ldcp.next; 278 279 return (status); 280 } 281 282 283 /* 284 * dcmd to print ldc packet information 285 * 286 * arg0 - count (number of pkts to print) 287 */ 288 int 289 ldcmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 290 { 291 ldc_msg_t msg; 292 uint64_t count = 1; 293 int i; 294 295 /* 296 * If no ldc_msg_t address was specified on the command line, 297 * print usage. 298 */ 299 if (!(flags & DCMD_ADDRSPEC)) { 300 return (DCMD_USAGE); 301 } 302 303 /* chk if we need to print more that one pkt */ 304 if (argc != 0) { 305 const mdb_arg_t *arg = &argv[0]; 306 307 if (arg->a_type == MDB_TYPE_IMMEDIATE) 308 count = arg->a_un.a_val; 309 else 310 count = (uint64_t)mdb_strtoull(arg->a_un.a_str); 311 } 312 313 /* print header */ 314 mdb_printf("%-13s %-10s %-4s %-5s %-4s %-11s %-4s %-10s\n", 315 "ADDR", "SEQID", "TYPE", "STYPE", "CTRL", "ENVELOPE", 316 "SIZE", "ACKID"); 317 318 /* print pkt */ 319 for (i = 0; i < count; i++) { 320 321 if (mdb_vread(&msg, sizeof (msg), addr) != sizeof (msg)) { 322 mdb_warn("failed to read ldc_msg_t at %p", addr); 323 return (DCMD_ERR); 324 } 325 326 mdb_printf("0x%p 0x%-8x %b %b", addr, msg.seqid, 327 msg.type, msg_type_bits, msg.stype, msg_stype_bits); 328 329 if (msg.type == LDC_CTRL) 330 mdb_printf(" %b ", msg.ctrl, msg_ctrl_bits); 331 else 332 mdb_printf(" %-4s ", "--"); 333 334 mdb_printf("%-5s %-5s", 335 ((msg.env & LDC_FRAG_START) != 0) ? "start" : "--", 336 ((msg.env & LDC_FRAG_STOP) != 0) ? "stop" : "--"); 337 338 /* print size */ 339 if (msg.type == LDC_DATA && msg.stype == LDC_INFO) 340 mdb_printf(" 0x%-2x ", (msg.env & LDC_LEN_MASK)); 341 else 342 mdb_printf(" %-4s ", "--"); 343 344 /* print ackid if data/ack */ 345 if (msg.type == LDC_DATA && msg.stype == LDC_ACK) 346 mdb_printf("0x%-8x\n", msg.ackid); 347 else 348 mdb_printf("%-10s\n", "--"); 349 350 /* next packet */ 351 addr = addr + LDC_PACKET_SIZE; 352 } 353 354 return (DCMD_OK); 355 } 356 357 358 /* 359 * Print LDC map table information 360 */ 361 int 362 ldcmtbl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 363 { 364 uint_t verbose = FALSE; 365 ldc_mtbl_t mtbl; 366 ldc_mte_slot_t mte; 367 uintptr_t mteaddr; 368 int i; 369 370 /* 371 * If no ldc_mtbl_t address was specified on the command line, 372 * print usage. 373 */ 374 if (!(flags & DCMD_ADDRSPEC)) { 375 return (DCMD_USAGE); 376 } 377 378 if (mdb_vread(&mtbl, sizeof (mtbl), addr) != sizeof (mtbl)) { 379 mdb_warn("failed to read ldc_mtbl_t at %p", addr); 380 return (DCMD_ERR); 381 } 382 383 mdb_printf("Map Table: addr=0x%p total=%ld free=%ld tbl_base=0x%p\n", 384 addr, mtbl.num_entries, mtbl.num_avail, mtbl.table); 385 386 if (mdb_getopts(argc, argv, 387 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) { 388 return (DCMD_USAGE); 389 } 390 if (!verbose) 391 return (DCMD_OK); 392 393 /* print table header */ 394 mdb_printf("\n%-4s %-13s %-2s %-2s %-2s %-2s %-2s %-2s %-2s %-5s\n", 395 "IDX", "RA_PFN", "CW", "CR", "IW", "IR", "X", "W", "R", "PGSZC"); 396 397 /* print each table entry */ 398 mteaddr = (uintptr_t)mtbl.table; 399 for (i = 0; i < mtbl.num_entries; i++) { 400 if (mdb_vread(&mte, sizeof (mte), mteaddr) != sizeof (mte)) { 401 return (DCMD_ABORT); 402 } 403 404 /* skip empty entries */ 405 if (mte.entry.ll != 0) { 406 mdb_printf("%-4d 0x%-11x %-2d %-2d %-2d %-2d " 407 "%-2d %-2d %-2d 0x%-2x\n", 408 i, mte.entry.mte_bit.rpfn, mte.entry.mte_bit.cw, 409 mte.entry.mte_bit.cr, mte.entry.mte_bit.iw, 410 mte.entry.mte_bit.ir, mte.entry.mte_bit.x, 411 mte.entry.mte_bit.w, mte.entry.mte_bit.r, 412 mte.entry.mte_bit.pgszc); 413 } 414 mteaddr = mteaddr + sizeof (ldc_mte_slot_t); 415 } 416 return (DCMD_OK); 417 } 418 419 420 421 /* 422 * Print LDC channel memory handle information 423 */ 424 int 425 ldcmhdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 426 { 427 ldc_mhdl_t mhdl; 428 ldc_memseg_t memseg; 429 uint64_t count = 1; 430 int i; 431 432 /* 433 * If no ldc_msg_t address was specified on the command line, 434 * print usage. 435 */ 436 if (!(flags & DCMD_ADDRSPEC)) { 437 return (DCMD_USAGE); 438 } 439 440 /* chk if we need to print more that one pkt */ 441 if (argc != 0) { 442 const mdb_arg_t *arg = &argv[0]; 443 444 if (arg->a_type == MDB_TYPE_IMMEDIATE) 445 count = arg->a_un.a_val; 446 else 447 count = (uint64_t)mdb_strtoull(arg->a_un.a_str); 448 } 449 450 mdb_printf("%-13s %-7s %-7s %-4s %-13s %-13s %-10s\n", 451 "ADDR", "STATUS", "MAPTYPE", "PERM", "MEMSEG", "VADDR", "SIZE"); 452 453 /* print pkt */ 454 for (i = 0; i < count; i++) { 455 456 if (mdb_vread(&mhdl, sizeof (mhdl), addr) != sizeof (mhdl)) { 457 mdb_warn("failed to read ldc_mhdl_t at %p", addr); 458 return (DCMD_ERR); 459 } 460 461 mdb_printf("0x%p %b %b %b 0x%p ", 462 addr, mhdl.status, mhdl_status_bits, 463 mhdl.mtype, mhdl_type_bits, mhdl.perm, mhdl_perm_bits, 464 mhdl.memseg); 465 466 if (mhdl.memseg != NULL) { 467 if (mdb_vread(&memseg, sizeof (memseg), 468 (uintptr_t)mhdl.memseg) != sizeof (memseg)) { 469 mdb_warn("failed to read ldc_memseg_t at %p", 470 mhdl.memseg); 471 return (DCMD_ERR); 472 } 473 474 mdb_printf("0x%p 0x%-8lx\n", memseg.vaddr, memseg.size); 475 } else { 476 mdb_printf("\n"); 477 } 478 479 if ((addr = (uintptr_t)mhdl.next) == NULL) 480 break; 481 } 482 483 return (DCMD_OK); 484 } 485 486 487 /* 488 * MDB module linkage information: 489 */ 490 static const mdb_dcmd_t dcmds[] = { 491 { "ldcinfo", "?[-v]", "LDom channel information", ldcinfo }, 492 { "ldcmsg", ":[cnt]", "LDom channel message", ldcmsg }, 493 { "ldcmtbl", ":[-v]", "LDom channel map table", ldcmtbl }, 494 { "ldcmhdl", ":[cnt]", "LDom channel memory handles", ldcmhdl }, 495 { NULL } 496 }; 497 498 static const mdb_walker_t walkers[] = { 499 { "ldcinfo", "List all LDom channels", 500 ldc_walk_init, ldc_walk_step, NULL }, 501 { NULL } 502 }; 503 504 static const mdb_modinfo_t modinfo = { 505 MDB_API_VERSION, dcmds, walkers 506 }; 507 508 const mdb_modinfo_t * 509 _mdb_init(void) 510 { 511 return (&modinfo); 512 } 513