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.
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.
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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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"
37 prt_an_state(int state
)
41 mdb_printf("REQ_ALLOCATED ");
44 mdb_printf("REQ_WAITING ");
47 mdb_printf("REQ_INPROGRESS ");
50 mdb_printf("REQ_DONE ");
53 mdb_printf("REQ_CANCELED ");
56 mdb_printf("? %d ?? ", state
);
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
},
71 kcf_areq_node_simple(kcf_areq_node_t
*areqn
)
73 mdb_printf("\nan_type: ");
74 if (areqn
->an_type
!= CRYPTO_ASYNCH
)
75 mdb_printf("%-8d ", areqn
->an_type
);
77 mdb_printf("CRYPTO_ASYNCH");
79 mdb_printf("\nan_state: ");
80 prt_an_state(areqn
->an_state
);
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");
86 mdb_printf("\ncr_reqid: %lx\n", areqn
->an_reqarg
.cr_reqid
);
90 * Verbose print of kcf_areq_node_t
93 v_kcf_areq_node(kcf_areq_node_t
*areqn
)
96 /* contents only -- the address is printed elsewhere */
99 mdb_printf("\n%16s: ", "an_type");
100 if (areqn
->an_type
!= CRYPTO_ASYNCH
)
101 mdb_printf("%-8d ", areqn
->an_type
);
103 mdb_printf("CRYPTO_ASYNCH");
106 mdb_printf("\t\t%16s: %p\n", "an_lock", areqn
->an_lock
);
109 mdb_printf("%16s: ", "an_state");
110 prt_an_state(areqn
->an_state
);
113 mdb_printf("%14s: next 4 items\n", "an_reqarg");
115 /* First column again */
116 mdb_printf("%16s: '%16b'", "cr_flag", areqn
->an_reqarg
.cr_flag
,
120 mdb_printf("\t%16s: %p\n", "cr_callback_func",
121 areqn
->an_reqarg
.cr_callback_func
);
123 /* First column again */
124 mdb_printf("%16s: %-16p", "cr_callback_arg",
125 areqn
->an_reqarg
.cr_callback_arg
);
128 mdb_printf("\t%16s: %lx\n", "cr_reqid",
129 (ulong_t
)areqn
->an_reqarg
.cr_reqid
);
131 /* First column again */
132 mdb_printf("%16s: %d", "an_params.rp_opgrp",
133 areqn
->an_params
.rp_opgrp
);
136 mdb_printf("\t%16s: %d\n", "an_params.rp_optype",
137 areqn
->an_params
.rp_optype
);
139 /* First column again */
140 mdb_printf("%16s: %-16p", "an_context",
144 mdb_printf("\t%16s: %p\n", "an_ctxchain_next",
145 areqn
->an_ctxchain_next
);
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");
152 mdb_printf("\t\t%16s: %s\n", "an_isdual",
153 areqn
->an_isdual
== B_FALSE
? "B_FALSE" : "B_TRUE");
155 /* First column again */
156 mdb_printf("%16s: %p", "an_next",
160 mdb_printf("\t\t%16s: %p\n", "an_prev", areqn
->an_prev
);
162 /* First column again */
163 mdb_printf("%16s: %p", "an_provider",
167 mdb_printf("\t\t%16s: %p\n", "an_idnext", areqn
->an_idnext
);
169 /* First column again */
170 mdb_printf("%16s: %p", "an_idprev",
174 mdb_printf("\t\t%16s: %hx\n", "an_done", areqn
->an_done
);
176 /* First column again */
177 mdb_printf("%16s: %d\n", "an_refcnt",
184 kcf_areq_node(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
186 kcf_areq_node_t areqn
;
187 uint_t opt_v
= FALSE
;
190 if (mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
, &opt_v
,
195 * read even if we're looping, because the cbdata design does not
196 * apply to mdb_pwalk_dcmd
198 if (mdb_vread(&areqn
, sizeof (kcf_areq_node_t
), addr
) == -1) {
199 mdb_warn("cannot read %p", addr
);
202 if (opt_v
) /* verbose */
203 return (v_kcf_areq_node(&areqn
));
205 return (kcf_areq_node_simple(&areqn
));
210 kcf_global_swq(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
212 kcf_global_swq_t swq
;
213 kcf_global_swq_t
*ptr
;
215 if (!(flags
& DCMD_ADDRSPEC
)) {
216 if (mdb_readsym(&ptr
, sizeof (uintptr_t), "gswq")
218 mdb_warn("cannot read gswq");
223 ptr
= (kcf_global_swq_t
*)addr
;
225 if (mdb_vread(&swq
, sizeof (kcf_global_swq_t
), (uintptr_t)ptr
) == -1) {
226 mdb_warn("cannot read %p", ptr
);
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
));
240 areq_walk_init_common(mdb_walk_state_t
*wsp
, boolean_t use_first
)
242 kcf_global_swq_t gswq_copy
;
245 if (mdb_readsym(&gswq_ptr
, sizeof (gswq_ptr
), "gswq") == -1) {
246 mdb_warn("failed to read 'gswq'");
249 if (mdb_vread(&gswq_copy
, sizeof (gswq_copy
), gswq_ptr
) == -1) {
250 mdb_warn("cannot read %p", gswq_ptr
);
253 if ((wsp
->walk_addr
= (use_first
? (uintptr_t)gswq_copy
.gs_first
:
254 (uintptr_t)gswq_copy
.gs_last
)) == (uintptr_t)NULL
) {
255 mdb_printf("Global swq is empty\n");
258 wsp
->walk_data
= mdb_alloc(sizeof (kcf_areq_node_t
), UM_SLEEP
);
263 areq_first_walk_init(mdb_walk_state_t
*wsp
)
265 return (areq_walk_init_common(wsp
, B_TRUE
));
269 areq_last_walk_init(mdb_walk_state_t
*wsp
)
271 return (areq_walk_init_common(wsp
, B_FALSE
));
274 typedef enum idwalk_type
{
275 IDNEXT
, /* an_idnext */
276 IDPREV
, /* an_idprev */
277 CTXCHAIN
/* an_ctxchain_next */
281 an_id_walk_init(mdb_walk_state_t
*wsp
, idwalk_type_t type
)
283 kcf_areq_node_t
*adn
;
285 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
286 mdb_warn("must give kcf_areq_node address\n");
289 adn
= wsp
->walk_data
= mdb_alloc(sizeof (kcf_areq_node_t
), UM_SLEEP
);
291 if (mdb_vread(adn
, sizeof (kcf_areq_node_t
), wsp
->walk_addr
) == -1) {
292 mdb_warn("cannot read %p", wsp
->walk_addr
);
298 wsp
->walk_addr
= (uintptr_t)adn
->an_idnext
;
301 wsp
->walk_addr
= (uintptr_t)adn
->an_idprev
;
304 wsp
->walk_addr
= (uintptr_t)adn
->an_ctxchain_next
;
307 mdb_warn("Bad structure member in walk_init\n");
313 an_idnext_walk_init(mdb_walk_state_t
*wsp
)
315 return (an_id_walk_init(wsp
, IDNEXT
));
318 an_idprev_walk_init(mdb_walk_state_t
*wsp
)
320 return (an_id_walk_init(wsp
, IDPREV
));
323 an_ctxchain_walk_init(mdb_walk_state_t
*wsp
)
325 return (an_id_walk_init(wsp
, CTXCHAIN
));
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.
332 an_id_walk_step(mdb_walk_state_t
*wsp
, idwalk_type_t type
)
335 kcf_areq_node_t
*ptr
;
337 if (wsp
->walk_addr
== (uintptr_t)NULL
) /* then we're done */
340 ptr
= wsp
->walk_data
;
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
);
348 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
353 if ((wsp
->walk_addr
=
354 (uintptr_t)ptr
->an_idnext
) == (uintptr_t)NULL
)
359 if ((wsp
->walk_addr
=
360 (uintptr_t)ptr
->an_idprev
) == (uintptr_t)NULL
)
365 if ((wsp
->walk_addr
=
366 (uintptr_t)ptr
->an_ctxchain_next
) ==
372 mdb_warn("Bad structure member in walk_step\n");
378 an_idnext_walk_step(mdb_walk_state_t
*wsp
)
380 return (an_id_walk_step(wsp
, IDNEXT
));
383 an_idprev_walk_step(mdb_walk_state_t
*wsp
)
385 return (an_id_walk_step(wsp
, IDPREV
));
388 an_ctxchain_walk_step(mdb_walk_state_t
*wsp
)
390 return (an_id_walk_step(wsp
, CTXCHAIN
));
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.
399 areq_walk_fini(mdb_walk_state_t
*wsp
)
402 mdb_printf("...end of kcf_areq_node walk\n");
404 mdb_free(wsp
->walk_data
, sizeof (kcf_areq_node_t
));
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.
413 an_walk_step_common(mdb_walk_state_t
*wsp
, boolean_t use_next
)
416 kcf_areq_node_t
*ptr
;
418 ptr
= (kcf_areq_node_t
*)wsp
->walk_data
;
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
);
425 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
428 if ((wsp
->walk_addr
= (use_next
? (uintptr_t)ptr
->an_next
:
429 (uintptr_t)ptr
->an_prev
)) == (uintptr_t)NULL
)
436 an_next_walk_step(mdb_walk_state_t
*wsp
)
438 return (an_walk_step_common(wsp
, B_TRUE
));
442 an_prev_walk_step(mdb_walk_state_t
*wsp
)
444 return (an_walk_step_common(wsp
, B_FALSE
));
448 * Walker data for reqid_table walking
450 typedef struct reqid_data
{
451 kcf_reqid_table_t rd_table
;
452 kcf_reqid_table_t
*rd_tbl_ptrs
[REQID_TABLES
];
456 typedef struct reqid_cb_data
{
457 crypto_req_id_t cb_reqid
;
462 extern int crypto_pr_reqid(uintptr_t, reqid_data_t
*, reqid_cb_data_t
*);
466 reqid_table_walk_init(mdb_walk_state_t
*wsp
)
469 reqid_cb_data_t
*cbdata
;
471 wsp
->walk_callback
= (mdb_walk_cb_t
)crypto_pr_reqid
;
473 wsp
->walk_data
= mdb_alloc(sizeof (reqid_data_t
), UM_SLEEP
);
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");
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;
489 wdata
= (reqid_data_t
*)wsp
->walk_data
;
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'");
497 wdata
->rd_cur_index
= 0;
498 wsp
->walk_addr
= (uintptr_t)wdata
->rd_tbl_ptrs
[wdata
->rd_cur_index
];
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
509 reqid_table_walk_step(mdb_walk_state_t
*wsp
)
515 wdata
= wsp
->walk_data
;
516 wsp
->walk_addr
= (uintptr_t)wdata
->rd_tbl_ptrs
[wdata
->rd_cur_index
];
520 "DEBUG: kcf_reqid_table at %p, sizeof kcf_reqid_table_t = %d\n",
521 wsp
->walk_addr
, sizeof (kcf_reqid_table_t
));
524 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
527 /* get ready for next call */
528 wdata
->rd_cur_index
++;
529 if (wdata
->rd_cur_index
>= REQID_TABLES
)
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.
540 reqid_table_walk_fini(mdb_walk_state_t
*wsp
)
543 mdb_printf("...end of kcf_reqid walk\n");
545 mdb_free(wsp
->walk_data
, sizeof (reqid_data_t
));
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.
554 crypto_pr_reqid(uintptr_t addr
, reqid_data_t
*data
, reqid_cb_data_t
*cbdata
)
556 kcf_areq_node_t node
;
560 if (addr
== (uintptr_t)NULL
) {
561 mdb_printf("kcf_reqid_table[%d] = NULL\n", data
->rd_cur_index
);
565 if (mdb_vread(&(data
->rd_table
), sizeof (kcf_reqid_table_t
),
567 mdb_warn("failed to read kcf_reqid_table at %p",
572 /* Loop over all rt_idhash's */
573 for (i
= 0; i
< REQID_BUCKETS
; i
++) {
574 uint_t number_in_chain
= 0;
577 /* follow the an_idnext chains for each bucket */
579 /* read kcf_areq_node */
580 if (number_in_chain
== 0)
582 (uintptr_t)data
->rd_table
.rt_idhash
[i
];
585 node_addr
= (uintptr_t)node
.an_idnext
;
587 mdb_printf("DEBUG: node_addr = %p\n", node_addr
);
590 if (node_addr
== (uintptr_t)NULL
)
593 if (mdb_vread(&node
, sizeof (kcf_areq_node_t
),
595 if (cbdata
->verbose
== TRUE
)
597 "cannot read rt_idhash %d"
602 /* see if we want to print it */
603 if ((cbdata
->cb_reqid
== 0) ||
604 (node
.an_reqarg
.cr_reqid
== cbdata
->cb_reqid
)) {
605 /* printed if false || reqid */
606 cbdata
->found
= TRUE
;
607 /* 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]"
612 data
->rd_cur_index
, addr
);
613 mdb_printf("\trt_lock: %p\trt_curid:"
615 data
->rd_table
.rt_lock
,
616 data
->rd_table
.rt_curid
);
619 /* print kcf_areq_node */
620 if (number_in_chain
< 1)
622 " %<b>rt_idhash[%lu%]%</b>"
628 " an_idnext %d = %<b>%p:%</b>\n",
629 i
, number_in_chain
, node_addr
);
632 /* if looking for one and only one reqid */
633 /* do it REALLY verbose */
634 if ((node
.an_reqarg
.cr_reqid
==
636 (cbdata
->cb_reqid
!= 0))
637 v_kcf_areq_node(&node
);
638 else if (cbdata
->verbose
== TRUE
)
640 * verbose for this walker
641 * means non-verbose for
642 * the kcf_areq_node details
644 kcf_areq_node_simple(&node
);
647 /* if we only wanted one reqid, quit now */
648 if (node
.an_reqarg
.cr_reqid
== cbdata
->cb_reqid
) {
654 } while (node
.an_idnext
!= NULL
); /* follow chain... */
656 } /* for each REQID_BUCKETS */
658 if ((needhdr
== TRUE
) && (cbdata
->cb_reqid
== 0)) {
659 mdb_printf("%kcf_reqid_table[%lu]: %p\n",
660 data
->rd_cur_index
, addr
);
667 crypto_find_reqid(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
669 const mdb_arg_t
*argp
= NULL
;
670 reqid_cb_data_t cbdata
;
673 cbdata
.cb_reqid
= 0L;
674 cbdata
.verbose
= FALSE
;
675 cbdata
.found
= FALSE
;
677 if (flags
& DCMD_ADDRSPEC
) {
678 mdb_printf("use addr ::kcf_reqid_table\n");
681 if ((i
= mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
,
682 &cbdata
.verbose
, NULL
)) != argc
) {
690 if ((argp
!= NULL
)) {
691 if (argp
->a_type
== MDB_TYPE_IMMEDIATE
)
692 cbdata
.cb_reqid
= argp
->a_un
.a_val
;
694 cbdata
.cb_reqid
= (crypto_req_id_t
)
695 mdb_strtoull(argp
->a_un
.a_str
);
697 status
= mdb_pwalk("kcf_reqid_table", (mdb_walk_cb_t
)crypto_pr_reqid
,
700 if ((cbdata
.cb_reqid
!= 0L) && (cbdata
.found
== FALSE
))
701 mdb_printf("ID 0x%lx not found\n", cbdata
.cb_reqid
);
704 mdb_printf("DEBUG: cbdata.db_reqid = %lx, cbdata.found = %d\n",
705 cbdata
.cb_reqid
, cbdata
.found
);
712 kcf_reqid_table_dcmd(uintptr_t addr
, uint_t flags
, int argc
,
713 const mdb_arg_t
*argv
)
716 reqid_cb_data_t cbdata
;
718 if (!(flags
& DCMD_ADDRSPEC
))
721 memset(&wdata
, 0, sizeof (wdata
));
722 memset(&cbdata
, 0, sizeof (cbdata
));
724 if ((mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
,
725 &cbdata
.verbose
, NULL
)) != argc
) {
728 crypto_pr_reqid(addr
, &wdata
, &cbdata
);