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 2005 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  * mdb dcmds for selected structures from
31  * usr/src/uts/common/sys/crypto/impl.h
32  */
33 #include <stdio.h>
34 #include <sys/mdb_modapi.h>
35 #include <sys/modctl.h>
36 #include <sys/types.h>
37 #include <sys/crypto/api.h>
38 #include <sys/crypto/common.h>
39 #include <sys/crypto/impl.h>
40 #include "crypto_cmds.h"
41 
42 int
43 kcf_sched_info(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
44 {
45 	kcf_sched_info_t sched;
46 	kcf_sched_info_t *sinfo = &sched;
47 
48 	if (!(flags & DCMD_ADDRSPEC)) {
49 		if ((argc == 1) && (argv->a_type == MDB_TYPE_IMMEDIATE))
50 			sinfo = (kcf_sched_info_t *)(uintptr_t)argv->a_un.a_val;
51 		else
52 			return (DCMD_USAGE);
53 	} else if (addr == NULL)	/* not allowed with DCMD_ADDRSPEC */
54 		return (DCMD_USAGE);
55 	else {
56 		if (mdb_vread(sinfo, sizeof (kcf_sched_info_t), addr) == -1) {
57 			mdb_warn("cannot read %p", addr);
58 			return (DCMD_ERR);
59 		}
60 	}
61 	mdb_printf("ks_ndispatches:\t%llu\n", sinfo->ks_ndispatches);
62 	mdb_printf("ks_nfails:\t%llu\n", sinfo->ks_nfails);
63 	mdb_printf("ks_nbusy_rval:\t%llu\n", sinfo->ks_nbusy_rval);
64 	mdb_printf("ks_ntaskq:\t%p\n", sinfo->ks_taskq);
65 	return (DCMD_OK);
66 }
67 
68 static const char *prov_states[] = {
69 	"none",
70 	"KCF_PROV_ALLOCATED",
71 	"KCF_PROV_UNVERIFIED",
72 	"KCF_PROV_READY",
73 	"KCF_PROV_BUSY",
74 	"KCF_PROV_FAILED",
75 	"KCF_PROV_DISABLED",
76 	"KCF_PROV_REMOVED",
77 	"KCF_PROV_FREED"
78 };
79 
80 static void
81 pr_kstat_named(kstat_named_t *ks)
82 {
83 	mdb_inc_indent(4);
84 
85 	mdb_printf("name = %s\n", ks->name);
86 	mdb_printf("value = ");
87 
88 	/*
89 	 * The only data type used for the provider kstats is uint64.
90 	 */
91 	switch (ks->data_type) {
92 	case KSTAT_DATA_UINT64:
93 #if defined(_LP64) || defined(_LONGLONG_TYPE)
94 		mdb_printf("%llu\n", ks->value.ui64);
95 #endif
96 		break;
97 	default:
98 		mdb_warn("Incorrect data type for kstat.\n");
99 	}
100 
101 	mdb_dec_indent(4);
102 }
103 
104 /*ARGSUSED*/
105 int
106 kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
107 {
108 	kcf_provider_desc_t desc;
109 	kcf_provider_desc_t *ptr;
110 	char string[MAXNAMELEN + 1];
111 	int i, j;
112 	crypto_mech_info_t *mech_pointer;
113 	mdb_arg_t arg;
114 
115 	if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC)
116 		return (DCMD_USAGE);
117 	ptr = (kcf_provider_desc_t *)addr;
118 
119 #ifdef DEBUG
120 	mdb_printf("DEBUG: reading kcf_provider_desc at %p\n", ptr);
121 #endif
122 
123 	if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), (uintptr_t)ptr)
124 	    == -1) {
125 		    mdb_warn("cannot read at address %p", (uintptr_t)ptr);
126 		    return (DCMD_ERR);
127 	}
128 	mdb_printf("%<b>kcf_provider_desc at %p%</b>\n", ptr);
129 
130 	switch (desc.pd_prov_type) {
131 	case CRYPTO_HW_PROVIDER:
132 		mdb_printf("pd_prov_type:\t\tCRYPTO_HW_PROVIDER\n");
133 		break;
134 	case CRYPTO_SW_PROVIDER:
135 		mdb_printf("pd_prov_type:\t\tCRYPTO_SW_PROVIDER\n");
136 		break;
137 	case CRYPTO_LOGICAL_PROVIDER:
138 		mdb_printf("pd_prov_type:\t\tCRYPTO_LOGICAL_PROVIDER\n");
139 		break;
140 	default:
141 		mdb_printf("bad pd_prov_type:\t%d\n", desc.pd_prov_type);
142 	}
143 
144 	mdb_printf("pd_prov_handle:\t\t%p\n", desc.pd_prov_handle);
145 	mdb_printf("pd_kcf_prov_handle:\t%u\n", desc.pd_kcf_prov_handle);
146 	mdb_printf("pd_prov_id:\t\t%u\n", desc.pd_prov_id);
147 	if (desc.pd_description == NULL)
148 		mdb_printf("pd_description:\t\tNULL\n");
149 	else if (mdb_readstr(string, MAXNAMELEN + 1,
150 		    (uintptr_t)desc.pd_description) == -1) {
151 		mdb_warn("cannot read %p", desc.pd_description);
152 	} else
153 	    mdb_printf("pd_description:\t\t%s\n", string);
154 
155 	mdb_printf("pd_ops_vector:\t\t%p\n", desc.pd_ops_vector);
156 	mdb_printf("pd_mech_list_count:\t%u\n", desc.pd_mech_list_count);
157 	/* mechanisms */
158 	mdb_inc_indent(4);
159 	for (i = 0; i < desc.pd_mech_list_count; i++) {
160 		mech_pointer = desc.pd_mechanisms + i;
161 		mdb_call_dcmd("crypto_mech_info",
162 			(uintptr_t)mech_pointer, DCMD_ADDRSPEC, 0, NULL);
163 	}
164 	mdb_dec_indent(4);
165 	mdb_printf("pd_map_mechnums:\n");
166 	mdb_inc_indent(8);
167 	for (i = 0; i < KCF_OPS_CLASSSIZE; i++) {
168 	    for (j = 0; j < KCF_MAXMECHTAB; j++) {
169 		mdb_printf("%llu ",
170 		    desc.pd_map_mechnums[i][j]);
171 	    }
172 	    mdb_printf("\n");
173 	}
174 	mdb_dec_indent(8);
175 	mdb_printf("pd_stats:\t\t%p\n", desc.pd_stats);
176 	mdb_printf("pd_ks_data.ps_ops_total:\n", desc.pd_ks_data.ps_ops_total);
177 	pr_kstat_named(&desc.pd_ks_data.ps_ops_total);
178 	mdb_printf("pd_ks_data.ps_ops_passed:\n",
179 	    desc.pd_ks_data.ps_ops_passed);
180 	pr_kstat_named(&desc.pd_ks_data.ps_ops_passed);
181 	mdb_printf("pd_ks_data.ps_ops_failed:\n",
182 	    desc.pd_ks_data.ps_ops_failed);
183 	pr_kstat_named(&desc.pd_ks_data.ps_ops_failed);
184 	mdb_printf("pd_ks_data.ps_ops_busy_rval:\n",
185 	    desc.pd_ks_data.ps_ops_busy_rval);
186 	pr_kstat_named(&desc.pd_ks_data.ps_ops_busy_rval);
187 
188 	mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat);
189 	mdb_printf("kcf_sched_info:\n");
190 	/* print pd_sched_info via existing function */
191 	mdb_inc_indent(8);
192 	arg.a_type = MDB_TYPE_IMMEDIATE;
193 	arg.a_un.a_val = (uintmax_t)(uintptr_t)&desc.pd_sched_info;
194 	mdb_call_dcmd("kcf_sched_info", (uintptr_t)NULL, 0, 1, &arg);
195 	mdb_dec_indent(8);
196 
197 	mdb_printf("pd_refcnt:\t\t%u\n", desc.pd_refcnt);
198 	if (desc.pd_name == NULL)
199 	    mdb_printf("pd_name:\t\t NULL\n");
200 	else if (mdb_readstr(string, MAXNAMELEN + 1, (uintptr_t)desc.pd_name)
201 		== -1)
202 		mdb_warn("could not read pd_name from %X\n", desc.pd_name);
203 	else
204 	    mdb_printf("pd_name:\t\t%s\n", string);
205 
206 	mdb_printf("pd_instance:\t\t%u\n", desc.pd_instance);
207 	mdb_printf("pd_module_id:\t\t%d\n", desc.pd_module_id);
208 	mdb_printf("pd_mctlp:\t\t%p\n", desc.pd_mctlp);
209 	mdb_printf("pd_sid:\t\t\t%u\n", desc.pd_sid);
210 	mdb_printf("pd_lock:\t\t%p\n", desc.pd_lock);
211 	if (desc.pd_state < KCF_PROV_ALLOCATED ||
212 	    desc.pd_state > KCF_PROV_FREED)
213 		mdb_printf("pd_state is invalid:\t%d\n", desc.pd_state);
214 	else
215 		mdb_printf("pd_state:\t%s\n", prov_states[desc.pd_state]);
216 
217 	mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque);
218 	mdb_printf("pd_remove_cv:\t\t%hd\n", desc.pd_remove_cv._opaque);
219 	mdb_printf("pd_restricted:\t\t%s\n",
220 	    desc.pd_restricted == B_FALSE ? "B_FALSE" : "B_TRUE");
221 	mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list);
222 	return (DCMD_OK);
223 }
224 
225 #define	GOT_NONE	(-2)
226 
227 /*ARGSUSED*/
228 int
229 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
230 {
231 	kcf_provider_desc_t **tab;
232 	kcf_provider_desc_t desc;
233 	kcf_provider_desc_t *ptr;
234 	uint_t prov_tab_max;
235 	int i;
236 	int gotzero = GOT_NONE;
237 	char string[MAXNAMELEN + 1];
238 
239 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
240 		return (DCMD_USAGE);
241 	} else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab")
242 	    == -1) {
243 		mdb_warn("cannot read prov_tab");
244 		return (DCMD_ERR);
245 
246 	} else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) {
247 		mdb_warn("cannot read prov_tab_max");
248 		return (DCMD_ERR);
249 	}
250 	mdb_printf("%<b>prov_tab = %p%</b>\n", ptr);
251 	tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *),
252 	    UM_SLEEP| UM_GC);
253 
254 #ifdef DEBUG
255 	mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max);
256 #endif
257 
258 	if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *),
259 	    (uintptr_t)ptr) == -1) {
260 		mdb_warn("cannot read prov_tab");
261 		return (DCMD_ERR);
262 	}
263 #ifdef DEBUG
264 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
265 	mdb_printf("DEBUG: *tab = %p\n", *tab);
266 #endif
267 	for (i = 0;  i <  prov_tab_max; i++) {
268 		/* save space, only print range for long list of nulls */
269 		if (tab[i] == NULL) {
270 			if (gotzero == GOT_NONE) {
271 			    mdb_printf("prov_tab[%d", i);
272 			    gotzero = i;
273 			}
274 		} else {
275 			/* first non-null in awhile, print index of prev null */
276 			if (gotzero != GOT_NONE) {
277 				if (gotzero == (i - 1))
278 					mdb_printf("] = NULL\n", i - 1);
279 				else
280 					mdb_printf(" - %d] = NULL\n", i - 1);
281 				gotzero = GOT_NONE;
282 			}
283 			/* interesting value, print it */
284 			mdb_printf("prov_tab[%d] = %p ", i, tab[i]);
285 
286 			if (mdb_vread(&desc, sizeof (kcf_provider_desc_t),
287 			    (uintptr_t)tab[i]) == -1) {
288 				mdb_warn("cannot read at address %p",
289 				    (uintptr_t)tab[i]);
290 				return (DCMD_ERR);
291 			}
292 
293 			(void) mdb_readstr(string, MAXNAMELEN + 1,
294 			    (uintptr_t)desc.pd_name);
295 			mdb_printf("(%s\t%s)\n", string,
296 			    prov_states[desc.pd_state]);
297 		}
298 	}
299 	/* if we've printed the first of many nulls but left the brace open */
300 	if ((i > 0) && (tab[i-1] == NULL)) {
301 		if (gotzero == GOT_NONE)
302 			mdb_printf("] = NULL\n");
303 		else
304 			mdb_printf(" - %d] = NULL\n", i - 1);
305 	}
306 
307 	return (DCMD_OK);
308 }
309 
310 /*ARGSUSED*/
311 int
312 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
313 {
314 	kcf_policy_desc_t **tab;
315 	kcf_policy_desc_t *ptr;
316 	uint_t policy_tab_max;
317 	int num, i;
318 	int gotzero = GOT_NONE;
319 
320 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
321 		return (DCMD_USAGE);
322 	} else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab")
323 	    == -1) {
324 		mdb_warn("cannot read policy_tab");
325 		return (DCMD_ERR);
326 
327 	} else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) {
328 		mdb_warn("cannot read policy_tab_max");
329 		return (DCMD_ERR);
330 	}
331 
332 	/* get the current number of descriptors in the table */
333 	if (mdb_readvar(&num, "policy_tab_num") == -1) {
334 		mdb_warn("cannot read policy_tab_num");
335 		return (DCMD_ERR);
336 	}
337 	mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n",
338 	    ptr, num);
339 
340 	tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *),
341 	    UM_SLEEP| UM_GC);
342 
343 	if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *),
344 	    (uintptr_t)ptr) == -1) {
345 		mdb_warn("cannot read policy_tab");
346 		return (DCMD_ERR);
347 	}
348 #ifdef DEBUG
349 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
350 	mdb_printf("DEBUG: *tab = %p\n", *tab);
351 #endif
352 	for (i = 0;  i < policy_tab_max; i++) {
353 		/* save space, only print range for long list of nulls */
354 		if (tab[i] == NULL) {
355 			if (gotzero == GOT_NONE) {
356 			    mdb_printf("policy_tab[%d", i);
357 			    gotzero = i;
358 			}
359 		} else {
360 			/* first non-null in awhile, print index of prev null */
361 			if (gotzero != GOT_NONE) {
362 				if (gotzero == (i - 1))
363 					mdb_printf("] = NULL\n", i - 1);
364 				else
365 					mdb_printf(" - %d] = NULL\n", i - 1);
366 				gotzero = GOT_NONE;
367 			}
368 			/* interesting value, print it */
369 			mdb_printf("policy_tab[%d] = %p\n", i, tab[i]);
370 		}
371 	}
372 	/* if we've printed the first of many nulls but left the brace open */
373 	if ((i > 0) && (tab[i-1] == NULL)) {
374 		if (gotzero == GOT_NONE)
375 			mdb_printf("] = NULL\n");
376 		else
377 			mdb_printf(" - %d] = NULL\n", i - 1);
378 	}
379 
380 	return (DCMD_OK);
381 }
382 
383 static void
384 prt_mechs(int count, crypto_mech_name_t *mechs)
385 {
386 	int i;
387 	char name[CRYPTO_MAX_MECH_NAME + 1];
388 	char name2[CRYPTO_MAX_MECH_NAME + 3];
389 
390 	for (i = 0; i < count; i++) {
391 		if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME,
392 		    (uintptr_t)((char *)mechs)) == -1)
393 			continue;
394 		/* put in quotes */
395 		(void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name);
396 		/* yes, length is 32, but then it will wrap */
397 		/* this shorter size formats nicely for most cases */
398 		mdb_printf("mechs[%d]=%-28s", i, name2);
399 		mdb_printf("%s", i%2 ? "\n" : "  "); /* 2-columns */
400 		mechs++;
401 	}
402 }
403 
404 /* ARGSUSED2 */
405 static int
406 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry,
407     void *cbdata)
408 {
409 	char name[MAXNAMELEN + 1];
410 
411 	mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr);
412 	mdb_printf("ce_next: %p", entry->ce_next);
413 
414 	if (entry->ce_name == NULL)
415 		    mdb_printf("\tce_name: NULL\n");
416 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name)
417 		    == -1)
418 		mdb_printf("could not read ce_name from %p\n",
419 			entry->ce_name);
420 	else
421 		mdb_printf("\tce_name: %s\n", name);
422 
423 	mdb_printf("ce_count: %d\n", entry->ce_count);
424 	prt_mechs(entry->ce_count, entry->ce_mechs);
425 	return (WALK_NEXT);
426 }
427 
428 int
429 soft_conf_walk_init(mdb_walk_state_t *wsp)
430 {
431 	uintptr_t *soft;
432 
433 	if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *),
434 	    "soft_config_list") == -1) {
435 		mdb_warn("failed to find 'soft_config_list'");
436 		return (WALK_ERR);
437 	}
438 	wsp->walk_addr = (uintptr_t)soft;
439 	wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP);
440 	wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry;
441 	return (WALK_NEXT);
442 }
443 
444 /*
445  * At each step, read a kcf_soft_conf_entry_t into our private storage, then
446  * invoke the callback function.  We terminate when we reach a NULL ce_next
447  * pointer.
448  */
449 int
450 soft_conf_walk_step(mdb_walk_state_t *wsp)
451 {
452 	int status;
453 
454 	if (wsp->walk_addr == NULL)	/* then we're done */
455 		return (WALK_DONE);
456 #ifdef DEBUG
457 	else
458 	    mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr);
459 #endif
460 
461 	if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t),
462 	    wsp->walk_addr) == -1) {
463 		mdb_warn("failed to read kcf_soft_conf_entry at %p",
464 		    wsp->walk_addr);
465 		return (WALK_DONE);
466 	}
467 
468 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
469 	    wsp->walk_cbdata);
470 
471 	wsp->walk_addr =
472 	    (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next);
473 	return (status);
474 }
475 
476 /*
477  * The walker's fini function is invoked at the end of each walk.  Since we
478  * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init,
479  * we must free it now.
480  */
481 void
482 soft_conf_walk_fini(mdb_walk_state_t *wsp)
483 {
484 #ifdef	DEBUG
485 	mdb_printf("...end of kcf_soft_conf_entry walk\n");
486 #endif
487 	mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t));
488 }
489 /* ARGSUSED2 */
490 int
491 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc,
492     const mdb_arg_t *argv)
493 {
494 	kcf_soft_conf_entry_t entry;
495 	kcf_soft_conf_entry_t *ptr;
496 
497 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
498 		if (addr == NULL) 	/* not allowed with DCMD_ADDRSPEC */
499 			return (DCMD_USAGE);
500 		else
501 			ptr = (kcf_soft_conf_entry_t *)addr;
502 	} else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list")
503 		    == -1) {
504 			mdb_warn("cannot read soft_config_list");
505 			return (DCMD_ERR);
506 	} else
507 		mdb_printf("soft_config_list = %p\n", ptr);
508 
509 	if (ptr == NULL)
510 		return (DCMD_OK);
511 
512 	if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr)
513 	    == -1) {
514 		    mdb_warn("cannot read at address %p", (uintptr_t)ptr);
515 		    return (DCMD_ERR);
516 	}
517 
518 	/* this could change in the future to have more than one ret val */
519 	if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR)
520 		return (DCMD_OK);
521 	return (DCMD_ERR);
522 }
523 
524 /* ARGSUSED1 */
525 int
526 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
527 {
528 	kcf_policy_desc_t  desc;
529 	char name[MAXNAMELEN + 1];
530 
531 
532 	if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC)
533 		return (DCMD_USAGE);
534 
535 	if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr)
536 	    == -1) {
537 		mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr);
538 		return (DCMD_ERR);
539 	}
540 	mdb_printf("pd_prov_type:  %s",
541 	    desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER"
542 		: "CRYPTO_SW_PROVIDER");
543 
544 	if (desc.pd_name == NULL)
545 		mdb_printf("\tpd_name: NULL\n");
546 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name)
547 	    == -1)
548 		mdb_printf("could not read pd_name from %p\n",
549 		    desc.pd_name);
550 	else
551 		mdb_printf("\tpd_name: %s\n", name);
552 
553 	mdb_printf("pd_instance: %d ", desc.pd_instance);
554 	mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt);
555 	mdb_printf("pd_mutex: %p", desc.pd_mutex);
556 	mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count);
557 	mdb_printf("\npd_disabled_mechs:\n");
558 	mdb_inc_indent(4);
559 	prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs);
560 	mdb_dec_indent(4);
561 	return (DCMD_OK);
562 }
563