19dd0f810Scindi /* 29dd0f810Scindi * CDDL HEADER START 39dd0f810Scindi * 49dd0f810Scindi * The contents of this file are subject to the terms of the 59dd0f810Scindi * Common Development and Distribution License (the "License"). 69dd0f810Scindi * You may not use this file except in compliance with the License. 79dd0f810Scindi * 89dd0f810Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99dd0f810Scindi * or http://www.opensolaris.org/os/licensing. 109dd0f810Scindi * See the License for the specific language governing permissions 119dd0f810Scindi * and limitations under the License. 129dd0f810Scindi * 139dd0f810Scindi * When distributing Covered Code, include this CDDL HEADER in each 149dd0f810Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159dd0f810Scindi * If applicable, add the following below this CDDL HEADER, with the 169dd0f810Scindi * fields enclosed by brackets "[]" replaced with your own identifying 179dd0f810Scindi * information: Portions Copyright [yyyy] [name of copyright owner] 189dd0f810Scindi * 199dd0f810Scindi * CDDL HEADER END 209dd0f810Scindi */ 219dd0f810Scindi 229dd0f810Scindi /* 23*2eeaed14Srobj * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 249dd0f810Scindi * Use is subject to license terms. 259dd0f810Scindi */ 269dd0f810Scindi #pragma ident "%Z%%M% %I% %E% SMI" 279dd0f810Scindi 289dd0f810Scindi #include <sys/mdb_modapi.h> 299dd0f810Scindi #include <libelf.h> 309dd0f810Scindi #include <sys/fm/protocol.h> 319dd0f810Scindi #include <topo_mod.h> 329dd0f810Scindi #include <topo_tree.h> 339dd0f810Scindi #include <topo_module.h> 3424db4641Seschrock #include <stddef.h> 359dd0f810Scindi 369dd0f810Scindi 379dd0f810Scindi /* 389dd0f810Scindi * We use this to keep track of which bucket we're in while walking 399dd0f810Scindi * the modhash and we also cache the length of the hash 409dd0f810Scindi */ 419dd0f810Scindi static topo_modhash_t tmh; 429dd0f810Scindi static uint_t hash_idx; 439dd0f810Scindi 449dd0f810Scindi static uintptr_t curr_pg; 459dd0f810Scindi static uint_t is_root; 469dd0f810Scindi static uint_t verbose; 479dd0f810Scindi static char *pgrp; 489dd0f810Scindi static char *tgt_scheme; 499dd0f810Scindi static char parent[255]; 509dd0f810Scindi 519dd0f810Scindi /* 529dd0f810Scindi * This structure is used by the topo_nodehash walker instances to 539dd0f810Scindi * keep track of where they're at in the node hash 549dd0f810Scindi */ 559dd0f810Scindi typedef struct tnwalk_state { 569dd0f810Scindi uint_t hash_idx; 579dd0f810Scindi topo_nodehash_t hash; 589dd0f810Scindi topo_nodehash_t *curr_hash; 599dd0f810Scindi } tnwalk_state_t; 609dd0f810Scindi 619dd0f810Scindi 629dd0f810Scindi static char *stab_lvls[] = {"Internal", "", "Private", "Obsolete", "External", 639dd0f810Scindi "Unstable", "Evolving", "Stable", "Standard", "Max"}; 649dd0f810Scindi 659dd0f810Scindi /*ARGSUSED*/ 669dd0f810Scindi static int 679dd0f810Scindi topo_handle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 689dd0f810Scindi { 699dd0f810Scindi char uuid[36], root[36], plat[36], isa[36], machine[36], product[36]; 709dd0f810Scindi topo_hdl_t th; 719dd0f810Scindi 729dd0f810Scindi /* 739dd0f810Scindi * Read in the structure and then read in all of the string fields from 749dd0f810Scindi * the target's addr space 759dd0f810Scindi */ 769dd0f810Scindi if (mdb_vread(&th, sizeof (th), addr) != sizeof (th)) { 779dd0f810Scindi mdb_warn("failed to read topo_hdl_t at %p", addr); 789dd0f810Scindi return (DCMD_ERR); 799dd0f810Scindi } 809dd0f810Scindi 819dd0f810Scindi if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)th.th_uuid) < 0) { 829dd0f810Scindi (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", th.th_uuid); 839dd0f810Scindi } 849dd0f810Scindi if (mdb_readstr(root, sizeof (root), (uintptr_t)th.th_rootdir) < 0) { 859dd0f810Scindi (void) mdb_snprintf(root, sizeof (root), "<%p>", th.th_rootdir); 869dd0f810Scindi } 879dd0f810Scindi if (mdb_readstr(plat, sizeof (plat), (uintptr_t)th.th_platform) < 0) { 889dd0f810Scindi (void) mdb_snprintf(plat, sizeof (plat), "<%p>", 899dd0f810Scindi th.th_platform); 909dd0f810Scindi } 919dd0f810Scindi if (mdb_readstr(isa, sizeof (isa), (uintptr_t)th.th_isa) < 0) { 929dd0f810Scindi (void) mdb_snprintf(isa, sizeof (isa), "<%p>", th.th_isa); 939dd0f810Scindi } 949dd0f810Scindi if (mdb_readstr(machine, sizeof (machine), (uintptr_t)th.th_machine) 959dd0f810Scindi < 0) { 969dd0f810Scindi 979dd0f810Scindi (void) mdb_snprintf(machine, sizeof (machine), "<%p>", 989dd0f810Scindi th.th_machine); 999dd0f810Scindi } 1009dd0f810Scindi if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product) 1019dd0f810Scindi < 0) { 1029dd0f810Scindi 1039dd0f810Scindi (void) mdb_snprintf(product, sizeof (product), "<%p>", 1049dd0f810Scindi th.th_product); 1059dd0f810Scindi } 1069dd0f810Scindi 1079dd0f810Scindi /* 1089dd0f810Scindi * Dump it all out in a nice pretty format and keep it to 80 chars wide 1099dd0f810Scindi */ 1109dd0f810Scindi if (DCMD_HDRSPEC(flags)) { 1119dd0f810Scindi mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", "FIELD", "VALUE", 1129dd0f810Scindi "DESCR"); 1139dd0f810Scindi } 1144557a2a1Srobj mdb_printf("%-12s 0x%-34p %-30s\n", "th_lock", 1154557a2a1Srobj addr + offsetof(topo_hdl_t, th_lock), 1169dd0f810Scindi "Mutex lock protecting handle"); 1179dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_uuid", uuid, 1189dd0f810Scindi "UUID of the topology snapshot"); 1199dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_rootdir", root, 1209dd0f810Scindi "Root directory of plugin paths"); 1219dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_platform", plat, "Platform name"); 1229dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_isa", isa, "ISA name"); 1239dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_machine", machine, 1249dd0f810Scindi "Machine name"); 1259dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_product", product, 1269dd0f810Scindi "Product name"); 1279dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "th_di", th.th_di, 1289dd0f810Scindi "Handle to the root of the devinfo tree"); 1299dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "th_pi", th.th_pi, 1309dd0f810Scindi "Handle to the root of the PROM tree"); 1319dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "th_modhash", th.th_modhash, 1329dd0f810Scindi "Module hash"); 1339dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "th_trees", "", 1349dd0f810Scindi "Scheme-specific topo tree list"); 1359dd0f810Scindi mdb_printf(" %-12s 0x%-34p %-30s\n", "l_prev", th.th_trees.l_prev, 1369dd0f810Scindi ""); 1379dd0f810Scindi mdb_printf(" %-12s 0x%-34p %-30s\n", "l_next", th.th_trees.l_next, 1389dd0f810Scindi ""); 1399dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "th_alloc", th.th_alloc, 1409dd0f810Scindi "Allocators"); 1419dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", th.th_errno, "errno"); 1429dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tm_debug", th.th_debug, 1439dd0f810Scindi "Debug mask"); 1449dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tm_dbout", th.th_dbout, 1459dd0f810Scindi "Debug channel"); 1469dd0f810Scindi 1479dd0f810Scindi return (DCMD_OK); 1489dd0f810Scindi } 1499dd0f810Scindi 1509dd0f810Scindi 1519dd0f810Scindi /*ARGSUSED*/ 1529dd0f810Scindi static int 1539dd0f810Scindi topo_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1549dd0f810Scindi { 1559dd0f810Scindi char name[36], path[36], root[36]; 1569dd0f810Scindi topo_mod_t tm; 1579dd0f810Scindi 1589dd0f810Scindi /* 1599dd0f810Scindi * Read in the structure and then read in all of the string fields from 1609dd0f810Scindi * the target's addr space 1619dd0f810Scindi */ 1629dd0f810Scindi if (mdb_vread(&tm, sizeof (tm), addr) != sizeof (tm)) { 1639dd0f810Scindi mdb_warn("failed to read topo_mod_t at %p", addr); 1649dd0f810Scindi return (DCMD_ERR); 1659dd0f810Scindi } 1669dd0f810Scindi 1679dd0f810Scindi if (mdb_readstr(name, sizeof (name), (uintptr_t)tm.tm_name) < 0) { 1689dd0f810Scindi (void) mdb_snprintf(name, sizeof (name), "<%p>", tm.tm_name); 1699dd0f810Scindi } 1709dd0f810Scindi if (mdb_readstr(path, sizeof (path), (uintptr_t)tm.tm_path) < 0) { 1719dd0f810Scindi (void) mdb_snprintf(path, sizeof (path), "<%p>", tm.tm_path); 1729dd0f810Scindi } 1739dd0f810Scindi if (mdb_readstr(root, sizeof (root), (uintptr_t)tm.tm_rootdir) < 0) { 1749dd0f810Scindi (void) mdb_snprintf(root, sizeof (root), "<%p>", tm.tm_rootdir); 1759dd0f810Scindi } 1769dd0f810Scindi 1779dd0f810Scindi /* 1789dd0f810Scindi * Dump it all out in a nice pretty format and keep it to 80 chars wide 1799dd0f810Scindi */ 1809dd0f810Scindi if (DCMD_HDRSPEC(flags)) { 1819dd0f810Scindi mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", 1829dd0f810Scindi "FIELD", "VALUE", "DESCR"); 1839dd0f810Scindi } 1844557a2a1Srobj mdb_printf("%-12s 0x%-34p %-30s\n", "tm_lock", 1854557a2a1Srobj addr + offsetof(topo_mod_t, tm_lock), 1869dd0f810Scindi "Lock for tm_cv/owner/flags/refs"); 1874557a2a1Srobj mdb_printf("%-12s 0x%-34p %-30s\n", "tm_cv", 1884557a2a1Srobj addr + offsetof(topo_mod_t, tm_cv), 1899dd0f810Scindi "Module condition variable"); 190*2eeaed14Srobj if (tm.tm_busy) 191*2eeaed14Srobj mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "TRUE", 1929dd0f810Scindi "Busy indicator"); 193*2eeaed14Srobj else 194*2eeaed14Srobj mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "FALSE", 195*2eeaed14Srobj "Busy indicator"); 196*2eeaed14Srobj 1979dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_next", tm.tm_next, 1989dd0f810Scindi "Next module in hash chain"); 1999dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_hdl", tm.tm_hdl, 2009dd0f810Scindi "Topo handle for this module"); 2019dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_alloc", tm.tm_alloc, 2029dd0f810Scindi "Allocators"); 2039dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "tm_name", name, 2049dd0f810Scindi "Basename of module"); 2059dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "tm_path", path, 2069dd0f810Scindi "Full pathname of module"); 2079dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "tm_rootdir", root, 2089dd0f810Scindi "Relative root directory of module"); 2099dd0f810Scindi mdb_printf("%-12s %-36u %-30s\n", "tm_refs", tm.tm_refs, 2109dd0f810Scindi "Module reference count"); 2119dd0f810Scindi mdb_printf("%-12s %-36u %-30s\n", "tm_flags", tm.tm_flags, 2129dd0f810Scindi "Module flags"); 2139dd0f810Scindi if (TOPO_MOD_INIT & tm.tm_flags) { 2149dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_INIT", 2159dd0f810Scindi "Module init completed"); 2169dd0f810Scindi } 2179dd0f810Scindi if (TOPO_MOD_FINI & tm.tm_flags) { 2189dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_FINI", 2199dd0f810Scindi "Module fini completed"); 2209dd0f810Scindi } 2219dd0f810Scindi if (TOPO_MOD_REG & tm.tm_flags) { 2229dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_REG", 2239dd0f810Scindi "Module registered"); 2249dd0f810Scindi } 2259dd0f810Scindi if (TOPO_MOD_UNREG & tm.tm_flags) { 2269dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_UNREG", 2279dd0f810Scindi "Module unregistered"); 2289dd0f810Scindi } 2299dd0f810Scindi 2309dd0f810Scindi mdb_printf("%-12s %-36u %-30s\n", "tm_debug", tm.tm_debug, 2319dd0f810Scindi "Debug printf mask"); 2329dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_data", tm.tm_data, 2339dd0f810Scindi "Private rtld/builtin data"); 2349dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_mops", tm.tm_mops, 2359dd0f810Scindi "Module class ops vector"); 2369dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tm_info", tm.tm_info, 2379dd0f810Scindi "Module info registered with handle"); 2389dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", tm.tm_errno, 2399dd0f810Scindi "Module errno"); 2409dd0f810Scindi 2419dd0f810Scindi return (DCMD_OK); 2429dd0f810Scindi } 2439dd0f810Scindi 2449dd0f810Scindi 2459dd0f810Scindi /*ARGSUSED*/ 2469dd0f810Scindi static int 2479dd0f810Scindi topo_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2489dd0f810Scindi { 2499dd0f810Scindi char name[36]; 2509dd0f810Scindi tnode_t tn; 2519dd0f810Scindi 2529dd0f810Scindi if (!addr) 2539dd0f810Scindi return (DCMD_ERR); 2549dd0f810Scindi 2559dd0f810Scindi /* 2569dd0f810Scindi * Read in the structure and then read in all of the string fields from 2579dd0f810Scindi * the target's addr space 2589dd0f810Scindi */ 2599dd0f810Scindi if (mdb_vread(&tn, sizeof (tn), addr) != sizeof (tn)) { 2609dd0f810Scindi mdb_warn("failed to read tnode_t at %p", addr); 2619dd0f810Scindi return (DCMD_ERR); 2629dd0f810Scindi } 2639dd0f810Scindi 2649dd0f810Scindi if (mdb_readstr(name, sizeof (name), (uintptr_t)tn.tn_name) < 0) { 2659dd0f810Scindi (void) mdb_snprintf(name, sizeof (name), "<%p>", tn.tn_name); 2669dd0f810Scindi } 2679dd0f810Scindi 2689dd0f810Scindi /* 2699dd0f810Scindi * Dump it all out in a nice pretty format and keep it to 80 chars wide 2709dd0f810Scindi */ 2719dd0f810Scindi if (DCMD_HDRSPEC(flags)) { 2729dd0f810Scindi mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", 2739dd0f810Scindi "FIELD", "VALUE", "DESCR"); 2749dd0f810Scindi } 2759dd0f810Scindi 27624db4641Seschrock mdb_printf("%-12s 0x%-34p %-30s\n", "tn_lock", 27724db4641Seschrock addr + offsetof(tnode_t, tn_lock), 27824db4641Seschrock "Lock protecting node members"); 2799dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "tn_name", name, 2809dd0f810Scindi "Node name"); 2819dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tn_instance", tn.tn_instance, 2829dd0f810Scindi "Node instance"); 2839dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tn_state", tn.tn_state, 2849dd0f810Scindi "Node state"); 2859dd0f810Scindi if (TOPO_NODE_INIT & tn.tn_state) { 2869dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_INIT", ""); 2879dd0f810Scindi } 2889dd0f810Scindi if (TOPO_NODE_ROOT & tn.tn_state) { 2899dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_ROOT", ""); 2909dd0f810Scindi } 2919dd0f810Scindi if (TOPO_NODE_BOUND & tn.tn_state) { 2929dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_BOUND", ""); 2939dd0f810Scindi } 2949dd0f810Scindi if (TOPO_NODE_LINKED & tn.tn_state) { 2959dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_LINKED", ""); 2969dd0f810Scindi } 2979dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tn_fflags", tn.tn_fflags, 2989dd0f810Scindi "FMRI flags"); 2999dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_parent", tn.tn_parent, 3009dd0f810Scindi "Node parent"); 3019dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_phash", tn.tn_phash, 3029dd0f810Scindi "Parent hash bucket"); 3039dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_hdl", tn.tn_hdl, 3049dd0f810Scindi "Topo handle"); 3059dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_enum", tn.tn_enum, 3069dd0f810Scindi "Enumerator module"); 3079dd0f810Scindi mdb_printf("%-12s %-36s %-30s\n", "tn_children", "", 3089dd0f810Scindi "Hash table of child nodes"); 30924db4641Seschrock mdb_printf(" %-12s 0x%-34p\n", "l_prev", tn.tn_children.l_prev); 31024db4641Seschrock mdb_printf(" %-12s 0x%-34p\n", "l_next", tn.tn_children.l_next); 3119dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_pgroups", &(tn.tn_pgroups), 3129dd0f810Scindi "Property group list"); 3139dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_methods", &(tn.tn_methods), 3149dd0f810Scindi "Registered method list"); 3159dd0f810Scindi mdb_printf("%-12s 0x%-34p %-30s\n", "tn_priv", tn.tn_priv, 3169dd0f810Scindi "Private enumerator data"); 3179dd0f810Scindi mdb_printf("%-12s %-36d %-30s\n", "tn_refs", tn.tn_refs, 3189dd0f810Scindi "Node reference count"); 3199dd0f810Scindi 3209dd0f810Scindi return (DCMD_OK); 3219dd0f810Scindi } 3229dd0f810Scindi 3239dd0f810Scindi /*ARGSUSED*/ 3249dd0f810Scindi static int 3259dd0f810Scindi find_tree_root(uintptr_t addr, const void *data, void *arg) 3269dd0f810Scindi { 3279dd0f810Scindi ttree_t *tree = (ttree_t *)data; 3289dd0f810Scindi char scheme[36]; 3299dd0f810Scindi 3309dd0f810Scindi if (mdb_readstr(scheme, sizeof (scheme), (uintptr_t)tree->tt_scheme) 3319dd0f810Scindi < 0) { 3329dd0f810Scindi (void) mdb_snprintf(scheme, sizeof (scheme), "<%p>", 3339dd0f810Scindi tree->tt_scheme); 3349dd0f810Scindi } 3359dd0f810Scindi 3369dd0f810Scindi if (strncmp(tgt_scheme, scheme, 36) == 0) { 3379dd0f810Scindi *((tnode_t **)arg) = tree->tt_root; 3389dd0f810Scindi return (WALK_DONE); 3399dd0f810Scindi } 3409dd0f810Scindi return (WALK_NEXT); 3419dd0f810Scindi } 3429dd0f810Scindi 343c40d7343Scindi static void 344c40d7343Scindi dump_propmethod(uintptr_t addr) 345c40d7343Scindi { 346c40d7343Scindi topo_propmethod_t pm; 347*2eeaed14Srobj char mname[32]; 348c40d7343Scindi 349c40d7343Scindi if (mdb_vread(&pm, sizeof (pm), addr) != sizeof (pm)) { 350c40d7343Scindi mdb_warn("failed to read topo_propmethod at %p", addr); 351c40d7343Scindi return; 352c40d7343Scindi } 353*2eeaed14Srobj if (mdb_readstr(mname, sizeof (mname), (uintptr_t)pm.tpm_name) < 0) { 354*2eeaed14Srobj (void) mdb_snprintf(mname, sizeof (mname), "<%p>", pm.tpm_name); 355*2eeaed14Srobj } 356c40d7343Scindi 357*2eeaed14Srobj mdb_printf(" method: %-32s version: %-16d args: %p\n", 358*2eeaed14Srobj mname, pm.tpm_version, pm.tpm_args); 359c40d7343Scindi } 3609dd0f810Scindi 3619dd0f810Scindi /* 3629dd0f810Scindi * Dump the given property value. For the actual property values 3639dd0f810Scindi * we dump a pointer to the nvlist which can be decoded using the ::nvlist 3649dd0f810Scindi * dcmd from the libnvpair MDB module 3659dd0f810Scindi */ 3669dd0f810Scindi /*ARGSUSED*/ 3679dd0f810Scindi static int 3689dd0f810Scindi dump_propval(uintptr_t addr, const void *data, void *arg) 3699dd0f810Scindi { 3709dd0f810Scindi topo_proplist_t *plistp = (topo_proplist_t *)data; 3719dd0f810Scindi topo_propval_t pval; 3729dd0f810Scindi char name[32], *type; 3739dd0f810Scindi 3749dd0f810Scindi if (mdb_vread(&pval, sizeof (pval), (uintptr_t)plistp->tp_pval) 3759dd0f810Scindi != sizeof (pval)) { 3769dd0f810Scindi 3779dd0f810Scindi mdb_warn("failed to read topo_propval_t at %p", 3789dd0f810Scindi plistp->tp_pval); 3799dd0f810Scindi return (WALK_ERR); 3809dd0f810Scindi } 3819dd0f810Scindi if (mdb_readstr(name, sizeof (name), (uintptr_t)pval.tp_name) < 0) { 3829dd0f810Scindi (void) mdb_snprintf(name, sizeof (name), "<%p>", pval.tp_name); 3839dd0f810Scindi } 3849dd0f810Scindi switch (pval.tp_type) { 3859dd0f810Scindi case TOPO_TYPE_BOOLEAN: type = "boolean"; break; 3869dd0f810Scindi case TOPO_TYPE_INT32: type = "int32"; break; 3879dd0f810Scindi case TOPO_TYPE_UINT32: type = "uint32"; break; 3889dd0f810Scindi case TOPO_TYPE_INT64: type = "int64"; break; 3899dd0f810Scindi case TOPO_TYPE_UINT64: type = "uint64"; break; 3909dd0f810Scindi case TOPO_TYPE_STRING: type = "string"; break; 3919dd0f810Scindi case TOPO_TYPE_FMRI: type = "fmri"; break; 3929dd0f810Scindi case TOPO_TYPE_INT32_ARRAY: type = "int32[]"; break; 3939dd0f810Scindi case TOPO_TYPE_UINT32_ARRAY: type = "uint32[]"; break; 3949dd0f810Scindi case TOPO_TYPE_INT64_ARRAY: type = "int64[]"; break; 3959dd0f810Scindi case TOPO_TYPE_UINT64_ARRAY: type = "uint64[]"; break; 3969dd0f810Scindi case TOPO_TYPE_STRING_ARRAY: type = "string[]"; break; 3979dd0f810Scindi case TOPO_TYPE_FMRI_ARRAY: type = "fmri[]"; break; 3989dd0f810Scindi default: type = "unknown type"; 3999dd0f810Scindi } 4009dd0f810Scindi mdb_printf(" %-32s %-16s value: %p\n", name, type, pval.tp_val); 401c40d7343Scindi 402c40d7343Scindi if (pval.tp_method != NULL) 403c40d7343Scindi dump_propmethod((uintptr_t)pval.tp_method); 404c40d7343Scindi 4059dd0f810Scindi return (WALK_NEXT); 4069dd0f810Scindi } 4079dd0f810Scindi 4089dd0f810Scindi 4099dd0f810Scindi /* 4109dd0f810Scindi * Dumps the contents of the property group. 4119dd0f810Scindi */ 4129dd0f810Scindi /*ARGSUSED*/ 4139dd0f810Scindi static int 4149dd0f810Scindi dump_pgroup(uintptr_t addr, const void *data, void *arg) 4159dd0f810Scindi { 4169dd0f810Scindi topo_pgroup_t *pgp = (topo_pgroup_t *)data; 4179dd0f810Scindi topo_ipgroup_info_t ipg; 4189dd0f810Scindi char buf[32]; 4199dd0f810Scindi 4209dd0f810Scindi if (mdb_vread(&ipg, sizeof (ipg), (uintptr_t)pgp->tpg_info) 4219dd0f810Scindi != sizeof (ipg)) { 4229dd0f810Scindi 4239dd0f810Scindi mdb_warn("failed to read topo_ipgroup_info_t at %p", 4249dd0f810Scindi pgp->tpg_info); 4259dd0f810Scindi return (WALK_ERR); 4269dd0f810Scindi } 4279dd0f810Scindi if (mdb_readstr(buf, sizeof (buf), (uintptr_t)ipg.tpi_name) < 0) { 4289dd0f810Scindi mdb_warn("failed to read string at %p", ipg.tpi_name); 4299dd0f810Scindi return (WALK_ERR); 4309dd0f810Scindi } 4319dd0f810Scindi /* 4329dd0f810Scindi * If this property group is the one we're interested in or if the user 4339dd0f810Scindi * specified the "all" property group, we'll dump it 4349dd0f810Scindi */ 4359dd0f810Scindi if ((strncmp(pgrp, buf, sizeof (buf)) == 0) || 4369dd0f810Scindi (strncmp(pgrp, "all", sizeof (buf)) == 0)) { 4379dd0f810Scindi 4389dd0f810Scindi mdb_printf(" group: %-32s version: %d, stability: %s/%s\n", 4399dd0f810Scindi buf, ipg.tpi_version, stab_lvls[ipg.tpi_namestab], 4409dd0f810Scindi stab_lvls[ipg.tpi_datastab]); 4419dd0f810Scindi 4429dd0f810Scindi (void) mdb_pwalk("topo_proplist", dump_propval, NULL, curr_pg); 4439dd0f810Scindi } 4449dd0f810Scindi return (WALK_NEXT); 4459dd0f810Scindi } 4469dd0f810Scindi 4479dd0f810Scindi 4489dd0f810Scindi /* 4499dd0f810Scindi * Recursive function to dump the specified node and all of it's children 4509dd0f810Scindi */ 4519dd0f810Scindi /*ARGSUSED*/ 4529dd0f810Scindi static int 4539dd0f810Scindi dump_tnode(uintptr_t addr, const void *data, void *arg) 4549dd0f810Scindi { 4559dd0f810Scindi tnode_t node; 4569dd0f810Scindi char pname[255], buf[80], old_pname[255]; 4579dd0f810Scindi 4589dd0f810Scindi if (!addr) { 4599dd0f810Scindi return (WALK_NEXT); 4609dd0f810Scindi } 4619dd0f810Scindi 4629dd0f810Scindi if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) { 4639dd0f810Scindi mdb_warn("failed to read tnode_t at %p", addr); 4649dd0f810Scindi return (WALK_ERR); 4659dd0f810Scindi } 4669dd0f810Scindi if (mdb_readstr(buf, sizeof (buf), (uintptr_t)node.tn_name) < 0) { 4679dd0f810Scindi (void) mdb_snprintf(buf, sizeof (buf), "<%p>", 4689dd0f810Scindi node.tn_name); 4699dd0f810Scindi } 4709dd0f810Scindi 4719dd0f810Scindi if (is_root) { 4729dd0f810Scindi mdb_snprintf(pname, sizeof (pname), "%s", parent); 4739dd0f810Scindi is_root = 0; 4749dd0f810Scindi } else { 4759dd0f810Scindi mdb_snprintf(pname, sizeof (pname), "%s/%s=%u", 4769dd0f810Scindi parent, buf, node.tn_instance); 4779dd0f810Scindi 4789dd0f810Scindi if (verbose) 4799dd0f810Scindi mdb_printf("%s\n tnode_t: %p\n", pname, addr); 4809dd0f810Scindi else 4819dd0f810Scindi mdb_printf("%s\n", pname); 4829dd0f810Scindi } 4839dd0f810Scindi mdb_snprintf(old_pname, sizeof (old_pname), "%s", parent); 4849dd0f810Scindi mdb_snprintf(parent, sizeof (parent), "%s", pname); 4859dd0f810Scindi 4869dd0f810Scindi if (pgrp) 4879dd0f810Scindi (void) mdb_pwalk("topo_pgroup", dump_pgroup, NULL, addr); 4889dd0f810Scindi 4899dd0f810Scindi (void) mdb_pwalk("topo_nodehash", dump_tnode, NULL, addr); 4909dd0f810Scindi mdb_snprintf(parent, sizeof (parent), "%s", old_pname); 4919dd0f810Scindi 4929dd0f810Scindi return (WALK_NEXT); 4939dd0f810Scindi } 4949dd0f810Scindi 4959dd0f810Scindi 4969dd0f810Scindi /* 4979dd0f810Scindi * Given a topo_hdl_t *, the topo dcmd dumps the topo tree. The format of the 4989dd0f810Scindi * output is modeled after fmtopo. Like fmtopo, by default, we'll dump the 4999dd0f810Scindi * "hc" scheme tree. The user can optionally specify a different tree via the 5009dd0f810Scindi * "-s <scheme>" option. 5019dd0f810Scindi * 5029dd0f810Scindi * Specifying the "-v" option provides more verbose output. Currently it 5039dd0f810Scindi * outputs the tnode_t * addr for each node, which is useful if you want to 5049dd0f810Scindi * dump it with the topo_node dcmd. 5059dd0f810Scindi * 5069dd0f810Scindi * The functionality of the "-P" option is similar to fmtopo. 5079dd0f810Scindi */ 5089dd0f810Scindi /*ARGSUSED*/ 5099dd0f810Scindi static int 5109dd0f810Scindi fmtopo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5119dd0f810Scindi { 5129dd0f810Scindi char product[36], *opt_s = NULL, *opt_P = NULL; 5139dd0f810Scindi topo_hdl_t th; 5149dd0f810Scindi tnode_t *tree_root; 5159dd0f810Scindi uint_t opt_v = FALSE; 5169dd0f810Scindi char *def_scheme = "hc"; 5179dd0f810Scindi 5189dd0f810Scindi if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opt_v, 5199dd0f810Scindi 's', MDB_OPT_STR, &opt_s, 'P', MDB_OPT_STR, &opt_P, NULL) 5209dd0f810Scindi != argc) { 5219dd0f810Scindi return (DCMD_USAGE); 5229dd0f810Scindi } 5239dd0f810Scindi 5249dd0f810Scindi if (opt_s) { 5259dd0f810Scindi tgt_scheme = opt_s; 5269dd0f810Scindi } else { 5279dd0f810Scindi tgt_scheme = def_scheme; 5289dd0f810Scindi } 5299dd0f810Scindi 5309dd0f810Scindi pgrp = opt_P; 5319dd0f810Scindi verbose = opt_v; 5329dd0f810Scindi is_root = 1; 5339dd0f810Scindi 5349dd0f810Scindi /* 5359dd0f810Scindi * Read in the topo_handle and some of its string fields from 5369dd0f810Scindi * the target's addr space 5379dd0f810Scindi */ 5389dd0f810Scindi if (mdb_vread(&th, sizeof (th), addr) != sizeof (th)) { 5399dd0f810Scindi mdb_warn("failed to read topo_hdl_t at %p", addr); 5409dd0f810Scindi return (DCMD_ERR); 5419dd0f810Scindi } 5429dd0f810Scindi 5439dd0f810Scindi if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product) 5449dd0f810Scindi < 0) { 5459dd0f810Scindi 5469dd0f810Scindi (void) mdb_snprintf(product, sizeof (product), "<%p>", 5479dd0f810Scindi th.th_product); 5489dd0f810Scindi } 5499dd0f810Scindi 5509dd0f810Scindi mdb_snprintf(parent, sizeof (parent), 5519dd0f810Scindi "%s://:product-id=%s", tgt_scheme, product); 5529dd0f810Scindi 5539dd0f810Scindi /* 5549dd0f810Scindi * Walk the list of topo trees, looking for the one that is for the 5559dd0f810Scindi * scheme we're interested in. 5569dd0f810Scindi */ 5579dd0f810Scindi tree_root = NULL; 5589dd0f810Scindi mdb_pwalk("topo_tree", find_tree_root, &tree_root, addr); 5599dd0f810Scindi 5609dd0f810Scindi if (! tree_root) { 5619dd0f810Scindi mdb_warn("failed to find a topo tree for scheme %s\n", 5629dd0f810Scindi tgt_scheme); 5639dd0f810Scindi return (DCMD_ERR); 5649dd0f810Scindi } 5659dd0f810Scindi 5669dd0f810Scindi return (dump_tnode((uintptr_t)tree_root, NULL, NULL)); 5679dd0f810Scindi } 5689dd0f810Scindi 5699dd0f810Scindi 5709dd0f810Scindi static int 5719dd0f810Scindi ttree_walk_init(mdb_walk_state_t *wsp) 5729dd0f810Scindi { 5739dd0f810Scindi topo_hdl_t th; 5749dd0f810Scindi 5759dd0f810Scindi if (wsp->walk_addr == NULL) { 5769dd0f810Scindi mdb_warn("NULL topo_hdl_t passed in"); 5779dd0f810Scindi return (WALK_ERR); 5789dd0f810Scindi } 5799dd0f810Scindi 5809dd0f810Scindi if (mdb_vread(&th, sizeof (th), wsp->walk_addr) != sizeof (th)) { 5819dd0f810Scindi mdb_warn("failed to read topo_hdl_t at %p", wsp->walk_addr); 5829dd0f810Scindi return (WALK_ERR); 5839dd0f810Scindi } 5849dd0f810Scindi 5859dd0f810Scindi wsp->walk_addr = (uintptr_t)th.th_trees.l_next; 5869dd0f810Scindi wsp->walk_data = mdb_alloc(sizeof (ttree_t), UM_SLEEP); 5879dd0f810Scindi 5889dd0f810Scindi return (WALK_NEXT); 5899dd0f810Scindi } 5909dd0f810Scindi 5919dd0f810Scindi 5929dd0f810Scindi static int 5939dd0f810Scindi ttree_walk_step(mdb_walk_state_t *wsp) 5949dd0f810Scindi { 5959dd0f810Scindi int rv; 5969dd0f810Scindi ttree_t *tree; 5979dd0f810Scindi 5989dd0f810Scindi if (wsp->walk_addr == NULL) 5999dd0f810Scindi return (WALK_DONE); 6009dd0f810Scindi 6019dd0f810Scindi if (mdb_vread(wsp->walk_data, sizeof (ttree_t), wsp->walk_addr) 6029dd0f810Scindi != sizeof (ttree_t)) { 6039dd0f810Scindi 6049dd0f810Scindi mdb_warn("failed to read ttree_t at %p", wsp->walk_addr); 6059dd0f810Scindi return (WALK_ERR); 6069dd0f810Scindi } 6079dd0f810Scindi 6089dd0f810Scindi rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 6099dd0f810Scindi wsp->walk_cbdata); 6109dd0f810Scindi 6119dd0f810Scindi tree = (ttree_t *)wsp->walk_data; 6129dd0f810Scindi wsp->walk_addr = (uintptr_t)tree->tt_list.l_next; 6139dd0f810Scindi 6149dd0f810Scindi return (rv); 6159dd0f810Scindi } 6169dd0f810Scindi 6179dd0f810Scindi 6189dd0f810Scindi static void 6199dd0f810Scindi ttree_walk_fini(mdb_walk_state_t *wsp) 6209dd0f810Scindi { 6219dd0f810Scindi mdb_free(wsp->walk_data, sizeof (ttree_t)); 6229dd0f810Scindi } 6239dd0f810Scindi 6249dd0f810Scindi 6259dd0f810Scindi static int 6269dd0f810Scindi tmod_walk_init(mdb_walk_state_t *wsp) 6279dd0f810Scindi { 6289dd0f810Scindi topo_hdl_t th; 6299dd0f810Scindi 6309dd0f810Scindi if (wsp->walk_addr == NULL) { 6319dd0f810Scindi mdb_warn("NULL topo_hdl_t passed in"); 6329dd0f810Scindi return (WALK_ERR); 6339dd0f810Scindi } 6349dd0f810Scindi 6359dd0f810Scindi if (mdb_vread(&th, sizeof (th), wsp->walk_addr) != sizeof (th)) { 6369dd0f810Scindi mdb_warn("failed to read topo_hdl_t at %p", wsp->walk_addr); 6379dd0f810Scindi return (WALK_ERR); 6389dd0f810Scindi } 6399dd0f810Scindi 6409dd0f810Scindi if (mdb_vread(&tmh, sizeof (topo_modhash_t), (uintptr_t)th.th_modhash) 6419dd0f810Scindi == -1) { 6429dd0f810Scindi 6439dd0f810Scindi mdb_warn("failed to read topo_modhash_t at %p", wsp->walk_addr); 6449dd0f810Scindi return (WALK_DONE); 6459dd0f810Scindi } 6469dd0f810Scindi 6479dd0f810Scindi hash_idx = 0; 6489dd0f810Scindi 6499dd0f810Scindi if (mdb_vread(&(wsp->walk_addr), sizeof (uintptr_t *), 6509dd0f810Scindi (uintptr_t)(tmh.mh_hash)) != sizeof (tnode_t *)) { 6519dd0f810Scindi 6529dd0f810Scindi mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t *), 6539dd0f810Scindi tmh.mh_hash); 6549dd0f810Scindi return (WALK_ERR); 6559dd0f810Scindi } 6569dd0f810Scindi 6579dd0f810Scindi wsp->walk_data = mdb_alloc(sizeof (topo_mod_t), UM_SLEEP); 6589dd0f810Scindi 6599dd0f810Scindi return (WALK_NEXT); 6609dd0f810Scindi } 6619dd0f810Scindi 6629dd0f810Scindi 6639dd0f810Scindi static int 6649dd0f810Scindi tmod_walk_step(mdb_walk_state_t *wsp) 6659dd0f810Scindi { 6669dd0f810Scindi int rv; 6679dd0f810Scindi topo_mod_t *tm; 6689dd0f810Scindi 6699dd0f810Scindi if (wsp->walk_addr == NULL) 6709dd0f810Scindi return (WALK_DONE); 6719dd0f810Scindi 6729dd0f810Scindi if (mdb_vread(wsp->walk_data, sizeof (topo_mod_t), wsp->walk_addr) 6739dd0f810Scindi == -1) { 6749dd0f810Scindi 6759dd0f810Scindi mdb_warn("failed to read topo_mod_t at %p", wsp->walk_addr); 6769dd0f810Scindi return (WALK_DONE); 6779dd0f810Scindi } 6789dd0f810Scindi 6799dd0f810Scindi rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 6809dd0f810Scindi wsp->walk_cbdata); 6819dd0f810Scindi 6829dd0f810Scindi tm = (topo_mod_t *)wsp->walk_data; 6839dd0f810Scindi 6849dd0f810Scindi if (tm->tm_next) 6859dd0f810Scindi wsp->walk_addr = (uintptr_t)tm->tm_next; 6869dd0f810Scindi else if (++hash_idx < tmh.mh_hashlen) 6879dd0f810Scindi if (mdb_vread(&(wsp->walk_addr), sizeof (uintptr_t *), 6889dd0f810Scindi (uintptr_t)(tmh.mh_hash+hash_idx)) != sizeof (tnode_t *)) { 6899dd0f810Scindi 6909dd0f810Scindi mdb_warn("failed to read %u bytes at %p", 6919dd0f810Scindi sizeof (tnode_t *), tmh.mh_hash+hash_idx); 6929dd0f810Scindi return (DCMD_ERR); 6939dd0f810Scindi } 6949dd0f810Scindi else 6959dd0f810Scindi wsp->walk_addr = NULL; 6969dd0f810Scindi 6979dd0f810Scindi return (rv); 6989dd0f810Scindi } 6999dd0f810Scindi 7009dd0f810Scindi static void 7019dd0f810Scindi tmod_walk_fini(mdb_walk_state_t *wsp) 7029dd0f810Scindi { 7039dd0f810Scindi mdb_free(wsp->walk_data, sizeof (topo_mod_t)); 7049dd0f810Scindi } 7059dd0f810Scindi 7069dd0f810Scindi 7079dd0f810Scindi static int 7089dd0f810Scindi tpg_walk_init(mdb_walk_state_t *wsp) 7099dd0f810Scindi { 7109dd0f810Scindi tnode_t node; 7119dd0f810Scindi 7129dd0f810Scindi if (wsp->walk_addr == NULL) { 7139dd0f810Scindi mdb_warn("NULL tnode_t passed in"); 7149dd0f810Scindi return (WALK_ERR); 7159dd0f810Scindi } 7169dd0f810Scindi 7179dd0f810Scindi if (mdb_vread(&node, sizeof (node), wsp->walk_addr) != sizeof (node)) { 7189dd0f810Scindi mdb_warn("failed to read tnode_t at %p", wsp->walk_addr); 7199dd0f810Scindi return (WALK_ERR); 7209dd0f810Scindi } 7219dd0f810Scindi 7229dd0f810Scindi wsp->walk_addr = (uintptr_t)node.tn_pgroups.l_next; 7239dd0f810Scindi wsp->walk_data = mdb_alloc(sizeof (topo_pgroup_t), UM_SLEEP); 7249dd0f810Scindi 7259dd0f810Scindi return (WALK_NEXT); 7269dd0f810Scindi } 7279dd0f810Scindi 7289dd0f810Scindi 7299dd0f810Scindi static int 7309dd0f810Scindi tpg_walk_step(mdb_walk_state_t *wsp) 7319dd0f810Scindi { 7329dd0f810Scindi int rv; 7339dd0f810Scindi topo_pgroup_t *tpgp; 7349dd0f810Scindi 7359dd0f810Scindi if (wsp->walk_addr == NULL) 7369dd0f810Scindi return (WALK_DONE); 7379dd0f810Scindi 7389dd0f810Scindi if (mdb_vread(wsp->walk_data, sizeof (topo_pgroup_t), wsp->walk_addr) 7399dd0f810Scindi == -1) { 7409dd0f810Scindi 7419dd0f810Scindi mdb_warn("failed to read topo_pgroup_t at %p", wsp->walk_addr); 7429dd0f810Scindi return (WALK_DONE); 7439dd0f810Scindi } 7449dd0f810Scindi 7459dd0f810Scindi curr_pg = wsp->walk_addr; 7469dd0f810Scindi rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 7479dd0f810Scindi wsp->walk_cbdata); 7489dd0f810Scindi 7499dd0f810Scindi tpgp = (topo_pgroup_t *)wsp->walk_data; 7509dd0f810Scindi wsp->walk_addr = (uintptr_t)tpgp->tpg_list.l_next; 7519dd0f810Scindi 7529dd0f810Scindi return (rv); 7539dd0f810Scindi } 7549dd0f810Scindi 7559dd0f810Scindi 7569dd0f810Scindi static void 7579dd0f810Scindi tpg_walk_fini(mdb_walk_state_t *wsp) 7589dd0f810Scindi { 7599dd0f810Scindi mdb_free(wsp->walk_data, sizeof (topo_pgroup_t)); 7609dd0f810Scindi } 7619dd0f810Scindi 7629dd0f810Scindi 7639dd0f810Scindi static int 7649dd0f810Scindi tpl_walk_init(mdb_walk_state_t *wsp) 7659dd0f810Scindi { 7669dd0f810Scindi topo_pgroup_t pg; 7679dd0f810Scindi 7689dd0f810Scindi if (wsp->walk_addr == NULL) { 7699dd0f810Scindi mdb_warn("NULL topo_pgroup_t passed in"); 7709dd0f810Scindi return (WALK_ERR); 7719dd0f810Scindi } 7729dd0f810Scindi 7739dd0f810Scindi if (mdb_vread(&pg, sizeof (pg), wsp->walk_addr) != sizeof (pg)) { 7749dd0f810Scindi mdb_warn("failed to read topo_pgroup_t at %p", wsp->walk_addr); 7759dd0f810Scindi return (WALK_ERR); 7769dd0f810Scindi } 7779dd0f810Scindi 7789dd0f810Scindi wsp->walk_addr = (uintptr_t)pg.tpg_pvals.l_next; 7799dd0f810Scindi wsp->walk_data = mdb_alloc(sizeof (topo_proplist_t), UM_SLEEP); 7809dd0f810Scindi 7819dd0f810Scindi return (WALK_NEXT); 7829dd0f810Scindi } 7839dd0f810Scindi 7849dd0f810Scindi 7859dd0f810Scindi static int 7869dd0f810Scindi tpl_walk_step(mdb_walk_state_t *wsp) 7879dd0f810Scindi { 7889dd0f810Scindi int rv; 7899dd0f810Scindi topo_proplist_t *plp; 7909dd0f810Scindi 7919dd0f810Scindi if (wsp->walk_addr == NULL) 7929dd0f810Scindi return (WALK_DONE); 7939dd0f810Scindi 7949dd0f810Scindi if (mdb_vread(wsp->walk_data, sizeof (topo_proplist_t), wsp->walk_addr) 7959dd0f810Scindi == -1) { 7969dd0f810Scindi 7979dd0f810Scindi mdb_warn("failed to read topo_proplist_t at %p", 7989dd0f810Scindi wsp->walk_addr); 7999dd0f810Scindi return (WALK_DONE); 8009dd0f810Scindi } 8019dd0f810Scindi plp = (topo_proplist_t *)wsp->walk_data; 8029dd0f810Scindi 8039dd0f810Scindi rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 8049dd0f810Scindi wsp->walk_cbdata); 8059dd0f810Scindi 8069dd0f810Scindi wsp->walk_addr = (uintptr_t)plp->tp_list.l_next; 8079dd0f810Scindi 8089dd0f810Scindi return (rv); 8099dd0f810Scindi } 8109dd0f810Scindi 8119dd0f810Scindi 8129dd0f810Scindi static void 8139dd0f810Scindi tpl_walk_fini(mdb_walk_state_t *wsp) 8149dd0f810Scindi { 8159dd0f810Scindi mdb_free(wsp->walk_data, sizeof (topo_proplist_t)); 8169dd0f810Scindi } 8179dd0f810Scindi 8189dd0f810Scindi 8199dd0f810Scindi static int 8209dd0f810Scindi tnh_walk_init(mdb_walk_state_t *wsp) 8219dd0f810Scindi { 8229dd0f810Scindi tnode_t node; 8239dd0f810Scindi tnwalk_state_t *state; 8249dd0f810Scindi 8259dd0f810Scindi if (wsp->walk_addr == NULL) { 8269dd0f810Scindi mdb_warn("NULL tnode_t passed in"); 8279dd0f810Scindi return (WALK_ERR); 8289dd0f810Scindi } 8299dd0f810Scindi 8309dd0f810Scindi if (mdb_vread(&node, sizeof (node), wsp->walk_addr) != sizeof (node)) { 8319dd0f810Scindi mdb_warn("failed to read tnode_t at %p", wsp->walk_addr); 8329dd0f810Scindi return (WALK_ERR); 8339dd0f810Scindi } 8349dd0f810Scindi 8359dd0f810Scindi state = mdb_zalloc(sizeof (tnwalk_state_t), UM_SLEEP); 8369dd0f810Scindi 8379dd0f810Scindi state->curr_hash = (topo_nodehash_t *)node.tn_children.l_next; 8389dd0f810Scindi state->hash_idx = 0; 8399dd0f810Scindi wsp->walk_data = state; 8409dd0f810Scindi 8419dd0f810Scindi return (WALK_NEXT); 8429dd0f810Scindi } 8439dd0f810Scindi 8449dd0f810Scindi 8459dd0f810Scindi static int 8469dd0f810Scindi tnh_walk_step(mdb_walk_state_t *wsp) 8479dd0f810Scindi { 8489dd0f810Scindi tnwalk_state_t *state = wsp->walk_data; 8499dd0f810Scindi int rv, i = state->hash_idx++; 8509dd0f810Scindi tnode_t *npp; 8519dd0f810Scindi 8529dd0f810Scindi if (state->curr_hash == NULL) 8539dd0f810Scindi return (WALK_DONE); 8549dd0f810Scindi 8559dd0f810Scindi if (mdb_vread(&(state->hash), sizeof (topo_nodehash_t), 8569dd0f810Scindi (uintptr_t)state->curr_hash) != sizeof (topo_nodehash_t)) { 8579dd0f810Scindi 8589dd0f810Scindi mdb_warn("failed to read topo_nodehash_t at %p", 8599dd0f810Scindi (uintptr_t)state->curr_hash); 8609dd0f810Scindi return (WALK_ERR); 8619dd0f810Scindi } 8629dd0f810Scindi 8639dd0f810Scindi if (mdb_vread(&npp, sizeof (tnode_t *), 8649dd0f810Scindi (uintptr_t)(state->hash.th_nodearr+i)) != sizeof (tnode_t *)) { 8659dd0f810Scindi 8669dd0f810Scindi mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t *), 8679dd0f810Scindi state->hash.th_nodearr+i); 8689dd0f810Scindi return (WALK_ERR); 8699dd0f810Scindi } 8709dd0f810Scindi wsp->walk_addr = (uintptr_t)npp; 8719dd0f810Scindi 8729dd0f810Scindi rv = wsp->walk_callback(wsp->walk_addr, state, wsp->walk_cbdata); 8739dd0f810Scindi 8749dd0f810Scindi if (state->hash_idx >= state->hash.th_arrlen) { 8759dd0f810Scindi /* 8769dd0f810Scindi * move on to the next child hash bucket 8779dd0f810Scindi */ 8789dd0f810Scindi state->curr_hash = 8799dd0f810Scindi (topo_nodehash_t *)(state->hash.th_list.l_next); 8809dd0f810Scindi state->hash_idx = 0; 8819dd0f810Scindi } 8829dd0f810Scindi 8839dd0f810Scindi return (rv); 8849dd0f810Scindi } 8859dd0f810Scindi 8869dd0f810Scindi 8879dd0f810Scindi static void 8889dd0f810Scindi tnh_walk_fini(mdb_walk_state_t *wsp) 8899dd0f810Scindi { 8909dd0f810Scindi mdb_free(wsp->walk_data, sizeof (tnwalk_state_t)); 8919dd0f810Scindi } 8929dd0f810Scindi 8939dd0f810Scindi 8949dd0f810Scindi static const mdb_dcmd_t dcmds[] = { 8959dd0f810Scindi { "topo_handle", "", "print contents of a topo handle", topo_handle, 8969dd0f810Scindi NULL }, 8979dd0f810Scindi { "topo_module", "", "print contents of a topo module handle", 8989dd0f810Scindi topo_module, NULL }, 8999dd0f810Scindi { "topo_node", "", "print contents of a topo node", topo_node, NULL }, 9009dd0f810Scindi { "fmtopo", "[-P <pgroup>][-s <scheme>][-v]", 9019dd0f810Scindi "print topology of the given handle", fmtopo, NULL }, 9029dd0f810Scindi { NULL } 9039dd0f810Scindi }; 9049dd0f810Scindi 9059dd0f810Scindi static const mdb_walker_t walkers[] = { 9069dd0f810Scindi { "topo_tree", "walk the tree list for a given topo handle", 9079dd0f810Scindi ttree_walk_init, ttree_walk_step, ttree_walk_fini, NULL }, 9089dd0f810Scindi { "topo_module", "walk the module hash for a given topo handle", 9099dd0f810Scindi tmod_walk_init, tmod_walk_step, tmod_walk_fini, NULL }, 9109dd0f810Scindi { "topo_pgroup", "walk the property groups for a given topo node", 9119dd0f810Scindi tpg_walk_init, tpg_walk_step, tpg_walk_fini, NULL }, 9129dd0f810Scindi { "topo_proplist", "walk the property list for a given property group", 9139dd0f810Scindi tpl_walk_init, tpl_walk_step, tpl_walk_fini, NULL }, 9149dd0f810Scindi { "topo_nodehash", "walk the child nodehash for a given topo node", 9159dd0f810Scindi tnh_walk_init, tnh_walk_step, tnh_walk_fini, NULL }, 9169dd0f810Scindi { NULL } 9179dd0f810Scindi }; 9189dd0f810Scindi 9199dd0f810Scindi static const mdb_modinfo_t modinfo = { 9209dd0f810Scindi MDB_API_VERSION, dcmds, walkers 9219dd0f810Scindi }; 9229dd0f810Scindi 9239dd0f810Scindi const mdb_modinfo_t * 9249dd0f810Scindi _mdb_init(void) 9259dd0f810Scindi { 9269dd0f810Scindi return (&modinfo); 9279dd0f810Scindi } 928