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
)) == 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
== 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
== 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
) == NULL
)
359 if ((wsp
->walk_addr
=
360 (uintptr_t)ptr
->an_idprev
) == NULL
)
365 if ((wsp
->walk_addr
=
366 (uintptr_t)ptr
->an_ctxchain_next
) == NULL
)
371 mdb_warn("Bad structure member in walk_step\n");
377 an_idnext_walk_step(mdb_walk_state_t
*wsp
)
379 return (an_id_walk_step(wsp
, IDNEXT
));
382 an_idprev_walk_step(mdb_walk_state_t
*wsp
)
384 return (an_id_walk_step(wsp
, IDPREV
));
387 an_ctxchain_walk_step(mdb_walk_state_t
*wsp
)
389 return (an_id_walk_step(wsp
, CTXCHAIN
));
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.
398 areq_walk_fini(mdb_walk_state_t
*wsp
)
401 mdb_printf("...end of kcf_areq_node walk\n");
403 mdb_free(wsp
->walk_data
, sizeof (kcf_areq_node_t
));
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.
412 an_walk_step_common(mdb_walk_state_t
*wsp
, boolean_t use_next
)
415 kcf_areq_node_t
*ptr
;
417 ptr
= (kcf_areq_node_t
*)wsp
->walk_data
;
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
);
424 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
427 if ((wsp
->walk_addr
= (use_next
? (uintptr_t)ptr
->an_next
:
428 (uintptr_t)ptr
->an_prev
)) == NULL
)
435 an_next_walk_step(mdb_walk_state_t
*wsp
)
437 return (an_walk_step_common(wsp
, B_TRUE
));
441 an_prev_walk_step(mdb_walk_state_t
*wsp
)
443 return (an_walk_step_common(wsp
, B_FALSE
));
447 * Walker data for reqid_table walking
449 typedef struct reqid_data
{
450 kcf_reqid_table_t rd_table
;
451 kcf_reqid_table_t
*rd_tbl_ptrs
[REQID_TABLES
];
455 typedef struct reqid_cb_data
{
456 crypto_req_id_t cb_reqid
;
461 extern int crypto_pr_reqid(uintptr_t, reqid_data_t
*, reqid_cb_data_t
*);
465 reqid_table_walk_init(mdb_walk_state_t
*wsp
)
468 reqid_cb_data_t
*cbdata
;
470 wsp
->walk_callback
= (mdb_walk_cb_t
)crypto_pr_reqid
;
472 wsp
->walk_data
= mdb_alloc(sizeof (reqid_data_t
), UM_SLEEP
);
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");
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;
488 wdata
= (reqid_data_t
*)wsp
->walk_data
;
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'");
496 wdata
->rd_cur_index
= 0;
497 wsp
->walk_addr
= (uintptr_t)wdata
->rd_tbl_ptrs
[wdata
->rd_cur_index
];
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
508 reqid_table_walk_step(mdb_walk_state_t
*wsp
)
514 wdata
= wsp
->walk_data
;
515 wsp
->walk_addr
= (uintptr_t)wdata
->rd_tbl_ptrs
[wdata
->rd_cur_index
];
519 "DEBUG: kcf_reqid_table at %p, sizeof kcf_reqid_table_t = %d\n",
520 wsp
->walk_addr
, sizeof (kcf_reqid_table_t
));
523 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
526 /* get ready for next call */
527 wdata
->rd_cur_index
++;
528 if (wdata
->rd_cur_index
>= REQID_TABLES
)
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.
539 reqid_table_walk_fini(mdb_walk_state_t
*wsp
)
542 mdb_printf("...end of kcf_reqid walk\n");
544 mdb_free(wsp
->walk_data
, sizeof (reqid_data_t
));
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.
553 crypto_pr_reqid(uintptr_t addr
, reqid_data_t
*data
, reqid_cb_data_t
*cbdata
)
555 kcf_areq_node_t node
;
560 mdb_printf("kcf_reqid_table[%d] = NULL\n", data
->rd_cur_index
);
564 if (mdb_vread(&(data
->rd_table
), sizeof (kcf_reqid_table_t
),
566 mdb_warn("failed to read kcf_reqid_table at %p",
571 /* Loop over all rt_idhash's */
572 for (i
= 0; i
< REQID_BUCKETS
; i
++) {
573 uint_t number_in_chain
= 0;
576 /* follow the an_idnext chains for each bucket */
578 /* read kcf_areq_node */
579 if (number_in_chain
== 0)
580 node_addr
= (uintptr_t)data
->rd_table
.rt_idhash
[i
];
583 node_addr
= (uintptr_t)node
.an_idnext
;
585 mdb_printf("DEBUG: node_addr = %p\n", node_addr
);
588 if (node_addr
== NULL
)
591 if (mdb_vread(&node
, sizeof (kcf_areq_node_t
), node_addr
)
593 if (cbdata
->verbose
== TRUE
)
595 "cannot read rt_idhash %d an_idnext %d\n",
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
);
613 /* print kcf_areq_node */
614 if (number_in_chain
< 1)
616 " %<b>rt_idhash[%lu%]%</b> = %<b>%p:%</b>\n",
621 " an_idnext %d = %<b>%p:%</b>\n",
622 i
, number_in_chain
, node_addr
);
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
)
632 * verbose for this walker means non-verbose for
633 * the kcf_areq_node details
635 kcf_areq_node_simple(&node
);
638 /* if we only wanted one reqid, quit now */
639 if (node
.an_reqarg
.cr_reqid
== cbdata
->cb_reqid
) {
645 } while (node
.an_idnext
!= NULL
); /* follow chain in same bucket */
647 } /* for each REQID_BUCKETS */
649 if ((needhdr
== TRUE
) && (cbdata
->cb_reqid
== 0)) {
650 mdb_printf("%kcf_reqid_table[%lu]: %p\n",
651 data
->rd_cur_index
, addr
);
658 crypto_find_reqid(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
660 const mdb_arg_t
*argp
= NULL
;
661 reqid_cb_data_t cbdata
;
664 cbdata
.cb_reqid
= 0L;
665 cbdata
.verbose
= FALSE
;
666 cbdata
.found
= FALSE
;
668 if (flags
& DCMD_ADDRSPEC
) {
669 mdb_printf("use addr ::kcf_reqid_table\n");
672 if ((i
= mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
,
673 &cbdata
.verbose
, NULL
)) != argc
) {
681 if ((argp
!= NULL
)) {
682 if (argp
->a_type
== MDB_TYPE_IMMEDIATE
)
683 cbdata
.cb_reqid
= argp
->a_un
.a_val
;
685 cbdata
.cb_reqid
= (crypto_req_id_t
)
686 mdb_strtoull(argp
->a_un
.a_str
);
688 status
= mdb_pwalk("kcf_reqid_table", (mdb_walk_cb_t
)crypto_pr_reqid
,
691 if ((cbdata
.cb_reqid
!= 0L) && (cbdata
.found
== FALSE
))
692 mdb_printf("ID 0x%lx not found\n", cbdata
.cb_reqid
);
695 mdb_printf("DEBUG: cbdata.db_reqid = %lx, cbdata.found = %d\n",
696 cbdata
.cb_reqid
, cbdata
.found
);
703 kcf_reqid_table_dcmd(uintptr_t addr
, uint_t flags
, int argc
,
704 const mdb_arg_t
*argv
)
707 reqid_cb_data_t cbdata
;
709 if (!(flags
& DCMD_ADDRSPEC
))
712 memset(&wdata
, 0, sizeof (wdata
));
713 memset(&cbdata
, 0, sizeof (cbdata
));
715 if ((mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
,
716 &cbdata
.verbose
, NULL
)) != argc
) {
719 crypto_pr_reqid(addr
, &wdata
, &cbdata
);