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