xref: /illumos-gate/usr/src/cmd/mdb/common/modules/crypto/sched_impl.c (revision 54034eb2d6e7d811adf4a1fe5105eac6fea6b0b5)
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 #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/api.h>
36 #include <sys/crypto/sched_impl.h>
37 #include "crypto_cmds.h"
38 
39 static void
40 prt_an_state(int state)
41 {
42 	switch (state) {
43 		case REQ_ALLOCATED:
44 			mdb_printf("REQ_ALLOCATED  ");
45 			break;
46 		case REQ_WAITING:
47 			mdb_printf("REQ_WAITING    ");
48 			break;
49 		case REQ_INPROGRESS:
50 			mdb_printf("REQ_INPROGRESS ");
51 			break;
52 		case REQ_DONE:
53 			mdb_printf("REQ_DONE       ");
54 			break;
55 		case REQ_CANCELED:
56 			mdb_printf("REQ_CANCELED   ");
57 			break;
58 		default:
59 			mdb_printf("? %d ??        ", state);
60 			break;
61 	}
62 }
63 
64 
65 static const mdb_bitmask_t call_flags[] = {
66 	{ "CRYPTO_ALWAYS_QUEUE", CRYPTO_ALWAYS_QUEUE, CRYPTO_ALWAYS_QUEUE },
67 	{ "CRYPTO_NOTIFY_OPDONE", CRYPTO_NOTIFY_OPDONE, CRYPTO_NOTIFY_OPDONE },
68 	{ "CRYPTO_SKIP_REQID", CRYPTO_SKIP_REQID, CRYPTO_SKIP_REQID },
69 	{ "CRYPTO_RESTRICTED", CRYPTO_RESTRICTED, CRYPTO_RESTRICTED },
70 	{ NULL, 0, 0 }
71 };
72 
73 /*ARGSUSED*/
74 static int
75 kcf_areq_node_simple(kcf_areq_node_t *areqn)
76 {
77 	mdb_printf("\nan_type: ");
78 	if (areqn->an_type != CRYPTO_ASYNCH)
79 		mdb_printf("%-8d    ", areqn->an_type);
80 	else
81 		mdb_printf("CRYPTO_ASYNCH");
82 
83 	mdb_printf("\nan_state: ");
84 	prt_an_state(areqn->an_state);
85 
86 	mdb_printf("\nan_context: %-16p\t", areqn->an_context);
87 	mdb_printf("an_is_my_turn: %s\t     ", areqn->an_is_my_turn == B_FALSE ?
88 			"B_FALSE" : "B_TRUE");
89 
90 	mdb_printf("\ncr_reqid: %lx\n", areqn->an_reqarg.cr_reqid);
91 	return (DCMD_OK);
92 }
93 /*
94  * Verbose print of kcf_areq_node_t
95  */
96 static int
97 v_kcf_areq_node(kcf_areq_node_t *areqn)
98 {
99 
100 	/* contents only -- the address is printed elsewhere */
101 	/* First column */
102 
103 	mdb_printf("\n%16s:  ", "an_type");
104 	if (areqn->an_type != CRYPTO_ASYNCH)
105 		mdb_printf("%-8d    ", areqn->an_type);
106 	else
107 		mdb_printf("CRYPTO_ASYNCH");
108 
109 	/* Second column */
110 	mdb_printf("\t\t%16s:  %p\n", "an_lock", areqn->an_lock);
111 
112 	/* First column */
113 	mdb_printf("%16s:  ", "an_state");
114 	prt_an_state(areqn->an_state);
115 
116 	/* Second column */
117 	mdb_printf("%14s:  next 4 items\n", "an_reqarg");
118 
119 	/* First column again */
120 	mdb_printf("%16s: '%16b'", "cr_flag", areqn->an_reqarg.cr_flag,
121 		call_flags);
122 
123 	/* Second column */
124 	mdb_printf("\t%16s:  %p\n", "cr_callback_func",
125 		areqn->an_reqarg.cr_callback_func);
126 
127 	/* First column again */
128 	mdb_printf("%16s:  %-16p", "cr_callback_arg",
129 		areqn->an_reqarg.cr_callback_arg);
130 
131 	/* Second column */
132 	mdb_printf("\t%16s:  %lx\n", "cr_reqid",
133 		(ulong_t)areqn->an_reqarg.cr_reqid);
134 
135 	/* First column again */
136 	mdb_printf("%16s:  %d", "an_params.rp_opgrp",
137 		areqn->an_params.rp_opgrp);
138 
139 	/* Second column */
140 	mdb_printf("\t%16s:  %d\n", "an_params.rp_optype",
141 		areqn->an_params.rp_optype);
142 
143 	/* First column again */
144 	mdb_printf("%16s:  %-16p", "an_context",
145 		areqn->an_context);
146 
147 	/* Second column */
148 	mdb_printf("\t%16s:  %p\n", "an_ctxchain_next",
149 		areqn->an_ctxchain_next);
150 
151 	/* First column again */
152 	mdb_printf("%16s:  %s", "an_is_my_turn",
153 	    areqn->an_is_my_turn == B_FALSE ? "B_FALSE" : "B_TRUE");
154 
155 	/* Second column */
156 	mdb_printf("\t\t%16s:  %s\n", "an_isdual",
157 	    areqn->an_isdual == B_FALSE ? "B_FALSE" : "B_TRUE");
158 
159 	/* First column again */
160 	mdb_printf("%16s:  %p", "an_next",
161 		areqn->an_next);
162 
163 	/* Second column */
164 	mdb_printf("\t\t%16s:  %p\n", "an_prev", areqn->an_prev);
165 
166 	/* First column again */
167 	mdb_printf("%16s:  %p", "an_provider",
168 		areqn->an_provider);
169 
170 	/* Second column */
171 	mdb_printf("\t\t%16s:  %p\n", "an_idnext", areqn->an_idnext);
172 
173 	/* First column again */
174 	mdb_printf("%16s:  %p", "an_idprev",
175 		areqn->an_idprev);
176 
177 	/* Second column */
178 	mdb_printf("\t\t%16s:  %hx\n", "an_done", areqn->an_done);
179 
180 	/* First column again */
181 	mdb_printf("%16s:  %d\n", "an_refcnt",
182 		areqn->an_refcnt);
183 
184 	return (DCMD_OK);
185 }
186 /*ARGSUSED*/
187 int
188 kcf_areq_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
189 {
190 	kcf_areq_node_t areqn;
191 	uint_t opt_v = FALSE;
192 
193 
194 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opt_v,
195 	    NULL) != argc)
196 			return (DCMD_USAGE);
197 
198 	/*
199 	 * read even if we're looping, because the cbdata design does not
200 	 * apply to mdb_pwalk_dcmd
201 	 */
202 	if (mdb_vread(&areqn, sizeof (kcf_areq_node_t), addr) == -1) {
203 		mdb_warn("cannot read %p", addr);
204 		return (DCMD_ERR);
205 	}
206 	if (opt_v)	/* verbose */
207 		return (v_kcf_areq_node(&areqn));
208 	else
209 		return (kcf_areq_node_simple(&areqn));
210 }
211 
212 /*ARGSUSED*/
213 int
214 kcf_global_swq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
215 {
216 	kcf_global_swq_t swq;
217 	kcf_global_swq_t *ptr;
218 
219 	if (!flags && DCMD_ADDRSPEC) {
220 		if (mdb_readsym(&ptr, sizeof (uintptr_t), "gswq")
221 		    == -1) {
222 			mdb_warn("cannot read gswq");
223 			return (DCMD_ERR);
224 		}
225 	}
226 	else
227 		ptr = (kcf_global_swq_t *)addr;
228 
229 	if (mdb_vread(&swq, sizeof (kcf_global_swq_t), (uintptr_t)ptr) == -1) {
230 		mdb_warn("cannot read %p", ptr);
231 		return (DCMD_ERR);
232 	}
233 	mdb_printf("gs_lock (mutex):\t%p\n", swq.gs_lock);
234 	mdb_printf("gs_cv:\t%hx\n", swq.gs_cv._opaque);
235 	mdb_printf("gs_njobs:\t%u\n", swq.gs_njobs);
236 	mdb_printf("gs_maxjobs:\t%u\n", swq.gs_maxjobs);
237 	mdb_printf("gs_first:\t%p\n", swq.gs_first);
238 	mdb_printf("gs_last:\t%p\n", swq.gs_last);
239 	return (mdb_pwalk_dcmd("an_next", "kcf_areq_node", argc,
240 	    argv, (uintptr_t)swq.gs_first));
241 }
242 
243 static int
244 areq_walk_init_common(mdb_walk_state_t *wsp, boolean_t use_first)
245 {
246 	kcf_global_swq_t gswq_copy;
247 	uintptr_t gswq_ptr;
248 
249 	if (mdb_readsym(&gswq_ptr, sizeof (gswq_ptr), "gswq") == -1) {
250 	    mdb_warn("failed to read 'gswq'");
251 	    return (WALK_ERR);
252 	}
253 	if (mdb_vread(&gswq_copy, sizeof (gswq_copy), gswq_ptr) == -1) {
254 		mdb_warn("cannot read %p", gswq_ptr);
255 		return (WALK_ERR);
256 	}
257 	if ((wsp->walk_addr = (use_first ? (uintptr_t)gswq_copy.gs_first :
258 	    (uintptr_t)gswq_copy.gs_last)) == NULL) {
259 		mdb_printf("Global swq is empty\n");
260 		return (WALK_DONE);
261 	}
262 	wsp->walk_data = mdb_alloc(sizeof (kcf_areq_node_t), UM_SLEEP);
263 	return (WALK_NEXT);
264 }
265 
266 int
267 areq_first_walk_init(mdb_walk_state_t *wsp)
268 {
269 	return (areq_walk_init_common(wsp, B_TRUE));
270 }
271 
272 int
273 areq_last_walk_init(mdb_walk_state_t *wsp)
274 {
275 	return (areq_walk_init_common(wsp, B_FALSE));
276 }
277 
278 typedef enum idwalk_type {
279 	IDNEXT,		/* an_idnext */
280 	IDPREV,		/* an_idprev */
281 	CTXCHAIN	/* an_ctxchain_next */
282 } idwalk_type_t;
283 
284 static int
285 an_id_walk_init(mdb_walk_state_t *wsp, idwalk_type_t type)
286 {
287 	kcf_areq_node_t *adn;
288 
289 	if (wsp->walk_addr == NULL) {
290 		mdb_warn("must give kcf_areq_node address\n");
291 		return (WALK_ERR);
292 	}
293 	adn = wsp->walk_data = mdb_alloc(sizeof (kcf_areq_node_t), UM_SLEEP);
294 
295 	if (mdb_vread(adn, sizeof (kcf_areq_node_t), wsp->walk_addr) == -1) {
296 		mdb_warn("cannot read %p", wsp->walk_addr);
297 		return (WALK_ERR);
298 	}
299 
300 	switch (type) {
301 		case IDNEXT:
302 			wsp->walk_addr = (uintptr_t)adn->an_idnext;
303 			break;
304 		case IDPREV:
305 			wsp->walk_addr = (uintptr_t)adn->an_idprev;
306 			break;
307 		case CTXCHAIN:
308 			wsp->walk_addr = (uintptr_t)adn->an_ctxchain_next;
309 			break;
310 		default:
311 			mdb_warn("Bad structure member in walk_init\n");
312 			return (WALK_ERR);
313 	}
314 	return (WALK_NEXT);
315 }
316 int
317 an_idnext_walk_init(mdb_walk_state_t *wsp)
318 {
319 	return (an_id_walk_init(wsp, IDNEXT));
320 }
321 int
322 an_idprev_walk_init(mdb_walk_state_t *wsp)
323 {
324 	return (an_id_walk_init(wsp, IDPREV));
325 }
326 int
327 an_ctxchain_walk_init(mdb_walk_state_t *wsp)
328 {
329 	return (an_id_walk_init(wsp, CTXCHAIN));
330 }
331 /*
332  * At each step, read a kcf_areq_node_t into our private storage, then invoke
333  * the callback function.  We terminate when we reach a NULL type pointer.
334  */
335 static int
336 an_id_walk_step(mdb_walk_state_t *wsp, idwalk_type_t type)
337 {
338 	int status;
339 	kcf_areq_node_t *ptr;
340 
341 	if (wsp->walk_addr == NULL)	/* then we're done */
342 		return (WALK_DONE);
343 
344 	ptr = wsp->walk_data;
345 
346 	if (mdb_vread(wsp->walk_data, sizeof (kcf_areq_node_t),
347 	    wsp->walk_addr) == -1) {
348 		mdb_warn("cannot read %p", wsp->walk_addr);
349 		return (WALK_ERR);
350 	}
351 
352 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
353 	    wsp->walk_cbdata);
354 
355 	switch (type) {
356 		case IDNEXT:
357 			if ((wsp->walk_addr =
358 			    (uintptr_t)ptr->an_idnext) == NULL)
359 				return (WALK_DONE);
360 			break;
361 
362 		case IDPREV:
363 			if ((wsp->walk_addr =
364 			    (uintptr_t)ptr->an_idprev) == NULL)
365 				return (WALK_DONE);
366 			break;
367 
368 		case CTXCHAIN:
369 			if ((wsp->walk_addr =
370 			    (uintptr_t)ptr->an_ctxchain_next) == NULL)
371 				return (WALK_DONE);
372 			break;
373 
374 		default:
375 			mdb_warn("Bad structure member in walk_step\n");
376 			return (WALK_ERR);
377 	}
378 	return (status);
379 }
380 int
381 an_idnext_walk_step(mdb_walk_state_t *wsp)
382 {
383 	return (an_id_walk_step(wsp, IDNEXT));
384 }
385 int
386 an_idprev_walk_step(mdb_walk_state_t *wsp)
387 {
388 	return (an_id_walk_step(wsp, IDPREV));
389 }
390 int
391 an_ctxchain_walk_step(mdb_walk_state_t *wsp)
392 {
393 	return (an_id_walk_step(wsp, CTXCHAIN));
394 }
395 
396 /*
397  * The walker's fini function is invoked at the end of each walk.  Since we
398  * dynamically allocated a kcf_areq_node_t in areq_walk_init,
399  * we must free it now.
400  */
401 void
402 areq_walk_fini(mdb_walk_state_t *wsp)
403 {
404 #ifdef	DEBUG
405 	mdb_printf("...end of kcf_areq_node walk\n");
406 #endif
407 	mdb_free(wsp->walk_data, sizeof (kcf_areq_node_t));
408 }
409 
410 /*
411  * At each step, read a kcf_areq_node_t into our private storage, then invoke
412  * the callback function.  We terminate when we reach a NULL an_next pointer
413  * or a NULL an_prev pointer. use_next flag indicates which one to check.
414  */
415 static int
416 an_walk_step_common(mdb_walk_state_t *wsp, boolean_t use_next)
417 {
418 	int status;
419 	kcf_areq_node_t *ptr;
420 
421 	ptr = (kcf_areq_node_t *)wsp->walk_data;
422 
423 	if (mdb_vread(wsp->walk_data, sizeof (kcf_areq_node_t),
424 	    wsp->walk_addr) == -1) {
425 		mdb_warn("failed to read kcf_areq_node at %p", wsp->walk_addr);
426 		return (WALK_DONE);
427 	}
428 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
429 	    wsp->walk_cbdata);
430 
431 	if ((wsp->walk_addr = (use_next ? (uintptr_t)ptr->an_next :
432 	    (uintptr_t)ptr->an_prev)) == NULL)
433 		return (WALK_DONE);
434 
435 	return (status);
436 }
437 
438 int
439 an_next_walk_step(mdb_walk_state_t *wsp)
440 {
441 	return (an_walk_step_common(wsp, B_TRUE));
442 }
443 
444 int
445 an_prev_walk_step(mdb_walk_state_t *wsp)
446 {
447 	return (an_walk_step_common(wsp, B_FALSE));
448 }
449 
450 /*
451  * Walker data for reqid_table walking
452  */
453 typedef	struct reqid_data {
454 	kcf_reqid_table_t rd_table;
455 	kcf_reqid_table_t *rd_tbl_ptrs[REQID_TABLES];
456 	int		rd_cur_index;
457 } reqid_data_t;
458 
459 typedef struct reqid_cb_data {
460 	crypto_req_id_t cb_reqid;
461 	int verbose;
462 	int found;
463 } reqid_cb_data_t;
464 
465 extern int crypto_pr_reqid(uintptr_t, reqid_data_t *, reqid_cb_data_t *);
466 
467 
468 int
469 reqid_table_walk_init(mdb_walk_state_t *wsp)
470 {
471 	reqid_data_t *wdata;
472 	reqid_cb_data_t *cbdata;
473 
474 	wsp->walk_callback = (mdb_walk_cb_t)crypto_pr_reqid;
475 
476 	wsp->walk_data = mdb_alloc(sizeof (reqid_data_t), UM_SLEEP);
477 
478 	/* see if the walker was called from the command line or mdb_pwalk */
479 	if (wsp->walk_cbdata == NULL) {		/* command line */
480 	    if ((wsp->walk_cbdata = mdb_zalloc(sizeof (reqid_cb_data_t),
481 		UM_SLEEP)) == NULL) {
482 		    mdb_warn("couldn't get cb memory for reqid_table_walker");
483 		    return (WALK_ERR);
484 	    }
485 	    /* initialize for a simple walk, as opposed to a reqid search */
486 	    cbdata = wsp->walk_cbdata;
487 	    cbdata->verbose = TRUE;
488 	    cbdata->cb_reqid = 0;
489 	}
490 
491 	wdata = (reqid_data_t *)wsp->walk_data;
492 
493 	if (mdb_readsym(wdata->rd_tbl_ptrs, sizeof (wdata->rd_tbl_ptrs),
494 		"kcf_reqid_table") == -1) {
495 		mdb_warn("failed to read 'kcf_reqid_table'");
496 		return (WALK_ERR);
497 
498 	}
499 	wdata->rd_cur_index = 0;
500 	wsp->walk_addr = (uintptr_t)wdata->rd_tbl_ptrs[wdata->rd_cur_index];
501 
502 
503 	return (WALK_NEXT);
504 }
505 
506 /*
507  * At each step, read a kcf_reqid_table_t into our private storage, then invoke
508  * the callback function.  We terminate when we reach a
509  */
510 int
511 reqid_table_walk_step(mdb_walk_state_t *wsp)
512 {
513 	int status;
514 	reqid_data_t *wdata;
515 
516 
517 	wdata = wsp->walk_data;
518 	wsp->walk_addr = (uintptr_t)wdata->rd_tbl_ptrs[wdata->rd_cur_index];
519 
520 #ifdef DEBUG
521 	mdb_printf(
522 	    "DEBUG: kcf_reqid_table at %p, sizeof kcf_reqid_table_t = %d\n",
523 		wsp->walk_addr, sizeof (kcf_reqid_table_t));
524 #endif
525 
526 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
527 	    wsp->walk_cbdata);
528 
529 	/* get ready for next call */
530 	wdata->rd_cur_index++;
531 	if (wdata->rd_cur_index >= REQID_TABLES)
532 		return (WALK_DONE);
533 	return (status);
534 }
535 
536 /*
537  * The walker's fini function is invoked at the end of each walk.  Since we
538  * dynamically allocated a reqid_data_t in areq_walk_init,
539  * we must free it now.
540  */
541 void
542 reqid_table_walk_fini(mdb_walk_state_t *wsp)
543 {
544 #ifdef DEBUG
545 	mdb_printf("...end of kcf_reqid walk\n");
546 #endif
547 	mdb_free(wsp->walk_data, sizeof (reqid_data_t));
548 }
549 
550 /*
551  * If there's an argument beyond -v, then we're looking for a specific
552  * reqid, otherwise, print any non-null kcf_areq things we run across.
553  */
554 
555 int
556 crypto_pr_reqid(uintptr_t addr, reqid_data_t *data, reqid_cb_data_t *cbdata)
557 {
558 	kcf_areq_node_t node;
559 	int i;
560 	int needhdr = TRUE;
561 
562 	if (addr == NULL) {
563 		mdb_printf("kcf_reqid_table[%d] = NULL\n", data->rd_cur_index);
564 		return (WALK_NEXT);
565 	}
566 
567 	if (mdb_vread(&(data->rd_table), sizeof (kcf_reqid_table_t),
568 	    addr) == -1) {
569 		mdb_warn("failed to read kcf_reqid_table at %p",
570 		    addr);
571 		return (WALK_ERR);
572 	}
573 
574 	/* Loop over all rt_idhash's */
575 	for (i = 0; i < REQID_BUCKETS; i++) {
576 	    uint_t number_in_chain = 0;
577 	    uintptr_t node_addr;
578 
579 	    /* follow the an_idnext chains for each bucket */
580 	    do {
581 		/* read kcf_areq_node */
582 		if (number_in_chain == 0)
583 		    node_addr = (uintptr_t)data->rd_table.rt_idhash[i];
584 		else
585 		    /*LINTED*/
586 		    node_addr = (uintptr_t)node.an_idnext;
587 #ifdef DEBUG
588 		mdb_printf("DEBUG: node_addr = %p\n", node_addr);
589 #endif
590 
591 		if (node_addr == NULL)
592 			break;  /* skip */
593 
594 		if (mdb_vread(&node, sizeof (kcf_areq_node_t), node_addr)
595 		    == -1) {
596 			if (cbdata->verbose == TRUE)
597 			    mdb_printf(
598 				"cannot read rt_idhash %d an_idnext %d\n",
599 				i, number_in_chain);
600 			break;
601 		}
602 		/* see if we want to print it */
603 		if ((cbdata->cb_reqid == 0) ||
604 		    (node.an_reqarg.cr_reqid == cbdata->cb_reqid)) {
605 			cbdata->found = TRUE;  /* printed if false || reqid */
606 			/* is this the first rd_idhash found for this table? */
607 			if (needhdr == TRUE) {
608 			    /* print both indices in bold */
609 			    mdb_printf("%<b>kcf_reqid_table[%lu] at %p:%</b>\n",
610 				data->rd_cur_index, addr);
611 			    mdb_printf("\trt_lock:  %p\trt_curid: %llx\n",
612 				data->rd_table.rt_lock,
613 				data->rd_table.rt_curid);
614 			    needhdr = FALSE;
615 			}
616 			/* print kcf_areq_node */
617 			if (number_in_chain < 1)
618 			    mdb_printf(
619 				"    %<b>rt_idhash[%lu%]%</b> = %<b>%p:%</b>\n",
620 				i, node_addr);
621 			else
622 			    mdb_printf(
623 				"    rt_idhash[%lu%]"
624 					" an_idnext %d  = %<b>%p:%</b>\n",
625 					i, number_in_chain, node_addr);
626 			mdb_inc_indent(8);
627 
628 			/* if we're looking for one and only one reqid */
629 			/* do it REALLY verbose */
630 			if ((node.an_reqarg.cr_reqid == cbdata->cb_reqid) &&
631 			    (cbdata->cb_reqid != 0))
632 				v_kcf_areq_node(&node);
633 			else if (cbdata->verbose == TRUE)
634 			/*
635 			 * verbose for this walker means non-verbose for
636 			 * the kcf_areq_node details
637 			 */
638 			    kcf_areq_node_simple(&node);
639 			mdb_dec_indent(8);
640 		}
641 		/* if we only wanted one reqid, quit now */
642 		if (node.an_reqarg.cr_reqid == cbdata->cb_reqid) {
643 			return (WALK_DONE);
644 		}
645 
646 		number_in_chain++;
647 
648 	    } while (node.an_idnext != NULL); /* follow chain in same bucket */
649 
650 	}  /* for each REQID_BUCKETS */
651 
652 	if ((needhdr == TRUE) && (cbdata->cb_reqid == 0)) {
653 	    mdb_printf("%kcf_reqid_table[%lu]: %p\n",
654 		data->rd_cur_index, addr);
655 	}
656 	return (WALK_NEXT);
657 }
658 
659 /*ARGSUSED*/
660 int
661 crypto_find_reqid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
662 {
663 	const mdb_arg_t *argp = NULL;
664 	reqid_cb_data_t cbdata;
665 	int i, status;
666 
667 	cbdata.cb_reqid = 0L;
668 	cbdata.verbose = FALSE;
669 	cbdata.found = FALSE;
670 
671 	if (flags & DCMD_ADDRSPEC) {
672 		mdb_printf("use addr ::kcf_reqid_table\n");
673 		return (DCMD_USAGE);
674 	}
675 	if ((i = mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE,
676 	    &cbdata.verbose, NULL)) != argc) {
677 		if (argc - i > 1)
678 			return (DCMD_USAGE);
679 	}
680 
681 	if (argc > i)
682 	    argp = &argv[i];
683 
684 	if ((argp != NULL)) {
685 	    if (argp->a_type == MDB_TYPE_IMMEDIATE)
686 		cbdata.cb_reqid = argp->a_un.a_val;
687 	    else
688 		cbdata.cb_reqid = (crypto_req_id_t)
689 		    mdb_strtoull(argp->a_un.a_str);
690 	}
691 	status = mdb_pwalk("kcf_reqid_table", (mdb_walk_cb_t)crypto_pr_reqid,
692 	    &cbdata, addr);
693 
694 	if ((cbdata.cb_reqid != 0L) && (cbdata.found == FALSE))
695 		mdb_printf("ID 0x%lx not found\n", cbdata.cb_reqid);
696 #ifdef DEBUG
697 	else
698 		mdb_printf("DEBUG: cbdata.db_reqid = %lx, cbdata.found = %d\n",
699 		    cbdata.cb_reqid, cbdata.found);
700 #endif
701 
702 	return (status);
703 }
704 
705 int
706 kcf_reqid_table_dcmd(uintptr_t addr, uint_t flags, int argc,
707     const mdb_arg_t *argv)
708 {
709 	reqid_data_t wdata;
710 	reqid_cb_data_t cbdata;
711 
712 	if (!(flags & DCMD_ADDRSPEC))
713 		return (DCMD_USAGE);
714 
715 	memset(&wdata, 0, sizeof (wdata));
716 	memset(&cbdata, 0, sizeof (cbdata));
717 
718 	if ((mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE,
719 	    &cbdata.verbose, NULL)) != argc) {
720 			return (DCMD_USAGE);
721 	}
722 	crypto_pr_reqid(addr, &wdata, &cbdata);
723 	return (DCMD_OK);
724 }
725