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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/mdb_modapi.h>
30 #include <sys/fm/protocol.h>
32 #include <topo_tree.h>
33 #include <topo_module.h>
38 * We use this to keep track of which bucket we're in while walking
39 * the modhash and we also cache the length of the hash
41 static topo_modhash_t tmh
;
42 static uint_t hash_idx
;
44 static uintptr_t curr_pg
;
45 static uint_t is_root
;
46 static uint_t verbose
;
48 static char *tgt_scheme
;
49 static char parent
[255];
52 * This structure is used by the topo_nodehash walker instances to
53 * keep track of where they're at in the node hash
55 typedef struct tnwalk_state
{
58 topo_nodehash_t
*curr_hash
;
62 static char *stab_lvls
[] = {"Internal", "", "Private", "Obsolete", "External",
63 "Unstable", "Evolving", "Stable", "Standard", "Max"};
67 topo_handle(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
69 char uuid
[36], root
[36], plat
[36], isa
[36], machine
[36], product
[36];
73 * Read in the structure and then read in all of the string fields from
74 * the target's addr space
76 if (mdb_vread(&th
, sizeof (th
), addr
) != sizeof (th
)) {
77 mdb_warn("failed to read topo_hdl_t at %p", addr
);
81 if (mdb_readstr(uuid
, sizeof (uuid
), (uintptr_t)th
.th_uuid
) < 0) {
82 (void) mdb_snprintf(uuid
, sizeof (uuid
), "<%p>", th
.th_uuid
);
84 if (mdb_readstr(root
, sizeof (root
), (uintptr_t)th
.th_rootdir
) < 0) {
85 (void) mdb_snprintf(root
, sizeof (root
), "<%p>", th
.th_rootdir
);
87 if (mdb_readstr(plat
, sizeof (plat
), (uintptr_t)th
.th_platform
) < 0) {
88 (void) mdb_snprintf(plat
, sizeof (plat
), "<%p>",
91 if (mdb_readstr(isa
, sizeof (isa
), (uintptr_t)th
.th_isa
) < 0) {
92 (void) mdb_snprintf(isa
, sizeof (isa
), "<%p>", th
.th_isa
);
94 if (mdb_readstr(machine
, sizeof (machine
), (uintptr_t)th
.th_machine
)
97 (void) mdb_snprintf(machine
, sizeof (machine
), "<%p>",
100 if (mdb_readstr(product
, sizeof (product
), (uintptr_t)th
.th_product
)
103 (void) mdb_snprintf(product
, sizeof (product
), "<%p>",
108 * Dump it all out in a nice pretty format and keep it to 80 chars wide
110 if (DCMD_HDRSPEC(flags
)) {
111 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", "FIELD", "VALUE",
114 mdb_printf("%-12s 0x%-34p %-30s\n", "th_lock",
115 addr
+ offsetof(topo_hdl_t
, th_lock
),
116 "Mutex lock protecting handle");
117 mdb_printf("%-12s %-36s %-30s\n", "th_uuid", uuid
,
118 "UUID of the topology snapshot");
119 mdb_printf("%-12s %-36s %-30s\n", "th_rootdir", root
,
120 "Root directory of plugin paths");
121 mdb_printf("%-12s %-36s %-30s\n", "th_platform", plat
, "Platform name");
122 mdb_printf("%-12s %-36s %-30s\n", "th_isa", isa
, "ISA name");
123 mdb_printf("%-12s %-36s %-30s\n", "th_machine", machine
,
125 mdb_printf("%-12s %-36s %-30s\n", "th_product", product
,
127 mdb_printf("%-12s 0x%-34p %-30s\n", "th_di", th
.th_di
,
128 "Handle to the root of the devinfo tree");
129 mdb_printf("%-12s 0x%-34p %-30s\n", "th_pi", th
.th_pi
,
130 "Handle to the root of the PROM tree");
131 mdb_printf("%-12s 0x%-34p %-30s\n", "th_modhash", th
.th_modhash
,
133 mdb_printf("%-12s %-36s %-30s\n", "th_trees", "",
134 "Scheme-specific topo tree list");
135 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_prev", th
.th_trees
.l_prev
,
137 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_next", th
.th_trees
.l_next
,
139 mdb_printf("%-12s 0x%-34p %-30s\n", "th_alloc", th
.th_alloc
,
141 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", th
.th_errno
, "errno");
142 mdb_printf("%-12s %-36d %-30s\n", "tm_debug", th
.th_debug
,
144 mdb_printf("%-12s %-36d %-30s\n", "tm_dbout", th
.th_dbout
,
153 topo_module(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
155 char name
[36], path
[36], root
[36];
159 * Read in the structure and then read in all of the string fields from
160 * the target's addr space
162 if (mdb_vread(&tm
, sizeof (tm
), addr
) != sizeof (tm
)) {
163 mdb_warn("failed to read topo_mod_t at %p", addr
);
167 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)tm
.tm_name
) < 0) {
168 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", tm
.tm_name
);
170 if (mdb_readstr(path
, sizeof (path
), (uintptr_t)tm
.tm_path
) < 0) {
171 (void) mdb_snprintf(path
, sizeof (path
), "<%p>", tm
.tm_path
);
173 if (mdb_readstr(root
, sizeof (root
), (uintptr_t)tm
.tm_rootdir
) < 0) {
174 (void) mdb_snprintf(root
, sizeof (root
), "<%p>", tm
.tm_rootdir
);
178 * Dump it all out in a nice pretty format and keep it to 80 chars wide
180 if (DCMD_HDRSPEC(flags
)) {
181 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
182 "FIELD", "VALUE", "DESCR");
184 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_lock",
185 addr
+ offsetof(topo_mod_t
, tm_lock
),
186 "Lock for tm_cv/owner/flags/refs");
187 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_cv",
188 addr
+ offsetof(topo_mod_t
, tm_cv
),
189 "Module condition variable");
191 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "TRUE",
194 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "FALSE",
197 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_next", tm
.tm_next
,
198 "Next module in hash chain");
199 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_hdl", tm
.tm_hdl
,
200 "Topo handle for this module");
201 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_alloc", tm
.tm_alloc
,
203 mdb_printf("%-12s %-36s %-30s\n", "tm_name", name
,
204 "Basename of module");
205 mdb_printf("%-12s %-36s %-30s\n", "tm_path", path
,
206 "Full pathname of module");
207 mdb_printf("%-12s %-36s %-30s\n", "tm_rootdir", root
,
208 "Relative root directory of module");
209 mdb_printf("%-12s %-36u %-30s\n", "tm_refs", tm
.tm_refs
,
210 "Module reference count");
211 mdb_printf("%-12s %-36u %-30s\n", "tm_flags", tm
.tm_flags
,
213 if (TOPO_MOD_INIT
& tm
.tm_flags
) {
214 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_INIT",
215 "Module init completed");
217 if (TOPO_MOD_FINI
& tm
.tm_flags
) {
218 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_FINI",
219 "Module fini completed");
221 if (TOPO_MOD_REG
& tm
.tm_flags
) {
222 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_REG",
223 "Module registered");
225 if (TOPO_MOD_UNREG
& tm
.tm_flags
) {
226 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_UNREG",
227 "Module unregistered");
230 mdb_printf("%-12s %-36u %-30s\n", "tm_debug", tm
.tm_debug
,
231 "Debug printf mask");
232 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_data", tm
.tm_data
,
233 "Private rtld/builtin data");
234 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_mops", tm
.tm_mops
,
235 "Module class ops vector");
236 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_info", tm
.tm_info
,
237 "Module info registered with handle");
238 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", tm
.tm_errno
,
247 topo_node(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
256 * Read in the structure and then read in all of the string fields from
257 * the target's addr space
259 if (mdb_vread(&tn
, sizeof (tn
), addr
) != sizeof (tn
)) {
260 mdb_warn("failed to read tnode_t at %p", addr
);
264 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)tn
.tn_name
) < 0) {
265 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", tn
.tn_name
);
269 * Dump it all out in a nice pretty format and keep it to 80 chars wide
271 if (DCMD_HDRSPEC(flags
)) {
272 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
273 "FIELD", "VALUE", "DESCR");
276 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_lock",
277 addr
+ offsetof(tnode_t
, tn_lock
),
278 "Lock protecting node members");
279 mdb_printf("%-12s %-36s %-30s\n", "tn_name", name
,
281 mdb_printf("%-12s %-36d %-30s\n", "tn_instance", tn
.tn_instance
,
283 mdb_printf("%-12s %-36d %-30s\n", "tn_state", tn
.tn_state
,
285 if (TOPO_NODE_INIT
& tn
.tn_state
) {
286 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_INIT", "");
288 if (TOPO_NODE_ROOT
& tn
.tn_state
) {
289 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_ROOT", "");
291 if (TOPO_NODE_BOUND
& tn
.tn_state
) {
292 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_BOUND", "");
294 if (TOPO_NODE_LINKED
& tn
.tn_state
) {
295 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_LINKED", "");
297 mdb_printf("%-12s %-36d %-30s\n", "tn_fflags", tn
.tn_fflags
,
299 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_parent", tn
.tn_parent
,
301 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_phash", tn
.tn_phash
,
302 "Parent hash bucket");
303 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_hdl", tn
.tn_hdl
,
305 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_enum", tn
.tn_enum
,
306 "Enumerator module");
307 mdb_printf("%-12s %-36s %-30s\n", "tn_children", "",
308 "Hash table of child nodes");
309 mdb_printf(" %-12s 0x%-34p\n", "l_prev", tn
.tn_children
.l_prev
);
310 mdb_printf(" %-12s 0x%-34p\n", "l_next", tn
.tn_children
.l_next
);
311 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_pgroups", &(tn
.tn_pgroups
),
312 "Property group list");
313 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_methods", &(tn
.tn_methods
),
314 "Registered method list");
315 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_priv", tn
.tn_priv
,
316 "Private enumerator data");
317 mdb_printf("%-12s %-36d %-30s\n", "tn_refs", tn
.tn_refs
,
318 "Node reference count");
325 find_tree_root(uintptr_t addr
, const void *data
, void *arg
)
327 ttree_t
*tree
= (ttree_t
*)data
;
330 if (mdb_readstr(scheme
, sizeof (scheme
), (uintptr_t)tree
->tt_scheme
)
332 (void) mdb_snprintf(scheme
, sizeof (scheme
), "<%p>",
336 if (strncmp(tgt_scheme
, scheme
, 36) == 0) {
337 *((tnode_t
**)arg
) = tree
->tt_root
;
344 dump_propmethod(uintptr_t addr
)
346 topo_propmethod_t pm
;
349 if (mdb_vread(&pm
, sizeof (pm
), addr
) != sizeof (pm
)) {
350 mdb_warn("failed to read topo_propmethod at %p", addr
);
353 if (mdb_readstr(mname
, sizeof (mname
), (uintptr_t)pm
.tpm_name
) < 0) {
354 (void) mdb_snprintf(mname
, sizeof (mname
), "<%p>", pm
.tpm_name
);
357 mdb_printf(" method: %-32s version: %-16d args: %p\n",
358 mname
, pm
.tpm_version
, pm
.tpm_args
);
362 * Dump the given property value. For the actual property values
363 * we dump a pointer to the nvlist which can be decoded using the ::nvlist
364 * dcmd from the libnvpair MDB module
368 dump_propval(uintptr_t addr
, const void *data
, void *arg
)
370 topo_proplist_t
*plistp
= (topo_proplist_t
*)data
;
372 char name
[32], *type
;
374 if (mdb_vread(&pval
, sizeof (pval
), (uintptr_t)plistp
->tp_pval
)
377 mdb_warn("failed to read topo_propval_t at %p",
381 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)pval
.tp_name
) < 0) {
382 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", pval
.tp_name
);
384 switch (pval
.tp_type
) {
385 case TOPO_TYPE_BOOLEAN
: type
= "boolean"; break;
386 case TOPO_TYPE_INT32
: type
= "int32"; break;
387 case TOPO_TYPE_UINT32
: type
= "uint32"; break;
388 case TOPO_TYPE_INT64
: type
= "int64"; break;
389 case TOPO_TYPE_UINT64
: type
= "uint64"; break;
390 case TOPO_TYPE_STRING
: type
= "string"; break;
391 case TOPO_TYPE_FMRI
: type
= "fmri"; break;
392 case TOPO_TYPE_INT32_ARRAY
: type
= "int32[]"; break;
393 case TOPO_TYPE_UINT32_ARRAY
: type
= "uint32[]"; break;
394 case TOPO_TYPE_INT64_ARRAY
: type
= "int64[]"; break;
395 case TOPO_TYPE_UINT64_ARRAY
: type
= "uint64[]"; break;
396 case TOPO_TYPE_STRING_ARRAY
: type
= "string[]"; break;
397 case TOPO_TYPE_FMRI_ARRAY
: type
= "fmri[]"; break;
398 default: type
= "unknown type";
400 mdb_printf(" %-32s %-16s value: %p\n", name
, type
, pval
.tp_val
);
402 if (pval
.tp_method
!= NULL
)
403 dump_propmethod((uintptr_t)pval
.tp_method
);
410 * Dumps the contents of the property group.
414 dump_pgroup(uintptr_t addr
, const void *data
, void *arg
)
416 topo_pgroup_t
*pgp
= (topo_pgroup_t
*)data
;
417 topo_ipgroup_info_t ipg
;
420 if (mdb_vread(&ipg
, sizeof (ipg
), (uintptr_t)pgp
->tpg_info
)
423 mdb_warn("failed to read topo_ipgroup_info_t at %p",
427 if (mdb_readstr(buf
, sizeof (buf
), (uintptr_t)ipg
.tpi_name
) < 0) {
428 mdb_warn("failed to read string at %p", ipg
.tpi_name
);
432 * If this property group is the one we're interested in or if the user
433 * specified the "all" property group, we'll dump it
435 if ((strncmp(pgrp
, buf
, sizeof (buf
)) == 0) ||
436 (strncmp(pgrp
, "all", sizeof (buf
)) == 0)) {
438 mdb_printf(" group: %-32s version: %d, stability: %s/%s\n",
439 buf
, ipg
.tpi_version
, stab_lvls
[ipg
.tpi_namestab
],
440 stab_lvls
[ipg
.tpi_datastab
]);
442 (void) mdb_pwalk("topo_proplist", dump_propval
, NULL
, curr_pg
);
449 * Recursive function to dump the specified node and all of it's children
453 dump_tnode(uintptr_t addr
, const void *data
, void *arg
)
456 char pname
[255], buf
[80], old_pname
[255];
462 if (mdb_vread(&node
, sizeof (node
), addr
) != sizeof (node
)) {
463 mdb_warn("failed to read tnode_t at %p", addr
);
466 if (mdb_readstr(buf
, sizeof (buf
), (uintptr_t)node
.tn_name
) < 0) {
467 (void) mdb_snprintf(buf
, sizeof (buf
), "<%p>",
472 mdb_snprintf(pname
, sizeof (pname
), "%s", parent
);
475 mdb_snprintf(pname
, sizeof (pname
), "%s/%s=%u",
476 parent
, buf
, node
.tn_instance
);
479 mdb_printf("%s\n tnode_t: %p\n", pname
, addr
);
481 mdb_printf("%s\n", pname
);
483 mdb_snprintf(old_pname
, sizeof (old_pname
), "%s", parent
);
484 mdb_snprintf(parent
, sizeof (parent
), "%s", pname
);
487 (void) mdb_pwalk("topo_pgroup", dump_pgroup
, NULL
, addr
);
489 (void) mdb_pwalk("topo_nodehash", dump_tnode
, NULL
, addr
);
490 mdb_snprintf(parent
, sizeof (parent
), "%s", old_pname
);
497 * Given a topo_hdl_t *, the topo dcmd dumps the topo tree. The format of the
498 * output is modeled after fmtopo. Like fmtopo, by default, we'll dump the
499 * "hc" scheme tree. The user can optionally specify a different tree via the
500 * "-s <scheme>" option.
502 * Specifying the "-v" option provides more verbose output. Currently it
503 * outputs the tnode_t * addr for each node, which is useful if you want to
504 * dump it with the topo_node dcmd.
506 * The functionality of the "-P" option is similar to fmtopo.
510 fmtopo(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
512 char product
[36], *opt_s
= NULL
, *opt_P
= NULL
;
515 uint_t opt_v
= FALSE
;
516 char *def_scheme
= "hc";
518 if (mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
, &opt_v
,
519 's', MDB_OPT_STR
, &opt_s
, 'P', MDB_OPT_STR
, &opt_P
, NULL
)
527 tgt_scheme
= def_scheme
;
535 * Read in the topo_handle and some of its string fields from
536 * the target's addr space
538 if (mdb_vread(&th
, sizeof (th
), addr
) != sizeof (th
)) {
539 mdb_warn("failed to read topo_hdl_t at %p", addr
);
543 if (mdb_readstr(product
, sizeof (product
), (uintptr_t)th
.th_product
)
546 (void) mdb_snprintf(product
, sizeof (product
), "<%p>",
550 mdb_snprintf(parent
, sizeof (parent
),
551 "%s://:product-id=%s", tgt_scheme
, product
);
554 * Walk the list of topo trees, looking for the one that is for the
555 * scheme we're interested in.
558 mdb_pwalk("topo_tree", find_tree_root
, &tree_root
, addr
);
561 mdb_warn("failed to find a topo tree for scheme %s\n",
566 return (dump_tnode((uintptr_t)tree_root
, NULL
, NULL
));
571 ttree_walk_init(mdb_walk_state_t
*wsp
)
575 if (wsp
->walk_addr
== NULL
) {
576 mdb_warn("NULL topo_hdl_t passed in");
580 if (mdb_vread(&th
, sizeof (th
), wsp
->walk_addr
) != sizeof (th
)) {
581 mdb_warn("failed to read topo_hdl_t at %p", wsp
->walk_addr
);
585 wsp
->walk_addr
= (uintptr_t)th
.th_trees
.l_next
;
586 wsp
->walk_data
= mdb_alloc(sizeof (ttree_t
), UM_SLEEP
);
593 ttree_walk_step(mdb_walk_state_t
*wsp
)
598 if (wsp
->walk_addr
== NULL
)
601 if (mdb_vread(wsp
->walk_data
, sizeof (ttree_t
), wsp
->walk_addr
)
602 != sizeof (ttree_t
)) {
604 mdb_warn("failed to read ttree_t at %p", wsp
->walk_addr
);
608 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
611 tree
= (ttree_t
*)wsp
->walk_data
;
612 wsp
->walk_addr
= (uintptr_t)tree
->tt_list
.l_next
;
619 ttree_walk_fini(mdb_walk_state_t
*wsp
)
621 mdb_free(wsp
->walk_data
, sizeof (ttree_t
));
626 tmod_walk_init(mdb_walk_state_t
*wsp
)
630 if (wsp
->walk_addr
== NULL
) {
631 mdb_warn("NULL topo_hdl_t passed in");
635 if (mdb_vread(&th
, sizeof (th
), wsp
->walk_addr
) != sizeof (th
)) {
636 mdb_warn("failed to read topo_hdl_t at %p", wsp
->walk_addr
);
640 if (mdb_vread(&tmh
, sizeof (topo_modhash_t
), (uintptr_t)th
.th_modhash
)
643 mdb_warn("failed to read topo_modhash_t at %p", wsp
->walk_addr
);
649 if (mdb_vread(&(wsp
->walk_addr
), sizeof (uintptr_t *),
650 (uintptr_t)(tmh
.mh_hash
)) != sizeof (tnode_t
*)) {
652 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t
*),
657 wsp
->walk_data
= mdb_alloc(sizeof (topo_mod_t
), UM_SLEEP
);
664 tmod_walk_step(mdb_walk_state_t
*wsp
)
669 if (wsp
->walk_addr
== NULL
)
672 if (mdb_vread(wsp
->walk_data
, sizeof (topo_mod_t
), wsp
->walk_addr
)
675 mdb_warn("failed to read topo_mod_t at %p", wsp
->walk_addr
);
679 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
682 tm
= (topo_mod_t
*)wsp
->walk_data
;
685 wsp
->walk_addr
= (uintptr_t)tm
->tm_next
;
686 else if (++hash_idx
< tmh
.mh_hashlen
)
687 if (mdb_vread(&(wsp
->walk_addr
), sizeof (uintptr_t *),
688 (uintptr_t)(tmh
.mh_hash
+hash_idx
)) != sizeof (tnode_t
*)) {
690 mdb_warn("failed to read %u bytes at %p",
691 sizeof (tnode_t
*), tmh
.mh_hash
+hash_idx
);
695 wsp
->walk_addr
= NULL
;
701 tmod_walk_fini(mdb_walk_state_t
*wsp
)
703 mdb_free(wsp
->walk_data
, sizeof (topo_mod_t
));
708 tpg_walk_init(mdb_walk_state_t
*wsp
)
712 if (wsp
->walk_addr
== NULL
) {
713 mdb_warn("NULL tnode_t passed in");
717 if (mdb_vread(&node
, sizeof (node
), wsp
->walk_addr
) != sizeof (node
)) {
718 mdb_warn("failed to read tnode_t at %p", wsp
->walk_addr
);
722 wsp
->walk_addr
= (uintptr_t)node
.tn_pgroups
.l_next
;
723 wsp
->walk_data
= mdb_alloc(sizeof (topo_pgroup_t
), UM_SLEEP
);
730 tpg_walk_step(mdb_walk_state_t
*wsp
)
735 if (wsp
->walk_addr
== NULL
)
738 if (mdb_vread(wsp
->walk_data
, sizeof (topo_pgroup_t
), wsp
->walk_addr
)
741 mdb_warn("failed to read topo_pgroup_t at %p", wsp
->walk_addr
);
745 curr_pg
= wsp
->walk_addr
;
746 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
749 tpgp
= (topo_pgroup_t
*)wsp
->walk_data
;
750 wsp
->walk_addr
= (uintptr_t)tpgp
->tpg_list
.l_next
;
757 tpg_walk_fini(mdb_walk_state_t
*wsp
)
759 mdb_free(wsp
->walk_data
, sizeof (topo_pgroup_t
));
764 tpl_walk_init(mdb_walk_state_t
*wsp
)
768 if (wsp
->walk_addr
== NULL
) {
769 mdb_warn("NULL topo_pgroup_t passed in");
773 if (mdb_vread(&pg
, sizeof (pg
), wsp
->walk_addr
) != sizeof (pg
)) {
774 mdb_warn("failed to read topo_pgroup_t at %p", wsp
->walk_addr
);
778 wsp
->walk_addr
= (uintptr_t)pg
.tpg_pvals
.l_next
;
779 wsp
->walk_data
= mdb_alloc(sizeof (topo_proplist_t
), UM_SLEEP
);
786 tpl_walk_step(mdb_walk_state_t
*wsp
)
789 topo_proplist_t
*plp
;
791 if (wsp
->walk_addr
== NULL
)
794 if (mdb_vread(wsp
->walk_data
, sizeof (topo_proplist_t
), wsp
->walk_addr
)
797 mdb_warn("failed to read topo_proplist_t at %p",
801 plp
= (topo_proplist_t
*)wsp
->walk_data
;
803 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
806 wsp
->walk_addr
= (uintptr_t)plp
->tp_list
.l_next
;
813 tpl_walk_fini(mdb_walk_state_t
*wsp
)
815 mdb_free(wsp
->walk_data
, sizeof (topo_proplist_t
));
820 tnh_walk_init(mdb_walk_state_t
*wsp
)
823 tnwalk_state_t
*state
;
825 if (wsp
->walk_addr
== NULL
) {
826 mdb_warn("NULL tnode_t passed in");
830 if (mdb_vread(&node
, sizeof (node
), wsp
->walk_addr
) != sizeof (node
)) {
831 mdb_warn("failed to read tnode_t at %p", wsp
->walk_addr
);
835 state
= mdb_zalloc(sizeof (tnwalk_state_t
), UM_SLEEP
);
837 state
->curr_hash
= (topo_nodehash_t
*)node
.tn_children
.l_next
;
839 wsp
->walk_data
= state
;
846 tnh_walk_step(mdb_walk_state_t
*wsp
)
848 tnwalk_state_t
*state
= wsp
->walk_data
;
849 int rv
, i
= state
->hash_idx
++;
852 if (state
->curr_hash
== NULL
)
855 if (mdb_vread(&(state
->hash
), sizeof (topo_nodehash_t
),
856 (uintptr_t)state
->curr_hash
) != sizeof (topo_nodehash_t
)) {
858 mdb_warn("failed to read topo_nodehash_t at %p",
859 (uintptr_t)state
->curr_hash
);
863 if (mdb_vread(&npp
, sizeof (tnode_t
*),
864 (uintptr_t)(state
->hash
.th_nodearr
+i
)) != sizeof (tnode_t
*)) {
866 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t
*),
867 state
->hash
.th_nodearr
+i
);
870 wsp
->walk_addr
= (uintptr_t)npp
;
872 rv
= wsp
->walk_callback(wsp
->walk_addr
, state
, wsp
->walk_cbdata
);
874 if (state
->hash_idx
>= state
->hash
.th_arrlen
) {
876 * move on to the next child hash bucket
879 (topo_nodehash_t
*)(state
->hash
.th_list
.l_next
);
888 tnh_walk_fini(mdb_walk_state_t
*wsp
)
890 mdb_free(wsp
->walk_data
, sizeof (tnwalk_state_t
));
894 static const mdb_dcmd_t dcmds
[] = {
895 { "topo_handle", "", "print contents of a topo handle", topo_handle
,
897 { "topo_module", "", "print contents of a topo module handle",
899 { "topo_node", "", "print contents of a topo node", topo_node
, NULL
},
900 { "fmtopo", "[-P <pgroup>][-s <scheme>][-v]",
901 "print topology of the given handle", fmtopo
, NULL
},
905 static const mdb_walker_t walkers
[] = {
906 { "topo_tree", "walk the tree list for a given topo handle",
907 ttree_walk_init
, ttree_walk_step
, ttree_walk_fini
, NULL
},
908 { "topo_module", "walk the module hash for a given topo handle",
909 tmod_walk_init
, tmod_walk_step
, tmod_walk_fini
, NULL
},
910 { "topo_pgroup", "walk the property groups for a given topo node",
911 tpg_walk_init
, tpg_walk_step
, tpg_walk_fini
, NULL
},
912 { "topo_proplist", "walk the property list for a given property group",
913 tpl_walk_init
, tpl_walk_step
, tpl_walk_fini
, NULL
},
914 { "topo_nodehash", "walk the child nodehash for a given topo node",
915 tnh_walk_init
, tnh_walk_step
, tnh_walk_fini
, NULL
},
919 static const mdb_modinfo_t modinfo
= {
920 MDB_API_VERSION
, dcmds
, walkers
923 const mdb_modinfo_t
*