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