xref: /titanic_52/usr/src/cmd/mdb/sun4v/modules/ldc/ldc.c (revision 948f2876ce2a3010558f4f6937e16086ebcd36f2)
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 2007 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("Stream: buf=0x%p off=0x%lx remains=0x%lx\n",
208 			    ldcp.stream_bufferp, ldcp.stream_offset,
209 			    ldcp.stream_remains);
210 		}
211 		if (ldcp.mtbl != NULL || ldcp.mhdl_list != NULL)
212 			mdb_printf("Memory: mtbl=0x%p mhdl_list=0x%p\n",
213 			    ldcp.mtbl, ldcp.mhdl_list);
214 		if (ldcp.exp_dring_list != NULL || ldcp.imp_dring_list != NULL)
215 			mdb_printf("Desc Ring: exported=0x%p imported=0x%p\n",
216 			    ldcp.exp_dring_list, ldcp.imp_dring_list);
217 		mdb_printf("\n");
218 	}
219 	return (DCMD_OK);
220 }
221 
222 
223 /*
224  * ldcinfo walker initialization
225  */
226 int
227 ldc_walk_init(mdb_walk_state_t *wsp)
228 {
229 	ldc_soft_state_t	softstate;
230 
231 	/* Must have a start addr.  */
232 	if (wsp->walk_addr == NULL) {
233 		if (mdb_readvar(&wsp->walk_addr, "ldcssp") == -1) {
234 			mdb_warn("failed to read 'ldcssp'");
235 			return (WALK_ERR);
236 		}
237 
238 		if (wsp->walk_addr == NULL)
239 			return (WALK_DONE);
240 
241 		if (mdb_vread(&softstate, sizeof (softstate), wsp->walk_addr)
242 		    != sizeof (softstate)) {
243 			mdb_warn("failed to read softstate %p", wsp->walk_addr);
244 			return (WALK_ERR);
245 		}
246 
247 		wsp->walk_addr = (uintptr_t)softstate.chan_list;
248 	}
249 
250 	return (WALK_NEXT);
251 }
252 
253 /*
254  * ldcinfo walker step routine.
255  */
256 int
257 ldc_walk_step(mdb_walk_state_t *wsp)
258 {
259 	int			status;
260 	ldc_chan_t		ldcp;
261 
262 	if (wsp->walk_addr == NULL)
263 		return (WALK_DONE);
264 
265 	if (mdb_vread(&ldcp, sizeof (ldc_chan_t), wsp->walk_addr) == -1) {
266 		mdb_warn("failed to read at %p", wsp->walk_addr);
267 
268 		return (WALK_ERR);
269 	}
270 
271 	status = wsp->walk_callback(wsp->walk_addr, &ldcp,
272 	    wsp->walk_cbdata);
273 	wsp->walk_addr = (uintptr_t)ldcp.next;
274 
275 	return (status);
276 }
277 
278 
279 /*
280  * dcmd to print ldc packet information
281  *
282  * arg0 - count (number of pkts to print)
283  */
284 int
285 ldcmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
286 {
287 	ldc_msg_t	msg;
288 	uint64_t 	count = 1;
289 	int		i;
290 
291 	/*
292 	 * If no ldc_msg_t address was specified on the command line,
293 	 * print usage.
294 	 */
295 	if (!(flags & DCMD_ADDRSPEC)) {
296 		return (DCMD_USAGE);
297 	}
298 
299 	/* chk if we need to print more that one pkt */
300 	if (argc != 0) {
301 		const mdb_arg_t *arg = &argv[0];
302 
303 		if (arg->a_type == MDB_TYPE_IMMEDIATE)
304 			count = arg->a_un.a_val;
305 		else
306 			count = (uint64_t)mdb_strtoull(arg->a_un.a_str);
307 	}
308 
309 	/* print header */
310 	mdb_printf("%-13s %-10s %-4s %-5s %-4s %-11s %-4s %-10s\n",
311 	    "ADDR", "SEQID", "TYPE", "STYPE", "CTRL", "ENVELOPE",
312 	    "SIZE", "ACKID");
313 
314 	/* print pkt */
315 	for (i = 0; i < count; i++) {
316 
317 		if (mdb_vread(&msg, sizeof (msg), addr) != sizeof (msg)) {
318 			mdb_warn("failed to read ldc_msg_t at %p", addr);
319 			return (DCMD_ERR);
320 		}
321 
322 		mdb_printf("0x%p 0x%-8x %b %b", addr, msg.seqid,
323 		    msg.type, msg_type_bits, msg.stype, msg_stype_bits);
324 
325 		if (msg.type == LDC_CTRL)
326 			mdb_printf(" %b ", msg.ctrl, msg_ctrl_bits);
327 		else
328 			mdb_printf(" %-4s ", "--");
329 
330 		mdb_printf("%-5s %-5s",
331 		    ((msg.env & LDC_FRAG_START) != 0) ? "start" : "--",
332 		    ((msg.env & LDC_FRAG_STOP) != 0) ? "stop" : "--");
333 
334 		/* print size */
335 		if (msg.type == LDC_DATA && msg.stype == LDC_INFO)
336 			mdb_printf(" 0x%-2x ", (msg.env & LDC_LEN_MASK));
337 		else
338 			mdb_printf(" %-4s ", "--");
339 
340 		/* print ackid if data/ack */
341 		if (msg.type == LDC_DATA && msg.stype == LDC_ACK)
342 			mdb_printf("0x%-8x\n", msg.ackid);
343 		else
344 			mdb_printf("%-10s\n", "--");
345 
346 		/* next packet */
347 		addr = addr + LDC_PACKET_SIZE;
348 	}
349 
350 	return (DCMD_OK);
351 }
352 
353 
354 /*
355  * Print LDC map table information
356  */
357 int
358 ldcmtbl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
359 {
360 	uint_t		verbose = FALSE;
361 	ldc_mtbl_t	mtbl;
362 	ldc_mte_slot_t	mte;
363 	uintptr_t	mteaddr;
364 	int		i;
365 
366 	/*
367 	 * If no ldc_mtbl_t address was specified on the command line,
368 	 * print usage.
369 	 */
370 	if (!(flags & DCMD_ADDRSPEC)) {
371 		return (DCMD_USAGE);
372 	}
373 
374 	if (mdb_vread(&mtbl, sizeof (mtbl), addr) != sizeof (mtbl)) {
375 		mdb_warn("failed to read ldc_mtbl_t at %p", addr);
376 		return (DCMD_ERR);
377 	}
378 
379 	mdb_printf("Map Table: addr=0x%p total=%ld free=%ld tbl_base=0x%p\n",
380 	    addr, mtbl.num_entries, mtbl.num_avail, mtbl.table);
381 
382 	if (mdb_getopts(argc, argv,
383 		'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) {
384 		return (DCMD_USAGE);
385 	}
386 	if (!verbose)
387 		return (DCMD_OK);
388 
389 	/* print table header */
390 	mdb_printf("\n%-4s  %-13s %-2s %-2s %-2s %-2s %-2s %-2s %-2s %-5s\n",
391 	    "IDX", "RA_PFN", "CW", "CR", "IW", "IR", "X", "W", "R", "PGSZC");
392 
393 	/* print each table entry */
394 	mteaddr = (uintptr_t)mtbl.table;
395 	for (i = 0; i < mtbl.num_entries; i++) {
396 		if (mdb_vread(&mte, sizeof (mte), mteaddr) != sizeof (mte)) {
397 			return (DCMD_ABORT);
398 		}
399 
400 		/* skip empty entries */
401 		if (mte.entry.ll != 0) {
402 			mdb_printf("%-4d  0x%-11x %-2d %-2d %-2d %-2d "
403 			    "%-2d %-2d %-2d 0x%-2x\n",
404 			    i, mte.entry.mte_bit.rpfn, mte.entry.mte_bit.cw,
405 			    mte.entry.mte_bit.cr, mte.entry.mte_bit.iw,
406 			    mte.entry.mte_bit.ir, mte.entry.mte_bit.x,
407 			    mte.entry.mte_bit.w, mte.entry.mte_bit.r,
408 			    mte.entry.mte_bit.pgszc);
409 		}
410 		mteaddr = mteaddr + sizeof (ldc_mte_slot_t);
411 	}
412 	return (DCMD_OK);
413 }
414 
415 
416 
417 /*
418  * Print LDC channel memory handle information
419  */
420 int
421 ldcmhdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
422 {
423 	ldc_mhdl_t	mhdl;
424 	ldc_memseg_t	memseg;
425 	uint64_t	count = 1;
426 	int		i;
427 
428 	/*
429 	 * If no ldc_msg_t address was specified on the command line,
430 	 * print usage.
431 	 */
432 	if (!(flags & DCMD_ADDRSPEC)) {
433 		return (DCMD_USAGE);
434 	}
435 
436 	/* chk if we need to print more that one pkt */
437 	if (argc != 0) {
438 		const mdb_arg_t *arg = &argv[0];
439 
440 		if (arg->a_type == MDB_TYPE_IMMEDIATE)
441 			count = arg->a_un.a_val;
442 		else
443 			count = (uint64_t)mdb_strtoull(arg->a_un.a_str);
444 	}
445 
446 	mdb_printf("%-13s  %-7s %-7s %-4s %-13s %-13s %-10s\n",
447 	    "ADDR", "STATUS", "MAPTYPE", "PERM", "MEMSEG", "VADDR", "SIZE");
448 
449 	/* print pkt */
450 	for (i = 0; i < count; i++) {
451 
452 		if (mdb_vread(&mhdl, sizeof (mhdl), addr) != sizeof (mhdl)) {
453 			mdb_warn("failed to read ldc_mhdl_t at %p", addr);
454 			return (DCMD_ERR);
455 		}
456 
457 		mdb_printf("0x%p  %b %b %b 0x%p ",
458 		    addr, mhdl.status, mhdl_status_bits,
459 		    mhdl.mtype, mhdl_type_bits, mhdl.perm, mhdl_perm_bits,
460 		    mhdl.memseg);
461 
462 		if (mhdl.memseg != NULL) {
463 			if (mdb_vread(&memseg, sizeof (memseg),
464 				(uintptr_t)mhdl.memseg) != sizeof (memseg)) {
465 				mdb_warn("failed to read ldc_memseg_t at %p",
466 				    mhdl.memseg);
467 				return (DCMD_ERR);
468 			}
469 
470 			mdb_printf("0x%p 0x%-8lx\n", memseg.vaddr, memseg.size);
471 		} else {
472 			mdb_printf("\n");
473 		}
474 
475 		if ((addr = (uintptr_t)mhdl.next) == NULL)
476 			break;
477 	}
478 
479 	return (DCMD_OK);
480 }
481 
482 
483 /*
484  * MDB module linkage information:
485  */
486 static const mdb_dcmd_t dcmds[] = {
487 	{ "ldcinfo", "?[-v]",  "LDom channel information", ldcinfo },
488 	{ "ldcmsg",  ":[cnt]", "LDom channel message", ldcmsg },
489 	{ "ldcmtbl", ":[-v]",  "LDom channel map table", ldcmtbl },
490 	{ "ldcmhdl", ":[cnt]", "LDom channel memory handles", ldcmhdl },
491 	{ NULL }
492 };
493 
494 static const mdb_walker_t walkers[] = {
495 	{ "ldcinfo", "List all LDom channels",
496 	    ldc_walk_init, ldc_walk_step, NULL },
497 	{ NULL }
498 };
499 
500 static const mdb_modinfo_t modinfo = {
501 	MDB_API_VERSION, dcmds, walkers
502 };
503 
504 const mdb_modinfo_t *
505 _mdb_init(void)
506 {
507 	return (&modinfo);
508 }
509