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 #include <sys/mdb_modapi.h>
28 #include <sys/fm/protocol.h>
30 #include <topo_tree.h>
31 #include <topo_module.h>
36 * We use this to keep track of which bucket we're in while walking
37 * the modhash and we also cache the length of the hash
39 static topo_modhash_t tmh
;
40 static uint_t hash_idx
;
42 static uintptr_t curr_pg
;
43 static uint_t is_root
;
44 static uint_t verbose
;
46 static char *tgt_scheme
;
47 static char parent
[255];
50 * This structure is used by the topo_nodehash walker instances to
51 * keep track of where they're at in the node hash
53 typedef struct tnwalk_state
{
56 topo_nodehash_t
*curr_hash
;
60 static char *stab_lvls
[] = {"Internal", "", "Private", "Obsolete", "External",
61 "Unstable", "Evolving", "Stable", "Standard", "Max"};
65 topo_handle(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
67 char uuid
[36], root
[36], plat
[36], isa
[36], machine
[36], product
[36];
71 * Read in the structure and then read in all of the string fields from
72 * the target's addr space
74 if (mdb_vread(&th
, sizeof (th
), addr
) != sizeof (th
)) {
75 mdb_warn("failed to read topo_hdl_t at %p", addr
);
79 if (mdb_readstr(uuid
, sizeof (uuid
), (uintptr_t)th
.th_uuid
) < 0) {
80 (void) mdb_snprintf(uuid
, sizeof (uuid
), "<%p>", th
.th_uuid
);
82 if (mdb_readstr(root
, sizeof (root
), (uintptr_t)th
.th_rootdir
) < 0) {
83 (void) mdb_snprintf(root
, sizeof (root
), "<%p>", th
.th_rootdir
);
85 if (mdb_readstr(plat
, sizeof (plat
), (uintptr_t)th
.th_platform
) < 0) {
86 (void) mdb_snprintf(plat
, sizeof (plat
), "<%p>",
89 if (mdb_readstr(isa
, sizeof (isa
), (uintptr_t)th
.th_isa
) < 0) {
90 (void) mdb_snprintf(isa
, sizeof (isa
), "<%p>", th
.th_isa
);
92 if (mdb_readstr(machine
, sizeof (machine
), (uintptr_t)th
.th_machine
)
95 (void) mdb_snprintf(machine
, sizeof (machine
), "<%p>",
98 if (mdb_readstr(product
, sizeof (product
), (uintptr_t)th
.th_product
)
101 (void) mdb_snprintf(product
, sizeof (product
), "<%p>",
106 * Dump it all out in a nice pretty format and keep it to 80 chars wide
108 if (DCMD_HDRSPEC(flags
)) {
109 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", "FIELD", "VALUE",
112 mdb_printf("%-12s 0x%-34p %-30s\n", "th_lock",
113 addr
+ offsetof(topo_hdl_t
, th_lock
),
114 "Mutex lock protecting handle");
115 mdb_printf("%-12s %-36s %-30s\n", "th_uuid", uuid
,
116 "UUID of the topology snapshot");
117 mdb_printf("%-12s %-36s %-30s\n", "th_rootdir", root
,
118 "Root directory of plugin paths");
119 mdb_printf("%-12s %-36s %-30s\n", "th_platform", plat
, "Platform name");
120 mdb_printf("%-12s %-36s %-30s\n", "th_isa", isa
, "ISA name");
121 mdb_printf("%-12s %-36s %-30s\n", "th_machine", machine
,
123 mdb_printf("%-12s %-36s %-30s\n", "th_product", product
,
125 mdb_printf("%-12s 0x%-34p %-30s\n", "th_di", th
.th_di
,
126 "Handle to the root of the devinfo tree");
127 mdb_printf("%-12s 0x%-34p %-30s\n", "th_pi", th
.th_pi
,
128 "Handle to the root of the PROM tree");
129 mdb_printf("%-12s 0x%-34p %-30s\n", "th_modhash", th
.th_modhash
,
131 mdb_printf("%-12s %-36s %-30s\n", "th_trees", "",
132 "Scheme-specific topo tree list");
133 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_prev", th
.th_trees
.l_prev
,
135 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_next", th
.th_trees
.l_next
,
137 mdb_printf("%-12s 0x%-34p %-30s\n", "th_alloc", th
.th_alloc
,
139 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", th
.th_errno
, "errno");
140 mdb_printf("%-12s %-36d %-30s\n", "tm_debug", th
.th_debug
,
142 mdb_printf("%-12s %-36d %-30s\n", "tm_dbout", th
.th_dbout
,
151 topo_module(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
153 char name
[36], path
[36], root
[36];
157 * Read in the structure and then read in all of the string fields from
158 * the target's addr space
160 if (mdb_vread(&tm
, sizeof (tm
), addr
) != sizeof (tm
)) {
161 mdb_warn("failed to read topo_mod_t at %p", addr
);
165 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)tm
.tm_name
) < 0) {
166 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", tm
.tm_name
);
168 if (mdb_readstr(path
, sizeof (path
), (uintptr_t)tm
.tm_path
) < 0) {
169 (void) mdb_snprintf(path
, sizeof (path
), "<%p>", tm
.tm_path
);
171 if (mdb_readstr(root
, sizeof (root
), (uintptr_t)tm
.tm_rootdir
) < 0) {
172 (void) mdb_snprintf(root
, sizeof (root
), "<%p>", tm
.tm_rootdir
);
176 * Dump it all out in a nice pretty format and keep it to 80 chars wide
178 if (DCMD_HDRSPEC(flags
)) {
179 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
180 "FIELD", "VALUE", "DESCR");
182 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_lock",
183 addr
+ offsetof(topo_mod_t
, tm_lock
),
184 "Lock for tm_cv/owner/flags/refs");
185 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_cv",
186 addr
+ offsetof(topo_mod_t
, tm_cv
),
187 "Module condition variable");
189 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "TRUE",
192 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "FALSE",
195 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_next", tm
.tm_next
,
196 "Next module in hash chain");
197 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_hdl", tm
.tm_hdl
,
198 "Topo handle for this module");
199 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_alloc", tm
.tm_alloc
,
201 mdb_printf("%-12s %-36s %-30s\n", "tm_name", name
,
202 "Basename of module");
203 mdb_printf("%-12s %-36s %-30s\n", "tm_path", path
,
204 "Full pathname of module");
205 mdb_printf("%-12s %-36s %-30s\n", "tm_rootdir", root
,
206 "Relative root directory of module");
207 mdb_printf("%-12s %-36u %-30s\n", "tm_refs", tm
.tm_refs
,
208 "Module reference count");
209 mdb_printf("%-12s %-36u %-30s\n", "tm_flags", tm
.tm_flags
,
211 if (TOPO_MOD_INIT
& tm
.tm_flags
) {
212 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_INIT",
213 "Module init completed");
215 if (TOPO_MOD_FINI
& tm
.tm_flags
) {
216 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_FINI",
217 "Module fini completed");
219 if (TOPO_MOD_REG
& tm
.tm_flags
) {
220 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_REG",
221 "Module registered");
223 if (TOPO_MOD_UNREG
& tm
.tm_flags
) {
224 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_UNREG",
225 "Module unregistered");
228 mdb_printf("%-12s %-36u %-30s\n", "tm_debug", tm
.tm_debug
,
229 "Debug printf mask");
230 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_data", tm
.tm_data
,
231 "Private rtld/builtin data");
232 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_mops", tm
.tm_mops
,
233 "Module class ops vector");
234 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_info", tm
.tm_info
,
235 "Module info registered with handle");
236 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", tm
.tm_errno
,
245 topo_node(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
254 * Read in the structure and then read in all of the string fields from
255 * the target's addr space
257 if (mdb_vread(&tn
, sizeof (tn
), addr
) != sizeof (tn
)) {
258 mdb_warn("failed to read tnode_t at %p", addr
);
262 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)tn
.tn_name
) < 0) {
263 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", tn
.tn_name
);
267 * Dump it all out in a nice pretty format and keep it to 80 chars wide
269 if (DCMD_HDRSPEC(flags
)) {
270 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
271 "FIELD", "VALUE", "DESCR");
274 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_lock",
275 addr
+ offsetof(tnode_t
, tn_lock
),
276 "Lock protecting node members");
277 mdb_printf("%-12s %-36s %-30s\n", "tn_name", name
,
279 mdb_printf("%-12s %-36d %-30s\n", "tn_instance", tn
.tn_instance
,
281 mdb_printf("%-12s %-36d %-30s\n", "tn_state", tn
.tn_state
,
283 if (TOPO_NODE_INIT
& tn
.tn_state
) {
284 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_INIT", "");
286 if (TOPO_NODE_ROOT
& tn
.tn_state
) {
287 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_ROOT", "");
289 if (TOPO_NODE_BOUND
& tn
.tn_state
) {
290 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_BOUND", "");
292 if (TOPO_NODE_LINKED
& tn
.tn_state
) {
293 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_LINKED", "");
295 mdb_printf("%-12s %-36d %-30s\n", "tn_fflags", tn
.tn_fflags
,
297 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_parent", tn
.tn_parent
,
299 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_phash", tn
.tn_phash
,
300 "Parent hash bucket");
301 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_hdl", tn
.tn_hdl
,
303 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_enum", tn
.tn_enum
,
304 "Enumerator module");
305 mdb_printf("%-12s %-36s %-30s\n", "tn_children", "",
306 "Hash table of child nodes");
307 mdb_printf(" %-12s 0x%-34p\n", "l_prev", tn
.tn_children
.l_prev
);
308 mdb_printf(" %-12s 0x%-34p\n", "l_next", tn
.tn_children
.l_next
);
309 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_pgroups", &(tn
.tn_pgroups
),
310 "Property group list");
311 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_methods", &(tn
.tn_methods
),
312 "Registered method list");
313 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_priv", tn
.tn_priv
,
314 "Private enumerator data");
315 mdb_printf("%-12s %-36d %-30s\n", "tn_refs", tn
.tn_refs
,
316 "Node reference count");
323 find_tree_root(uintptr_t addr
, const void *data
, void *arg
)
325 ttree_t
*tree
= (ttree_t
*)data
;
328 if (mdb_readstr(scheme
, sizeof (scheme
), (uintptr_t)tree
->tt_scheme
)
330 (void) mdb_snprintf(scheme
, sizeof (scheme
), "<%p>",
334 if (strncmp(tgt_scheme
, scheme
, 36) == 0) {
335 *((tnode_t
**)arg
) = tree
->tt_root
;
342 dump_propmethod(uintptr_t addr
)
344 topo_propmethod_t pm
;
347 if (mdb_vread(&pm
, sizeof (pm
), addr
) != sizeof (pm
)) {
348 mdb_warn("failed to read topo_propmethod at %p", addr
);
351 if (mdb_readstr(mname
, sizeof (mname
), (uintptr_t)pm
.tpm_name
) < 0) {
352 (void) mdb_snprintf(mname
, sizeof (mname
), "<%p>", pm
.tpm_name
);
355 mdb_printf(" method: %-32s version: %-16d args: %p\n",
356 mname
, pm
.tpm_version
, pm
.tpm_args
);
360 * Dump the given property value. For the actual property values
361 * we dump a pointer to the nvlist which can be decoded using the ::nvlist
362 * dcmd from the libnvpair MDB module
366 dump_propval(uintptr_t addr
, const void *data
, void *arg
)
368 topo_proplist_t
*plistp
= (topo_proplist_t
*)data
;
370 char name
[32], *type
;
372 if (mdb_vread(&pval
, sizeof (pval
), (uintptr_t)plistp
->tp_pval
)
375 mdb_warn("failed to read topo_propval_t at %p",
379 if (mdb_readstr(name
, sizeof (name
), (uintptr_t)pval
.tp_name
) < 0) {
380 (void) mdb_snprintf(name
, sizeof (name
), "<%p>", pval
.tp_name
);
382 switch (pval
.tp_type
) {
383 case TOPO_TYPE_BOOLEAN
: type
= "boolean"; break;
384 case TOPO_TYPE_INT32
: type
= "int32"; break;
385 case TOPO_TYPE_UINT32
: type
= "uint32"; break;
386 case TOPO_TYPE_INT64
: type
= "int64"; break;
387 case TOPO_TYPE_UINT64
: type
= "uint64"; break;
388 case TOPO_TYPE_STRING
: type
= "string"; break;
389 case TOPO_TYPE_FMRI
: type
= "fmri"; break;
390 case TOPO_TYPE_INT32_ARRAY
: type
= "int32[]"; break;
391 case TOPO_TYPE_UINT32_ARRAY
: type
= "uint32[]"; break;
392 case TOPO_TYPE_INT64_ARRAY
: type
= "int64[]"; break;
393 case TOPO_TYPE_UINT64_ARRAY
: type
= "uint64[]"; break;
394 case TOPO_TYPE_STRING_ARRAY
: type
= "string[]"; break;
395 case TOPO_TYPE_FMRI_ARRAY
: type
= "fmri[]"; break;
396 default: type
= "unknown type";
398 mdb_printf(" %-32s %-16s value: %p\n", name
, type
, pval
.tp_val
);
400 if (pval
.tp_method
!= NULL
)
401 dump_propmethod((uintptr_t)pval
.tp_method
);
408 * Dumps the contents of the property group.
412 dump_pgroup(uintptr_t addr
, const void *data
, void *arg
)
414 topo_pgroup_t
*pgp
= (topo_pgroup_t
*)data
;
415 topo_ipgroup_info_t ipg
;
418 if (mdb_vread(&ipg
, sizeof (ipg
), (uintptr_t)pgp
->tpg_info
)
421 mdb_warn("failed to read topo_ipgroup_info_t at %p",
425 if (mdb_readstr(buf
, sizeof (buf
), (uintptr_t)ipg
.tpi_name
) < 0) {
426 mdb_warn("failed to read string at %p", ipg
.tpi_name
);
430 * If this property group is the one we're interested in or if the user
431 * specified the "all" property group, we'll dump it
433 if ((strncmp(pgrp
, buf
, sizeof (buf
)) == 0) ||
434 (strncmp(pgrp
, "all", sizeof (buf
)) == 0)) {
436 mdb_printf(" group: %-32s version: %d, stability: %s/%s\n",
437 buf
, ipg
.tpi_version
, stab_lvls
[ipg
.tpi_namestab
],
438 stab_lvls
[ipg
.tpi_datastab
]);
440 (void) mdb_pwalk("topo_proplist", dump_propval
, NULL
, curr_pg
);
447 * Recursive function to dump the specified node and all of it's children
451 dump_tnode(uintptr_t addr
, const void *data
, void *arg
)
454 char pname
[255], buf
[80], old_pname
[255];
460 if (mdb_vread(&node
, sizeof (node
), addr
) != sizeof (node
)) {
461 mdb_warn("failed to read tnode_t at %p", addr
);
464 if (mdb_readstr(buf
, sizeof (buf
), (uintptr_t)node
.tn_name
) < 0) {
465 (void) mdb_snprintf(buf
, sizeof (buf
), "<%p>",
470 mdb_snprintf(pname
, sizeof (pname
), "%s", parent
);
473 mdb_snprintf(pname
, sizeof (pname
), "%s/%s=%u",
474 parent
, buf
, node
.tn_instance
);
477 mdb_printf("%s\n tnode_t: %p\n", pname
, addr
);
479 mdb_printf("%s\n", pname
);
481 mdb_snprintf(old_pname
, sizeof (old_pname
), "%s", parent
);
482 mdb_snprintf(parent
, sizeof (parent
), "%s", pname
);
485 (void) mdb_pwalk("topo_pgroup", dump_pgroup
, NULL
, addr
);
487 (void) mdb_pwalk("topo_nodehash", dump_tnode
, NULL
, addr
);
488 mdb_snprintf(parent
, sizeof (parent
), "%s", old_pname
);
495 * Given a topo_hdl_t *, the topo dcmd dumps the topo tree. The format of the
496 * output is modeled after fmtopo. Like fmtopo, by default, we'll dump the
497 * "hc" scheme tree. The user can optionally specify a different tree via the
498 * "-s <scheme>" option.
500 * Specifying the "-v" option provides more verbose output. Currently it
501 * outputs the tnode_t * addr for each node, which is useful if you want to
502 * dump it with the topo_node dcmd.
504 * The functionality of the "-P" option is similar to fmtopo.
508 fmtopo(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
510 char product
[36], *opt_s
= NULL
, *opt_P
= NULL
;
513 uint_t opt_v
= FALSE
;
514 char *def_scheme
= "hc";
516 if (mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
, &opt_v
,
517 's', MDB_OPT_STR
, &opt_s
, 'P', MDB_OPT_STR
, &opt_P
, NULL
)
525 tgt_scheme
= def_scheme
;
533 * Read in the topo_handle and some of its string fields from
534 * the target's addr space
536 if (mdb_vread(&th
, sizeof (th
), addr
) != sizeof (th
)) {
537 mdb_warn("failed to read topo_hdl_t at %p", addr
);
541 if (mdb_readstr(product
, sizeof (product
), (uintptr_t)th
.th_product
)
544 (void) mdb_snprintf(product
, sizeof (product
), "<%p>",
548 mdb_snprintf(parent
, sizeof (parent
),
549 "%s://:product-id=%s", tgt_scheme
, product
);
552 * Walk the list of topo trees, looking for the one that is for the
553 * scheme we're interested in.
556 mdb_pwalk("topo_tree", find_tree_root
, &tree_root
, addr
);
559 mdb_warn("failed to find a topo tree for scheme %s\n",
564 return (dump_tnode((uintptr_t)tree_root
, NULL
, NULL
));
569 ttree_walk_init(mdb_walk_state_t
*wsp
)
573 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
574 mdb_warn("NULL topo_hdl_t passed in");
578 if (mdb_vread(&th
, sizeof (th
), wsp
->walk_addr
) != sizeof (th
)) {
579 mdb_warn("failed to read topo_hdl_t at %p", wsp
->walk_addr
);
583 wsp
->walk_addr
= (uintptr_t)th
.th_trees
.l_next
;
584 wsp
->walk_data
= mdb_alloc(sizeof (ttree_t
), UM_SLEEP
);
591 ttree_walk_step(mdb_walk_state_t
*wsp
)
596 if (wsp
->walk_addr
== (uintptr_t)NULL
)
599 if (mdb_vread(wsp
->walk_data
, sizeof (ttree_t
), wsp
->walk_addr
)
600 != sizeof (ttree_t
)) {
602 mdb_warn("failed to read ttree_t at %p", wsp
->walk_addr
);
606 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
609 tree
= (ttree_t
*)wsp
->walk_data
;
610 wsp
->walk_addr
= (uintptr_t)tree
->tt_list
.l_next
;
617 ttree_walk_fini(mdb_walk_state_t
*wsp
)
619 mdb_free(wsp
->walk_data
, sizeof (ttree_t
));
624 tmod_walk_init(mdb_walk_state_t
*wsp
)
628 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
629 mdb_warn("NULL topo_hdl_t passed in");
633 if (mdb_vread(&th
, sizeof (th
), wsp
->walk_addr
) != sizeof (th
)) {
634 mdb_warn("failed to read topo_hdl_t at %p", wsp
->walk_addr
);
638 if (mdb_vread(&tmh
, sizeof (topo_modhash_t
), (uintptr_t)th
.th_modhash
)
641 mdb_warn("failed to read topo_modhash_t at %p", wsp
->walk_addr
);
647 if (mdb_vread(&(wsp
->walk_addr
), sizeof (uintptr_t *),
648 (uintptr_t)(tmh
.mh_hash
)) != sizeof (tnode_t
*)) {
650 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t
*),
655 wsp
->walk_data
= mdb_alloc(sizeof (topo_mod_t
), UM_SLEEP
);
662 tmod_walk_step(mdb_walk_state_t
*wsp
)
667 if (wsp
->walk_addr
== (uintptr_t)NULL
)
670 if (mdb_vread(wsp
->walk_data
, sizeof (topo_mod_t
), wsp
->walk_addr
)
673 mdb_warn("failed to read topo_mod_t at %p", wsp
->walk_addr
);
677 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
680 tm
= (topo_mod_t
*)wsp
->walk_data
;
683 wsp
->walk_addr
= (uintptr_t)tm
->tm_next
;
684 else if (++hash_idx
< tmh
.mh_hashlen
)
685 if (mdb_vread(&(wsp
->walk_addr
), sizeof (uintptr_t *),
686 (uintptr_t)(tmh
.mh_hash
+hash_idx
)) != sizeof (tnode_t
*)) {
688 mdb_warn("failed to read %u bytes at %p",
689 sizeof (tnode_t
*), tmh
.mh_hash
+hash_idx
);
693 wsp
->walk_addr
= (uintptr_t)NULL
;
699 tmod_walk_fini(mdb_walk_state_t
*wsp
)
701 mdb_free(wsp
->walk_data
, sizeof (topo_mod_t
));
706 tpg_walk_init(mdb_walk_state_t
*wsp
)
710 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
711 mdb_warn("NULL tnode_t passed in");
715 if (mdb_vread(&node
, sizeof (node
), wsp
->walk_addr
) != sizeof (node
)) {
716 mdb_warn("failed to read tnode_t at %p", wsp
->walk_addr
);
720 wsp
->walk_addr
= (uintptr_t)node
.tn_pgroups
.l_next
;
721 wsp
->walk_data
= mdb_alloc(sizeof (topo_pgroup_t
), UM_SLEEP
);
728 tpg_walk_step(mdb_walk_state_t
*wsp
)
733 if (wsp
->walk_addr
== (uintptr_t)NULL
)
736 if (mdb_vread(wsp
->walk_data
, sizeof (topo_pgroup_t
), wsp
->walk_addr
)
739 mdb_warn("failed to read topo_pgroup_t at %p", wsp
->walk_addr
);
743 curr_pg
= wsp
->walk_addr
;
744 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
747 tpgp
= (topo_pgroup_t
*)wsp
->walk_data
;
748 wsp
->walk_addr
= (uintptr_t)tpgp
->tpg_list
.l_next
;
755 tpg_walk_fini(mdb_walk_state_t
*wsp
)
757 mdb_free(wsp
->walk_data
, sizeof (topo_pgroup_t
));
762 tpl_walk_init(mdb_walk_state_t
*wsp
)
766 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
767 mdb_warn("NULL topo_pgroup_t passed in");
771 if (mdb_vread(&pg
, sizeof (pg
), wsp
->walk_addr
) != sizeof (pg
)) {
772 mdb_warn("failed to read topo_pgroup_t at %p", wsp
->walk_addr
);
776 wsp
->walk_addr
= (uintptr_t)pg
.tpg_pvals
.l_next
;
777 wsp
->walk_data
= mdb_alloc(sizeof (topo_proplist_t
), UM_SLEEP
);
784 tpl_walk_step(mdb_walk_state_t
*wsp
)
787 topo_proplist_t
*plp
;
789 if (wsp
->walk_addr
== (uintptr_t)NULL
)
792 if (mdb_vread(wsp
->walk_data
, sizeof (topo_proplist_t
), wsp
->walk_addr
)
795 mdb_warn("failed to read topo_proplist_t at %p",
799 plp
= (topo_proplist_t
*)wsp
->walk_data
;
801 rv
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
804 wsp
->walk_addr
= (uintptr_t)plp
->tp_list
.l_next
;
811 tpl_walk_fini(mdb_walk_state_t
*wsp
)
813 mdb_free(wsp
->walk_data
, sizeof (topo_proplist_t
));
818 tnh_walk_init(mdb_walk_state_t
*wsp
)
821 tnwalk_state_t
*state
;
823 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
824 mdb_warn("NULL tnode_t passed in");
828 if (mdb_vread(&node
, sizeof (node
), wsp
->walk_addr
) != sizeof (node
)) {
829 mdb_warn("failed to read tnode_t at %p", wsp
->walk_addr
);
833 state
= mdb_zalloc(sizeof (tnwalk_state_t
), UM_SLEEP
);
835 state
->curr_hash
= (topo_nodehash_t
*)node
.tn_children
.l_next
;
837 wsp
->walk_data
= state
;
844 tnh_walk_step(mdb_walk_state_t
*wsp
)
846 tnwalk_state_t
*state
= wsp
->walk_data
;
847 int rv
, i
= state
->hash_idx
++;
850 if (state
->curr_hash
== NULL
)
853 if (mdb_vread(&(state
->hash
), sizeof (topo_nodehash_t
),
854 (uintptr_t)state
->curr_hash
) != sizeof (topo_nodehash_t
)) {
856 mdb_warn("failed to read topo_nodehash_t at %p",
857 (uintptr_t)state
->curr_hash
);
861 if (mdb_vread(&npp
, sizeof (tnode_t
*),
862 (uintptr_t)(state
->hash
.th_nodearr
+i
)) != sizeof (tnode_t
*)) {
864 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t
*),
865 state
->hash
.th_nodearr
+i
);
868 wsp
->walk_addr
= (uintptr_t)npp
;
870 rv
= wsp
->walk_callback(wsp
->walk_addr
, state
, wsp
->walk_cbdata
);
872 if (state
->hash_idx
>= state
->hash
.th_arrlen
) {
874 * move on to the next child hash bucket
877 (topo_nodehash_t
*)(state
->hash
.th_list
.l_next
);
886 tnh_walk_fini(mdb_walk_state_t
*wsp
)
888 mdb_free(wsp
->walk_data
, sizeof (tnwalk_state_t
));
892 static const mdb_dcmd_t dcmds
[] = {
893 { "topo_handle", "", "print contents of a topo handle", topo_handle
,
895 { "topo_module", "", "print contents of a topo module handle",
897 { "topo_node", "", "print contents of a topo node", topo_node
, NULL
},
898 { "fmtopo", "[-P <pgroup>][-s <scheme>][-v]",
899 "print topology of the given handle", fmtopo
, NULL
},
903 static const mdb_walker_t walkers
[] = {
904 { "topo_tree", "walk the tree list for a given topo handle",
905 ttree_walk_init
, ttree_walk_step
, ttree_walk_fini
, NULL
},
906 { "topo_module", "walk the module hash for a given topo handle",
907 tmod_walk_init
, tmod_walk_step
, tmod_walk_fini
, NULL
},
908 { "topo_pgroup", "walk the property groups for a given topo node",
909 tpg_walk_init
, tpg_walk_step
, tpg_walk_fini
, NULL
},
910 { "topo_proplist", "walk the property list for a given property group",
911 tpl_walk_init
, tpl_walk_step
, tpl_walk_fini
, NULL
},
912 { "topo_nodehash", "walk the child nodehash for a given topo node",
913 tnh_walk_init
, tnh_walk_step
, tnh_walk_fini
, NULL
},
917 static const mdb_modinfo_t modinfo
= {
918 MDB_API_VERSION
, dcmds
, walkers
921 const mdb_modinfo_t
*