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