dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / libtopo / libtopo.c
blob178a2a4613341f0973ddc6301a3f9ce1c484d7db
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #include <sys/mdb_modapi.h>
27 #include <libelf.h>
28 #include <sys/fm/protocol.h>
29 #include <topo_mod.h>
30 #include <topo_tree.h>
31 #include <topo_module.h>
32 #include <stddef.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;
45 static char *pgrp;
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 {
54 uint_t hash_idx;
55 topo_nodehash_t hash;
56 topo_nodehash_t *curr_hash;
57 } tnwalk_state_t;
60 static char *stab_lvls[] = {"Internal", "", "Private", "Obsolete", "External",
61 "Unstable", "Evolving", "Stable", "Standard", "Max"};
63 /*ARGSUSED*/
64 static int
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];
68 topo_hdl_t th;
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);
76 return (DCMD_ERR);
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>",
87 th.th_platform);
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)
93 < 0) {
95 (void) mdb_snprintf(machine, sizeof (machine), "<%p>",
96 th.th_machine);
98 if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product)
99 < 0) {
101 (void) mdb_snprintf(product, sizeof (product), "<%p>",
102 th.th_product);
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",
110 "DESCR");
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,
122 "Machine name");
123 mdb_printf("%-12s %-36s %-30s\n", "th_product", product,
124 "Product name");
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,
130 "Module hash");
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,
134 "");
135 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_next", th.th_trees.l_next,
136 "");
137 mdb_printf("%-12s 0x%-34p %-30s\n", "th_alloc", th.th_alloc,
138 "Allocators");
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,
141 "Debug mask");
142 mdb_printf("%-12s %-36d %-30s\n", "tm_dbout", th.th_dbout,
143 "Debug channel");
145 return (DCMD_OK);
149 /*ARGSUSED*/
150 static int
151 topo_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
153 char name[36], path[36], root[36];
154 topo_mod_t tm;
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);
162 return (DCMD_ERR);
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");
188 if (tm.tm_busy)
189 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "TRUE",
190 "Busy indicator");
191 else
192 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "FALSE",
193 "Busy indicator");
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,
200 "Allocators");
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,
210 "Module 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,
237 "Module errno");
239 return (DCMD_OK);
243 /*ARGSUSED*/
244 static int
245 topo_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
247 char name[36];
248 tnode_t tn;
250 if (!addr)
251 return (DCMD_ERR);
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);
259 return (DCMD_ERR);
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,
278 "Node name");
279 mdb_printf("%-12s %-36d %-30s\n", "tn_instance", tn.tn_instance,
280 "Node instance");
281 mdb_printf("%-12s %-36d %-30s\n", "tn_state", tn.tn_state,
282 "Node 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,
296 "FMRI flags");
297 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_parent", tn.tn_parent,
298 "Node 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,
302 "Topo handle");
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");
318 return (DCMD_OK);
321 /*ARGSUSED*/
322 static int
323 find_tree_root(uintptr_t addr, const void *data, void *arg)
325 ttree_t *tree = (ttree_t *)data;
326 char scheme[36];
328 if (mdb_readstr(scheme, sizeof (scheme), (uintptr_t)tree->tt_scheme)
329 < 0) {
330 (void) mdb_snprintf(scheme, sizeof (scheme), "<%p>",
331 tree->tt_scheme);
334 if (strncmp(tgt_scheme, scheme, 36) == 0) {
335 *((tnode_t **)arg) = tree->tt_root;
336 return (WALK_DONE);
338 return (WALK_NEXT);
341 static void
342 dump_propmethod(uintptr_t addr)
344 topo_propmethod_t pm;
345 char mname[32];
347 if (mdb_vread(&pm, sizeof (pm), addr) != sizeof (pm)) {
348 mdb_warn("failed to read topo_propmethod at %p", addr);
349 return;
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
364 /*ARGSUSED*/
365 static int
366 dump_propval(uintptr_t addr, const void *data, void *arg)
368 topo_proplist_t *plistp = (topo_proplist_t *)data;
369 topo_propval_t pval;
370 char name[32], *type;
372 if (mdb_vread(&pval, sizeof (pval), (uintptr_t)plistp->tp_pval)
373 != sizeof (pval)) {
375 mdb_warn("failed to read topo_propval_t at %p",
376 plistp->tp_pval);
377 return (WALK_ERR);
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);
403 return (WALK_NEXT);
408 * Dumps the contents of the property group.
410 /*ARGSUSED*/
411 static int
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;
416 char buf[32];
418 if (mdb_vread(&ipg, sizeof (ipg), (uintptr_t)pgp->tpg_info)
419 != sizeof (ipg)) {
421 mdb_warn("failed to read topo_ipgroup_info_t at %p",
422 pgp->tpg_info);
423 return (WALK_ERR);
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);
427 return (WALK_ERR);
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);
442 return (WALK_NEXT);
447 * Recursive function to dump the specified node and all of it's children
449 /*ARGSUSED*/
450 static int
451 dump_tnode(uintptr_t addr, const void *data, void *arg)
453 tnode_t node;
454 char pname[255], buf[80], old_pname[255];
456 if (!addr) {
457 return (WALK_NEXT);
460 if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) {
461 mdb_warn("failed to read tnode_t at %p", addr);
462 return (WALK_ERR);
464 if (mdb_readstr(buf, sizeof (buf), (uintptr_t)node.tn_name) < 0) {
465 (void) mdb_snprintf(buf, sizeof (buf), "<%p>",
466 node.tn_name);
469 if (is_root) {
470 mdb_snprintf(pname, sizeof (pname), "%s", parent);
471 is_root = 0;
472 } else {
473 mdb_snprintf(pname, sizeof (pname), "%s/%s=%u",
474 parent, buf, node.tn_instance);
476 if (verbose)
477 mdb_printf("%s\n tnode_t: %p\n", pname, addr);
478 else
479 mdb_printf("%s\n", pname);
481 mdb_snprintf(old_pname, sizeof (old_pname), "%s", parent);
482 mdb_snprintf(parent, sizeof (parent), "%s", pname);
484 if (pgrp)
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);
490 return (WALK_NEXT);
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.
506 /*ARGSUSED*/
507 static int
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;
511 topo_hdl_t th;
512 tnode_t *tree_root;
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)
518 != argc) {
519 return (DCMD_USAGE);
522 if (opt_s) {
523 tgt_scheme = opt_s;
524 } else {
525 tgt_scheme = def_scheme;
528 pgrp = opt_P;
529 verbose = opt_v;
530 is_root = 1;
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);
538 return (DCMD_ERR);
541 if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product)
542 < 0) {
544 (void) mdb_snprintf(product, sizeof (product), "<%p>",
545 th.th_product);
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.
555 tree_root = NULL;
556 mdb_pwalk("topo_tree", find_tree_root, &tree_root, addr);
558 if (! tree_root) {
559 mdb_warn("failed to find a topo tree for scheme %s\n",
560 tgt_scheme);
561 return (DCMD_ERR);
564 return (dump_tnode((uintptr_t)tree_root, NULL, NULL));
568 static int
569 ttree_walk_init(mdb_walk_state_t *wsp)
571 topo_hdl_t th;
573 if (wsp->walk_addr == (uintptr_t)NULL) {
574 mdb_warn("NULL topo_hdl_t passed in");
575 return (WALK_ERR);
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);
580 return (WALK_ERR);
583 wsp->walk_addr = (uintptr_t)th.th_trees.l_next;
584 wsp->walk_data = mdb_alloc(sizeof (ttree_t), UM_SLEEP);
586 return (WALK_NEXT);
590 static int
591 ttree_walk_step(mdb_walk_state_t *wsp)
593 int rv;
594 ttree_t *tree;
596 if (wsp->walk_addr == (uintptr_t)NULL)
597 return (WALK_DONE);
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);
603 return (WALK_ERR);
606 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
607 wsp->walk_cbdata);
609 tree = (ttree_t *)wsp->walk_data;
610 wsp->walk_addr = (uintptr_t)tree->tt_list.l_next;
612 return (rv);
616 static void
617 ttree_walk_fini(mdb_walk_state_t *wsp)
619 mdb_free(wsp->walk_data, sizeof (ttree_t));
623 static int
624 tmod_walk_init(mdb_walk_state_t *wsp)
626 topo_hdl_t th;
628 if (wsp->walk_addr == (uintptr_t)NULL) {
629 mdb_warn("NULL topo_hdl_t passed in");
630 return (WALK_ERR);
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);
635 return (WALK_ERR);
638 if (mdb_vread(&tmh, sizeof (topo_modhash_t), (uintptr_t)th.th_modhash)
639 == -1) {
641 mdb_warn("failed to read topo_modhash_t at %p", wsp->walk_addr);
642 return (WALK_DONE);
645 hash_idx = 0;
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 *),
651 tmh.mh_hash);
652 return (WALK_ERR);
655 wsp->walk_data = mdb_alloc(sizeof (topo_mod_t), UM_SLEEP);
657 return (WALK_NEXT);
661 static int
662 tmod_walk_step(mdb_walk_state_t *wsp)
664 int rv;
665 topo_mod_t *tm;
667 if (wsp->walk_addr == (uintptr_t)NULL)
668 return (WALK_DONE);
670 if (mdb_vread(wsp->walk_data, sizeof (topo_mod_t), wsp->walk_addr)
671 == -1) {
673 mdb_warn("failed to read topo_mod_t at %p", wsp->walk_addr);
674 return (WALK_DONE);
677 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
678 wsp->walk_cbdata);
680 tm = (topo_mod_t *)wsp->walk_data;
682 if (tm->tm_next)
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);
690 return (DCMD_ERR);
692 else
693 wsp->walk_addr = (uintptr_t)NULL;
695 return (rv);
698 static void
699 tmod_walk_fini(mdb_walk_state_t *wsp)
701 mdb_free(wsp->walk_data, sizeof (topo_mod_t));
705 static int
706 tpg_walk_init(mdb_walk_state_t *wsp)
708 tnode_t node;
710 if (wsp->walk_addr == (uintptr_t)NULL) {
711 mdb_warn("NULL tnode_t passed in");
712 return (WALK_ERR);
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);
717 return (WALK_ERR);
720 wsp->walk_addr = (uintptr_t)node.tn_pgroups.l_next;
721 wsp->walk_data = mdb_alloc(sizeof (topo_pgroup_t), UM_SLEEP);
723 return (WALK_NEXT);
727 static int
728 tpg_walk_step(mdb_walk_state_t *wsp)
730 int rv;
731 topo_pgroup_t *tpgp;
733 if (wsp->walk_addr == (uintptr_t)NULL)
734 return (WALK_DONE);
736 if (mdb_vread(wsp->walk_data, sizeof (topo_pgroup_t), wsp->walk_addr)
737 == -1) {
739 mdb_warn("failed to read topo_pgroup_t at %p", wsp->walk_addr);
740 return (WALK_DONE);
743 curr_pg = wsp->walk_addr;
744 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
745 wsp->walk_cbdata);
747 tpgp = (topo_pgroup_t *)wsp->walk_data;
748 wsp->walk_addr = (uintptr_t)tpgp->tpg_list.l_next;
750 return (rv);
754 static void
755 tpg_walk_fini(mdb_walk_state_t *wsp)
757 mdb_free(wsp->walk_data, sizeof (topo_pgroup_t));
761 static int
762 tpl_walk_init(mdb_walk_state_t *wsp)
764 topo_pgroup_t pg;
766 if (wsp->walk_addr == (uintptr_t)NULL) {
767 mdb_warn("NULL topo_pgroup_t passed in");
768 return (WALK_ERR);
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);
773 return (WALK_ERR);
776 wsp->walk_addr = (uintptr_t)pg.tpg_pvals.l_next;
777 wsp->walk_data = mdb_alloc(sizeof (topo_proplist_t), UM_SLEEP);
779 return (WALK_NEXT);
783 static int
784 tpl_walk_step(mdb_walk_state_t *wsp)
786 int rv;
787 topo_proplist_t *plp;
789 if (wsp->walk_addr == (uintptr_t)NULL)
790 return (WALK_DONE);
792 if (mdb_vread(wsp->walk_data, sizeof (topo_proplist_t), wsp->walk_addr)
793 == -1) {
795 mdb_warn("failed to read topo_proplist_t at %p",
796 wsp->walk_addr);
797 return (WALK_DONE);
799 plp = (topo_proplist_t *)wsp->walk_data;
801 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
802 wsp->walk_cbdata);
804 wsp->walk_addr = (uintptr_t)plp->tp_list.l_next;
806 return (rv);
810 static void
811 tpl_walk_fini(mdb_walk_state_t *wsp)
813 mdb_free(wsp->walk_data, sizeof (topo_proplist_t));
817 static int
818 tnh_walk_init(mdb_walk_state_t *wsp)
820 tnode_t node;
821 tnwalk_state_t *state;
823 if (wsp->walk_addr == (uintptr_t)NULL) {
824 mdb_warn("NULL tnode_t passed in");
825 return (WALK_ERR);
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);
830 return (WALK_ERR);
833 state = mdb_zalloc(sizeof (tnwalk_state_t), UM_SLEEP);
835 state->curr_hash = (topo_nodehash_t *)node.tn_children.l_next;
836 state->hash_idx = 0;
837 wsp->walk_data = state;
839 return (WALK_NEXT);
843 static int
844 tnh_walk_step(mdb_walk_state_t *wsp)
846 tnwalk_state_t *state = wsp->walk_data;
847 int rv, i = state->hash_idx++;
848 tnode_t *npp;
850 if (state->curr_hash == NULL)
851 return (WALK_DONE);
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);
858 return (WALK_ERR);
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);
866 return (WALK_ERR);
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
876 state->curr_hash =
877 (topo_nodehash_t *)(state->hash.th_list.l_next);
878 state->hash_idx = 0;
881 return (rv);
885 static void
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,
894 NULL },
895 { "topo_module", "", "print contents of a topo module handle",
896 topo_module, NULL },
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 },
900 { 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 },
914 { NULL }
917 static const mdb_modinfo_t modinfo = {
918 MDB_API_VERSION, dcmds, walkers
921 const mdb_modinfo_t *
922 _mdb_init(void)
924 return (&modinfo);