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