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 %s\n",
220 	    (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ?
221 		"CRYPTO_HIDE_PROVIDER" : " ",
222 	    (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ?
223 		"CRYPTO_HASH_NO_UPDATE" : " ",
224 	    (desc.pd_flags & KCF_LPROV_MEMBER) ?
225 		"KCF_LPROV_MEMBER" : " ",
226 	    (desc.pd_flags & KCF_PROV_RESTRICTED) ?
227 		"KCF_PROV_RESTRICTED" : " ");
228 	if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE)
229 		mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit);
230 	mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list);
231 	return (DCMD_OK);
232 }
233 
234 #define	GOT_NONE	(-2)
235 
236 /*ARGSUSED*/
237 int
238 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
239 {
240 	kcf_provider_desc_t **tab;
241 	kcf_provider_desc_t desc;
242 	kcf_provider_desc_t *ptr;
243 	uint_t prov_tab_max;
244 	int i;
245 	int gotzero = GOT_NONE;
246 	char string[MAXNAMELEN + 1];
247 
248 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
249 		return (DCMD_USAGE);
250 	} else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab")
251 	    == -1) {
252 		mdb_warn("cannot read prov_tab");
253 		return (DCMD_ERR);
254 
255 	} else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) {
256 		mdb_warn("cannot read prov_tab_max");
257 		return (DCMD_ERR);
258 	}
259 	mdb_printf("%<b>prov_tab = %p%</b>\n", ptr);
260 	tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *),
261 	    UM_SLEEP| UM_GC);
262 
263 #ifdef DEBUG
264 	mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max);
265 #endif
266 
267 	if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *),
268 	    (uintptr_t)ptr) == -1) {
269 		mdb_warn("cannot read prov_tab");
270 		return (DCMD_ERR);
271 	}
272 #ifdef DEBUG
273 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
274 	mdb_printf("DEBUG: *tab = %p\n", *tab);
275 #endif
276 	for (i = 0;  i <  prov_tab_max; i++) {
277 		/* save space, only print range for long list of nulls */
278 		if (tab[i] == NULL) {
279 			if (gotzero == GOT_NONE) {
280 			    mdb_printf("prov_tab[%d", i);
281 			    gotzero = i;
282 			}
283 		} else {
284 			/* first non-null in awhile, print index of prev null */
285 			if (gotzero != GOT_NONE) {
286 				if (gotzero == (i - 1))
287 					mdb_printf("] = NULL\n", i - 1);
288 				else
289 					mdb_printf(" - %d] = NULL\n", i - 1);
290 				gotzero = GOT_NONE;
291 			}
292 			/* interesting value, print it */
293 			mdb_printf("prov_tab[%d] = %p ", i, tab[i]);
294 
295 			if (mdb_vread(&desc, sizeof (kcf_provider_desc_t),
296 			    (uintptr_t)tab[i]) == -1) {
297 				mdb_warn("cannot read at address %p",
298 				    (uintptr_t)tab[i]);
299 				return (DCMD_ERR);
300 			}
301 
302 			(void) mdb_readstr(string, MAXNAMELEN + 1,
303 			    (uintptr_t)desc.pd_name);
304 			mdb_printf("(%s\t%s)\n", string,
305 			    prov_states[desc.pd_state]);
306 		}
307 	}
308 	/* if we've printed the first of many nulls but left the brace open */
309 	if ((i > 0) && (tab[i-1] == NULL)) {
310 		if (gotzero == GOT_NONE)
311 			mdb_printf("] = NULL\n");
312 		else
313 			mdb_printf(" - %d] = NULL\n", i - 1);
314 	}
315 
316 	return (DCMD_OK);
317 }
318 
319 /*ARGSUSED*/
320 int
321 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
322 {
323 	kcf_policy_desc_t **tab;
324 	kcf_policy_desc_t *ptr;
325 	uint_t policy_tab_max;
326 	int num, i;
327 	int gotzero = GOT_NONE;
328 
329 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
330 		return (DCMD_USAGE);
331 	} else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab")
332 	    == -1) {
333 		mdb_warn("cannot read policy_tab");
334 		return (DCMD_ERR);
335 
336 	} else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) {
337 		mdb_warn("cannot read policy_tab_max");
338 		return (DCMD_ERR);
339 	}
340 
341 	/* get the current number of descriptors in the table */
342 	if (mdb_readvar(&num, "policy_tab_num") == -1) {
343 		mdb_warn("cannot read policy_tab_num");
344 		return (DCMD_ERR);
345 	}
346 	mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n",
347 	    ptr, num);
348 
349 	tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *),
350 	    UM_SLEEP| UM_GC);
351 
352 	if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *),
353 	    (uintptr_t)ptr) == -1) {
354 		mdb_warn("cannot read policy_tab");
355 		return (DCMD_ERR);
356 	}
357 #ifdef DEBUG
358 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
359 	mdb_printf("DEBUG: *tab = %p\n", *tab);
360 #endif
361 	for (i = 0;  i < policy_tab_max; i++) {
362 		/* save space, only print range for long list of nulls */
363 		if (tab[i] == NULL) {
364 			if (gotzero == GOT_NONE) {
365 			    mdb_printf("policy_tab[%d", i);
366 			    gotzero = i;
367 			}
368 		} else {
369 			/* first non-null in awhile, print index of prev null */
370 			if (gotzero != GOT_NONE) {
371 				if (gotzero == (i - 1))
372 					mdb_printf("] = NULL\n", i - 1);
373 				else
374 					mdb_printf(" - %d] = NULL\n", i - 1);
375 				gotzero = GOT_NONE;
376 			}
377 			/* interesting value, print it */
378 			mdb_printf("policy_tab[%d] = %p\n", i, tab[i]);
379 		}
380 	}
381 	/* if we've printed the first of many nulls but left the brace open */
382 	if ((i > 0) && (tab[i-1] == NULL)) {
383 		if (gotzero == GOT_NONE)
384 			mdb_printf("] = NULL\n");
385 		else
386 			mdb_printf(" - %d] = NULL\n", i - 1);
387 	}
388 
389 	return (DCMD_OK);
390 }
391 
392 static void
393 prt_mechs(int count, crypto_mech_name_t *mechs)
394 {
395 	int i;
396 	char name[CRYPTO_MAX_MECH_NAME + 1];
397 	char name2[CRYPTO_MAX_MECH_NAME + 3];
398 
399 	for (i = 0; i < count; i++) {
400 		if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME,
401 		    (uintptr_t)((char *)mechs)) == -1)
402 			continue;
403 		/* put in quotes */
404 		(void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name);
405 		/* yes, length is 32, but then it will wrap */
406 		/* this shorter size formats nicely for most cases */
407 		mdb_printf("mechs[%d]=%-28s", i, name2);
408 		mdb_printf("%s", i%2 ? "\n" : "  "); /* 2-columns */
409 		mechs++;
410 	}
411 }
412 
413 /* ARGSUSED2 */
414 static int
415 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry,
416     void *cbdata)
417 {
418 	char name[MAXNAMELEN + 1];
419 
420 	mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr);
421 	mdb_printf("ce_next: %p", entry->ce_next);
422 
423 	if (entry->ce_name == NULL)
424 		    mdb_printf("\tce_name: NULL\n");
425 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name)
426 		    == -1)
427 		mdb_printf("could not read ce_name from %p\n",
428 			entry->ce_name);
429 	else
430 		mdb_printf("\tce_name: %s\n", name);
431 
432 	mdb_printf("ce_count: %d\n", entry->ce_count);
433 	prt_mechs(entry->ce_count, entry->ce_mechs);
434 	return (WALK_NEXT);
435 }
436 
437 int
438 soft_conf_walk_init(mdb_walk_state_t *wsp)
439 {
440 	uintptr_t *soft;
441 
442 	if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *),
443 	    "soft_config_list") == -1) {
444 		mdb_warn("failed to find 'soft_config_list'");
445 		return (WALK_ERR);
446 	}
447 	wsp->walk_addr = (uintptr_t)soft;
448 	wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP);
449 	wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry;
450 	return (WALK_NEXT);
451 }
452 
453 /*
454  * At each step, read a kcf_soft_conf_entry_t into our private storage, then
455  * invoke the callback function.  We terminate when we reach a NULL ce_next
456  * pointer.
457  */
458 int
459 soft_conf_walk_step(mdb_walk_state_t *wsp)
460 {
461 	int status;
462 
463 	if (wsp->walk_addr == NULL)	/* then we're done */
464 		return (WALK_DONE);
465 #ifdef DEBUG
466 	else
467 	    mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr);
468 #endif
469 
470 	if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t),
471 	    wsp->walk_addr) == -1) {
472 		mdb_warn("failed to read kcf_soft_conf_entry at %p",
473 		    wsp->walk_addr);
474 		return (WALK_DONE);
475 	}
476 
477 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
478 	    wsp->walk_cbdata);
479 
480 	wsp->walk_addr =
481 	    (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next);
482 	return (status);
483 }
484 
485 /*
486  * The walker's fini function is invoked at the end of each walk.  Since we
487  * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init,
488  * we must free it now.
489  */
490 void
491 soft_conf_walk_fini(mdb_walk_state_t *wsp)
492 {
493 #ifdef	DEBUG
494 	mdb_printf("...end of kcf_soft_conf_entry walk\n");
495 #endif
496 	mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t));
497 }
498 /* ARGSUSED2 */
499 int
500 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc,
501     const mdb_arg_t *argv)
502 {
503 	kcf_soft_conf_entry_t entry;
504 	kcf_soft_conf_entry_t *ptr;
505 
506 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
507 		if (addr == NULL) 	/* not allowed with DCMD_ADDRSPEC */
508 			return (DCMD_USAGE);
509 		else
510 			ptr = (kcf_soft_conf_entry_t *)addr;
511 	} else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list")
512 		    == -1) {
513 			mdb_warn("cannot read soft_config_list");
514 			return (DCMD_ERR);
515 	} else
516 		mdb_printf("soft_config_list = %p\n", ptr);
517 
518 	if (ptr == NULL)
519 		return (DCMD_OK);
520 
521 	if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr)
522 	    == -1) {
523 		    mdb_warn("cannot read at address %p", (uintptr_t)ptr);
524 		    return (DCMD_ERR);
525 	}
526 
527 	/* this could change in the future to have more than one ret val */
528 	if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR)
529 		return (DCMD_OK);
530 	return (DCMD_ERR);
531 }
532 
533 /* ARGSUSED1 */
534 int
535 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
536 {
537 	kcf_policy_desc_t  desc;
538 	char name[MAXNAMELEN + 1];
539 
540 
541 	if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC)
542 		return (DCMD_USAGE);
543 
544 	if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr)
545 	    == -1) {
546 		mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr);
547 		return (DCMD_ERR);
548 	}
549 	mdb_printf("pd_prov_type:  %s",
550 	    desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER"
551 		: "CRYPTO_SW_PROVIDER");
552 
553 	if (desc.pd_name == NULL)
554 		mdb_printf("\tpd_name: NULL\n");
555 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name)
556 	    == -1)
557 		mdb_printf("could not read pd_name from %p\n",
558 		    desc.pd_name);
559 	else
560 		mdb_printf("\tpd_name: %s\n", name);
561 
562 	mdb_printf("pd_instance: %d ", desc.pd_instance);
563 	mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt);
564 	mdb_printf("pd_mutex: %p", desc.pd_mutex);
565 	mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count);
566 	mdb_printf("\npd_disabled_mechs:\n");
567 	mdb_inc_indent(4);
568 	prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs);
569 	mdb_dec_indent(4);
570 	return (DCMD_OK);
571 }
572