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