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 { "rel ", ALLBITS, LDC_MODE_RELIABLE },
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
ldcinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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_RELIABLE) {
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
ldc_walk_init(mdb_walk_state_t * wsp)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
ldc_walk_step(mdb_walk_state_t * wsp)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
ldcmsg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
ldcmtbl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
ldcmhdl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
_mdb_init(void)509 _mdb_init(void)
510 {
511 return (&modinfo);
512 }
513