120c794b3Sgavinm /*
220c794b3Sgavinm  * CDDL HEADER START
320c794b3Sgavinm  *
420c794b3Sgavinm  * The contents of this file are subject to the terms of the
520c794b3Sgavinm  * Common Development and Distribution License (the "License").
620c794b3Sgavinm  * You may not use this file except in compliance with the License.
720c794b3Sgavinm  *
820c794b3Sgavinm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
920c794b3Sgavinm  * or http://www.opensolaris.org/os/licensing.
1020c794b3Sgavinm  * See the License for the specific language governing permissions
1120c794b3Sgavinm  * and limitations under the License.
1220c794b3Sgavinm  *
1320c794b3Sgavinm  * When distributing Covered Code, include this CDDL HEADER in each
1420c794b3Sgavinm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1520c794b3Sgavinm  * If applicable, add the following below this CDDL HEADER, with the
1620c794b3Sgavinm  * fields enclosed by brackets "[]" replaced with your own identifying
1720c794b3Sgavinm  * information: Portions Copyright [yyyy] [name of copyright owner]
1820c794b3Sgavinm  *
1920c794b3Sgavinm  * CDDL HEADER END
2020c794b3Sgavinm  */
2120c794b3Sgavinm 
2220c794b3Sgavinm /*
232d2efdc6SVuong Nguyen  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2420c794b3Sgavinm  */
2520c794b3Sgavinm 
2620c794b3Sgavinm #include <mdb/mdb_modapi.h>
2720c794b3Sgavinm #include <generic_cpu/gcpu.h>
2820c794b3Sgavinm #include <sys/cpu_module_impl.h>
2920c794b3Sgavinm #include <sys/cpu_module_ms_impl.h>
3020c794b3Sgavinm 
3120c794b3Sgavinm typedef struct cmi_hdl_impl {
3220c794b3Sgavinm 	enum cmi_hdl_class cmih_class;		/* Handle nature */
3320c794b3Sgavinm 	struct cmi_hdl_ops *cmih_ops;		/* Operations vector */
3420c794b3Sgavinm 	uint_t cmih_chipid;			/* Chipid of cpu resource */
358031591dSSrihari Venkatesan 	uint_t cmih_procnodeid;			/* Nodeid of cpu resource */
3620c794b3Sgavinm 	uint_t cmih_coreid;			/* Core within die */
3720c794b3Sgavinm 	uint_t cmih_strandid;			/* Thread within core */
388031591dSSrihari Venkatesan 	uint_t cmih_procnodes_per_pkg;		/* Nodes in a processor */
391fbe4a4fSSrihari Venkatesan 	boolean_t cmih_mstrand;			/* cores are multithreaded */
4020c794b3Sgavinm 	volatile uint32_t *cmih_refcntp;	/* Reference count pointer */
4120c794b3Sgavinm 	uint64_t cmih_msrsrc;			/* MSR data source flags */
4220c794b3Sgavinm 	void *cmih_hdlpriv;			/* cmi_hw.c private data */
4320c794b3Sgavinm 	void *cmih_spec;			/* cmi_hdl_{set,get}_specific */
4420c794b3Sgavinm 	void *cmih_cmi;				/* cpu mod control structure */
4520c794b3Sgavinm 	void *cmih_cmidata;			/* cpu mod private data */
4620c794b3Sgavinm 	const struct cmi_mc_ops *cmih_mcops;	/* Memory-controller ops */
4720c794b3Sgavinm 	void *cmih_mcdata;			/* Memory-controller data */
48e4b86885SCheng Sean Ye 	uint64_t cmih_flags;
49074bb90dSTom Pothier 	uint16_t cmih_smbiosid;			/* SMBIOS Type 4 struct ID */
50074bb90dSTom Pothier 	uint_t cmih_smb_chipid;			/* smbios chipid */
51074bb90dSTom Pothier 	nvlist_t *cmih_smb_bboard;		/* smbios bboard */
5220c794b3Sgavinm } cmi_hdl_impl_t;
5320c794b3Sgavinm 
542d39cb4cSVuong Nguyen typedef struct cmi_hdl_ent {
55a3c46958Sgavinm 	volatile uint32_t cmae_refcnt;
56a3c46958Sgavinm 	cmi_hdl_impl_t *cmae_hdlp;
572d39cb4cSVuong Nguyen } cmi_hdl_ent_t;
5820c794b3Sgavinm 
5920c794b3Sgavinm typedef struct cmi {
6020c794b3Sgavinm 	struct cmi *cmi_next;
6120c794b3Sgavinm 	struct cmi *cmi_prev;
6220c794b3Sgavinm 	const cmi_ops_t *cmi_ops;
6320c794b3Sgavinm 	struct modctl *cmi_modp;
6420c794b3Sgavinm 	uint_t cmi_refcnt;
6520c794b3Sgavinm } cmi_t;
6620c794b3Sgavinm 
6720c794b3Sgavinm typedef struct cms {
6820c794b3Sgavinm 	struct cms *cms_next;
6920c794b3Sgavinm 	struct cms *cms_prev;
7020c794b3Sgavinm 	const cms_ops_t *cms_ops;
7120c794b3Sgavinm 	struct modctl *cms_modp;
7220c794b3Sgavinm 	uint_t cms_refcnt;
7320c794b3Sgavinm } cms_t;
7420c794b3Sgavinm 
7520c794b3Sgavinm struct cms_ctl {
7620c794b3Sgavinm 	cms_t *cs_cms;
7720c794b3Sgavinm 	void *cs_cmsdata;
7820c794b3Sgavinm };
7920c794b3Sgavinm 
802d39cb4cSVuong Nguyen #define	CMI_MAX_CHIPID_NBITS		6	/* max chipid of 63 */
812d39cb4cSVuong Nguyen 
822d39cb4cSVuong Nguyen #define	CMI_MAX_CHIPID			((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
832d2efdc6SVuong Nguyen #define	CMI_MAX_CORES_PER_CHIP(cbits)	(1 << (cbits))
842d2efdc6SVuong Nguyen #define	CMI_MAX_COREID(cbits)		((1 << (cbits)) - 1)
852d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDS_PER_CORE(sbits)	(1 << (sbits))
862d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDID(sbits)		((1 << (sbits)) - 1)
872d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDS_PER_CHIP(cbits, sbits)	\
882d2efdc6SVuong Nguyen 	(CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
892d39cb4cSVuong Nguyen 
902d39cb4cSVuong Nguyen #define	CMI_CHIPID_ARR_SZ		(1 << CMI_MAX_CHIPID_NBITS)
9120c794b3Sgavinm 
9220c794b3Sgavinm struct cmih_walk_state {
932d39cb4cSVuong Nguyen 	int chipid, coreid, strandid;	/* currently visited cpu */
942d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *chip_tab[CMI_CHIPID_ARR_SZ];
952d2efdc6SVuong Nguyen 	uint_t core_nbits;
962d2efdc6SVuong Nguyen 	uint_t strand_nbits;
9720c794b3Sgavinm };
9820c794b3Sgavinm 
992d39cb4cSVuong Nguyen /*
1002d39cb4cSVuong Nguyen  * Advance the <chipid,coreid,strandid> tuple to the next strand entry
1012d39cb4cSVuong Nguyen  * Return true upon sucessful result. Otherwise return false if already reach
1022d39cb4cSVuong Nguyen  * the highest strand.
1032d39cb4cSVuong Nguyen  */
1042d39cb4cSVuong Nguyen static boolean_t
cmih_ent_next(struct cmih_walk_state * wsp)1052d39cb4cSVuong Nguyen cmih_ent_next(struct cmih_walk_state *wsp)
1062d39cb4cSVuong Nguyen {
1072d39cb4cSVuong Nguyen 	uint_t carry = 0;
1082d39cb4cSVuong Nguyen 
1092d39cb4cSVuong Nguyen 	/* Check for end of the table */
1102d2efdc6SVuong Nguyen 	if (wsp->chipid >= CMI_MAX_CHIPID &&
1112d2efdc6SVuong Nguyen 	    wsp->coreid >= CMI_MAX_COREID(wsp->core_nbits) &&
1122d2efdc6SVuong Nguyen 	    wsp->strandid >= CMI_MAX_STRANDID(wsp->strand_nbits))
1132d39cb4cSVuong Nguyen 		return (B_FALSE);
1142d39cb4cSVuong Nguyen 
1152d39cb4cSVuong Nguyen 	/* increment the strand id */
1162d39cb4cSVuong Nguyen 	wsp->strandid++;
1172d2efdc6SVuong Nguyen 	carry =  wsp->strandid >> wsp->strand_nbits;
1182d2efdc6SVuong Nguyen 	wsp->strandid =  wsp->strandid & CMI_MAX_STRANDID(wsp->strand_nbits);
1192d39cb4cSVuong Nguyen 	if (carry == 0)
1202d39cb4cSVuong Nguyen 		return (B_TRUE);
1212d39cb4cSVuong Nguyen 
1222d39cb4cSVuong Nguyen 	/* increment the core id */
1232d39cb4cSVuong Nguyen 	wsp->coreid++;
1242d2efdc6SVuong Nguyen 	carry = wsp->coreid >> wsp->core_nbits;
1252d2efdc6SVuong Nguyen 	wsp->coreid = wsp->coreid & CMI_MAX_COREID(wsp->core_nbits);
1262d39cb4cSVuong Nguyen 	if (carry == 0)
1272d39cb4cSVuong Nguyen 		return (B_TRUE);
1282d39cb4cSVuong Nguyen 
1292d39cb4cSVuong Nguyen 	/* increment the chip id */
1302bc98732SRichard Lowe 	wsp->chipid = (wsp->chipid + 1) & (CMI_MAX_CHIPID);
1312d39cb4cSVuong Nguyen 
1322d39cb4cSVuong Nguyen 	return (B_TRUE);
1332d39cb4cSVuong Nguyen }
1342d39cb4cSVuong Nguyen 
1352d39cb4cSVuong Nguyen /*
1362d2efdc6SVuong Nguyen  * Lookup for the hdl entry of a given <chip,core,strand> tuple
1372d39cb4cSVuong Nguyen  */
1382d39cb4cSVuong Nguyen static cmi_hdl_ent_t *
cmih_ent_lookup(struct cmih_walk_state * wsp)1392d39cb4cSVuong Nguyen cmih_ent_lookup(struct cmih_walk_state *wsp)
1402d39cb4cSVuong Nguyen {
1412d39cb4cSVuong Nguyen 	if (wsp == NULL || wsp->chip_tab[wsp->chipid] == NULL)
1422d39cb4cSVuong Nguyen 		return (NULL);	/* chip is not present */
1432d39cb4cSVuong Nguyen 
1442d39cb4cSVuong Nguyen 	return (wsp->chip_tab[wsp->chipid] +
1452d2efdc6SVuong Nguyen 	    (((wsp->coreid & CMI_MAX_COREID(wsp->core_nbits)) <<
1462d2efdc6SVuong Nguyen 	    wsp->strand_nbits) |
1472d2efdc6SVuong Nguyen 	    ((wsp->strandid) & CMI_MAX_STRANDID(wsp->strand_nbits))));
1482d39cb4cSVuong Nguyen }
1492d39cb4cSVuong Nguyen 
1502d39cb4cSVuong Nguyen /* forward decls */
1512d39cb4cSVuong Nguyen static void
1522d39cb4cSVuong Nguyen cmih_walk_fini(mdb_walk_state_t *wsp);
1532d39cb4cSVuong Nguyen 
15420c794b3Sgavinm static int
cmih_walk_init(mdb_walk_state_t * wsp)15520c794b3Sgavinm cmih_walk_init(mdb_walk_state_t *wsp)
15620c794b3Sgavinm {
1572d39cb4cSVuong Nguyen 	int i;
1582d39cb4cSVuong Nguyen 	ssize_t sz;
159a3c46958Sgavinm 	struct cmih_walk_state *awsp;
1602d39cb4cSVuong Nguyen 	void *pg;
1612d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
16220c794b3Sgavinm 
163*892ad162SToomas Soome 	if (wsp->walk_addr != 0) {
164a3c46958Sgavinm 		mdb_warn("cmihdl is a global walker\n");
16520c794b3Sgavinm 		return (WALK_ERR);
16620c794b3Sgavinm 	}
16720c794b3Sgavinm 
168a3c46958Sgavinm 	wsp->walk_data = awsp =
16920c794b3Sgavinm 	    mdb_zalloc(sizeof (struct cmih_walk_state), UM_SLEEP);
17020c794b3Sgavinm 
1712d2efdc6SVuong Nguyen 	/* read the number of core bits and strand bits */
1722d2efdc6SVuong Nguyen 	if (mdb_readvar(&awsp->core_nbits, "cmi_core_nbits") == -1) {
1732d2efdc6SVuong Nguyen 		mdb_warn("read of cmi_core_nbits failed");
1742d2efdc6SVuong Nguyen 		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1752d2efdc6SVuong Nguyen 		wsp->walk_data = NULL;
1762d2efdc6SVuong Nguyen 		return (WALK_ERR);
1772d2efdc6SVuong Nguyen 	}
1782d2efdc6SVuong Nguyen 	if (mdb_readvar(&awsp->strand_nbits, "cmi_strand_nbits") == -1) {
1792d2efdc6SVuong Nguyen 		mdb_warn("read of cmi_strand_nbits failed");
1802d2efdc6SVuong Nguyen 		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1812d2efdc6SVuong Nguyen 		wsp->walk_data = NULL;
1822d2efdc6SVuong Nguyen 		return (WALK_ERR);
1832d2efdc6SVuong Nguyen 	}
1842d2efdc6SVuong Nguyen 
1852d39cb4cSVuong Nguyen 	/* table of chipid entries */
1862d39cb4cSVuong Nguyen 	if ((sz = mdb_readvar(&awsp->chip_tab, "cmi_chip_tab")) == -1) {
1872d39cb4cSVuong Nguyen 		mdb_warn("read of cmi_chip_tab failed");
1882d39cb4cSVuong Nguyen 		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1892d39cb4cSVuong Nguyen 		wsp->walk_data = NULL;
19020c794b3Sgavinm 		return (WALK_ERR);
1912d39cb4cSVuong Nguyen 	} else if (sz < sizeof (awsp->chip_tab)) {
1922d39cb4cSVuong Nguyen 		mdb_warn("Unexpected cmi_chip_tab size (exp=%ld, actual=%ld)",
1932d39cb4cSVuong Nguyen 		    sizeof (awsp->chip_tab), sz);
1942d39cb4cSVuong Nguyen 		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1952d39cb4cSVuong Nguyen 		wsp->walk_data = NULL;
1962d39cb4cSVuong Nguyen 		return (WALK_ERR);
1972d39cb4cSVuong Nguyen 	}
1982d39cb4cSVuong Nguyen 
1992d39cb4cSVuong Nguyen 	/* read the per-chip table that contains all strands of the chip */
2002d2efdc6SVuong Nguyen 	sz = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits, awsp->strand_nbits) *
2012d2efdc6SVuong Nguyen 	    sizeof (cmi_hdl_ent_t);
2022d39cb4cSVuong Nguyen 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
2032d39cb4cSVuong Nguyen 		if (awsp->chip_tab[i] == NULL)
2042d39cb4cSVuong Nguyen 			continue; /* this chip(i) is not present */
2052d39cb4cSVuong Nguyen 		pg = mdb_alloc(sz, UM_SLEEP);
2062d39cb4cSVuong Nguyen 		if (mdb_vread(pg, sz, (uintptr_t)awsp->chip_tab[i]) != sz) {
2072d39cb4cSVuong Nguyen 			mdb_warn("read of cmi_hdl(%i) array at 0x%p failed",
2082d39cb4cSVuong Nguyen 			    i, awsp->chip_tab[i]);
2092d39cb4cSVuong Nguyen 			mdb_free(pg, sz);
2102d39cb4cSVuong Nguyen 			cmih_walk_fini(wsp);
2112d39cb4cSVuong Nguyen 			return (WALK_ERR);
2122d39cb4cSVuong Nguyen 		}
2132d39cb4cSVuong Nguyen 		awsp->chip_tab[i] = pg;
21420c794b3Sgavinm 	}
21520c794b3Sgavinm 
2162d39cb4cSVuong Nguyen 	/* Look up the hdl of the first strand <0,0,0> */
217*892ad162SToomas Soome 	wsp->walk_addr = 0;
2182d39cb4cSVuong Nguyen 	if ((ent = cmih_ent_lookup(awsp)) != NULL)
2192d39cb4cSVuong Nguyen 		wsp->walk_addr = (uintptr_t)ent->cmae_hdlp;
22020c794b3Sgavinm 
22120c794b3Sgavinm 	return (WALK_NEXT);
22220c794b3Sgavinm }
22320c794b3Sgavinm 
22420c794b3Sgavinm static int
cmih_walk_step(mdb_walk_state_t * wsp)22520c794b3Sgavinm cmih_walk_step(mdb_walk_state_t *wsp)
22620c794b3Sgavinm {
227a3c46958Sgavinm 	struct cmih_walk_state *awsp = wsp->walk_data;
228*892ad162SToomas Soome 	uintptr_t addr = 0;
22920c794b3Sgavinm 	cmi_hdl_impl_t hdl;
2302d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
23120c794b3Sgavinm 	int rv;
23220c794b3Sgavinm 
2332d39cb4cSVuong Nguyen 	if ((ent = cmih_ent_lookup(awsp)) != NULL)
2342d39cb4cSVuong Nguyen 		addr = (uintptr_t)ent->cmae_hdlp;
235*892ad162SToomas Soome 	if (wsp->walk_addr == 0 || addr == 0)
2362d39cb4cSVuong Nguyen 		return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
23720c794b3Sgavinm 
23820c794b3Sgavinm 	if (mdb_vread(&hdl, sizeof (hdl), addr) != sizeof (hdl)) {
23920c794b3Sgavinm 		mdb_warn("read of handle at 0x%p failed", addr);
24020c794b3Sgavinm 		return (WALK_DONE);
24120c794b3Sgavinm 	}
24220c794b3Sgavinm 
24320c794b3Sgavinm 	if ((rv = wsp->walk_callback(addr, (void *)&hdl,
24420c794b3Sgavinm 	    wsp->walk_cbdata)) != WALK_NEXT)
24520c794b3Sgavinm 		return (rv);
24620c794b3Sgavinm 
2472d39cb4cSVuong Nguyen 	return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
24820c794b3Sgavinm }
24920c794b3Sgavinm 
25020c794b3Sgavinm static void
cmih_walk_fini(mdb_walk_state_t * wsp)25120c794b3Sgavinm cmih_walk_fini(mdb_walk_state_t *wsp)
25220c794b3Sgavinm {
253a3c46958Sgavinm 	struct cmih_walk_state *awsp = wsp->walk_data;
25420c794b3Sgavinm 
255a3c46958Sgavinm 	if (awsp != NULL) {
2562d39cb4cSVuong Nguyen 		int i;
2572d2efdc6SVuong Nguyen 		int max_strands = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits,
2582d2efdc6SVuong Nguyen 		    awsp->strand_nbits);
2592d39cb4cSVuong Nguyen 		for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
2602d39cb4cSVuong Nguyen 			/* free the per-chip table */
2612d39cb4cSVuong Nguyen 			if (awsp->chip_tab[i] != NULL) {
2622d39cb4cSVuong Nguyen 				mdb_free((void *)awsp->chip_tab[i],
2632d2efdc6SVuong Nguyen 				    max_strands * sizeof (cmi_hdl_ent_t));
2642d39cb4cSVuong Nguyen 				awsp->chip_tab[i] = NULL;
2652d39cb4cSVuong Nguyen 			}
2662d39cb4cSVuong Nguyen 		}
26720c794b3Sgavinm 		mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
2682d39cb4cSVuong Nguyen 		wsp->walk_data = NULL;
26920c794b3Sgavinm 	}
27020c794b3Sgavinm }
27120c794b3Sgavinm 
27220c794b3Sgavinm struct cmihdl_cb {
27320c794b3Sgavinm 	int mod_cpuid;
27420c794b3Sgavinm 	int mod_chipid;
27520c794b3Sgavinm 	int mod_coreid;
27620c794b3Sgavinm 	int mod_strandid;
27720c794b3Sgavinm 	uintptr_t mod_hdladdr;
27820c794b3Sgavinm };
27920c794b3Sgavinm 
28020c794b3Sgavinm static int
cmihdl_cb(uintptr_t addr,const void * arg,void * data)28120c794b3Sgavinm cmihdl_cb(uintptr_t addr, const void *arg, void *data)
28220c794b3Sgavinm {
28320c794b3Sgavinm 	cmi_hdl_impl_t *hdl = (cmi_hdl_impl_t *)arg;
28420c794b3Sgavinm 	struct cmihdl_cb *cbp = data;
28520c794b3Sgavinm 	cpu_t *cp;
28620c794b3Sgavinm 	int rv;
28720c794b3Sgavinm 
28820c794b3Sgavinm 	if (cbp->mod_cpuid != -1) {
28920c794b3Sgavinm 		cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
29020c794b3Sgavinm 		if (mdb_vread(cp, sizeof (cpu_t),
29120c794b3Sgavinm 		    (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
29220c794b3Sgavinm 			mdb_warn("Read of cpu_t at 0x%p failed",
29320c794b3Sgavinm 			    hdl->cmih_hdlpriv);
29420c794b3Sgavinm 			mdb_free(cp, sizeof (cpu_t));
29520c794b3Sgavinm 			return (WALK_ERR);
29620c794b3Sgavinm 		}
29720c794b3Sgavinm 
29820c794b3Sgavinm 		if (cp->cpu_id == cbp->mod_cpuid) {
29920c794b3Sgavinm 			cbp->mod_hdladdr = addr;
30020c794b3Sgavinm 			rv = WALK_DONE;
30120c794b3Sgavinm 		} else {
30220c794b3Sgavinm 			rv = WALK_NEXT;
30320c794b3Sgavinm 		}
30420c794b3Sgavinm 
30520c794b3Sgavinm 		mdb_free(cp, sizeof (cpu_t));
30620c794b3Sgavinm 		return (rv);
30720c794b3Sgavinm 	} else {
30820c794b3Sgavinm 		if (hdl->cmih_chipid == cbp->mod_chipid &&
30920c794b3Sgavinm 		    hdl->cmih_coreid == cbp->mod_coreid &&
31020c794b3Sgavinm 		    hdl->cmih_strandid == cbp->mod_strandid) {
31120c794b3Sgavinm 			cbp->mod_hdladdr = addr;
31220c794b3Sgavinm 			return (WALK_DONE);
31320c794b3Sgavinm 		} else {
31420c794b3Sgavinm 			return (WALK_NEXT);
31520c794b3Sgavinm 		}
31620c794b3Sgavinm 	}
31720c794b3Sgavinm }
31820c794b3Sgavinm 
31920c794b3Sgavinm static int
cmihdl_disp(uintptr_t addr,cmi_hdl_impl_t * hdl)32020c794b3Sgavinm cmihdl_disp(uintptr_t addr, cmi_hdl_impl_t *hdl)
32120c794b3Sgavinm {
32220c794b3Sgavinm 	struct cms_ctl cmsctl;			/* 16 bytes max */
32320c794b3Sgavinm 	struct modctl cmimodc, cmsmodc;		/* 288 bytes max */
32420c794b3Sgavinm 	cmi_t cmi;				/* 40 bytes max */
32520c794b3Sgavinm 	cms_t cms;				/* 40 bytes max */
32620c794b3Sgavinm 	cpu_t *cp;
32720c794b3Sgavinm 	char cmimodnm[25], cmsmodnm[25];	/* 50 bytes */
32820c794b3Sgavinm 	char cpuidstr[4], hwidstr[16];
32920c794b3Sgavinm 	int native = hdl->cmih_class == CMI_HDL_NATIVE;
33020c794b3Sgavinm 	uint32_t refcnt;
33120c794b3Sgavinm 
33220c794b3Sgavinm 	cmimodnm[0] = cmsmodnm[0] = '-';
33320c794b3Sgavinm 	cmimodnm[1] = cmsmodnm[1] = '\0';
33420c794b3Sgavinm 
33520c794b3Sgavinm 	if (hdl->cmih_cmi != NULL) {
33620c794b3Sgavinm 		if (mdb_vread(&cmi, sizeof (cmi_t),
33720c794b3Sgavinm 		    (uintptr_t)hdl->cmih_cmi) != sizeof (cmi)) {
33820c794b3Sgavinm 			mdb_warn("Read of cmi_t at 0x%p failed",
33920c794b3Sgavinm 			    hdl->cmih_cmi);
34020c794b3Sgavinm 			return (0);
34120c794b3Sgavinm 		}
34220c794b3Sgavinm 
34320c794b3Sgavinm 		if (cmi.cmi_modp != NULL) {
34420c794b3Sgavinm 			if (mdb_vread(&cmimodc, sizeof (struct modctl),
34520c794b3Sgavinm 			    (uintptr_t)cmi.cmi_modp) != sizeof (cmimodc)) {
34620c794b3Sgavinm 				mdb_warn("Read of modctl at 0x%p failed",
34720c794b3Sgavinm 				    cmi.cmi_modp);
34820c794b3Sgavinm 				return (0);
34920c794b3Sgavinm 			}
35020c794b3Sgavinm 
35120c794b3Sgavinm 			if (mdb_readstr(cmimodnm, sizeof (cmimodnm),
35220c794b3Sgavinm 			    (uintptr_t)cmimodc.mod_modname) == -1) {
35320c794b3Sgavinm 				mdb_warn("Read of cmi module name at 0x%p "
35420c794b3Sgavinm 				    "failed", cmimodc.mod_modname);
35520c794b3Sgavinm 				return (0);
35620c794b3Sgavinm 			}
35720c794b3Sgavinm 		}
35820c794b3Sgavinm 	}
35920c794b3Sgavinm 
36020c794b3Sgavinm 	if (hdl->cmih_spec != NULL) {
36120c794b3Sgavinm 		if (mdb_vread(&cmsctl, sizeof (struct cms_ctl),
36220c794b3Sgavinm 		    (uintptr_t)hdl->cmih_spec) != sizeof (cmsctl)) {
36320c794b3Sgavinm 			mdb_warn("Read of struct cms_ctl at 0x%p failed",
36420c794b3Sgavinm 			    hdl->cmih_spec);
36520c794b3Sgavinm 			return (0);
36620c794b3Sgavinm 		}
36720c794b3Sgavinm 
36820c794b3Sgavinm 		if (mdb_vread(&cms, sizeof (cms_t),
36920c794b3Sgavinm 		    (uintptr_t)cmsctl.cs_cms) != sizeof (cms)) {
37020c794b3Sgavinm 			mdb_warn("Read of cms_t at 0x%p failed", cmsctl.cs_cms);
37120c794b3Sgavinm 			return (0);
37220c794b3Sgavinm 		}
37320c794b3Sgavinm 
37420c794b3Sgavinm 		if (cms.cms_modp != NULL) {
37520c794b3Sgavinm 			if (mdb_vread(&cmsmodc, sizeof (struct modctl),
37620c794b3Sgavinm 			    (uintptr_t)cms.cms_modp) != sizeof (cmsmodc)) {
37720c794b3Sgavinm 				mdb_warn("Read of modctl at 0x%p failed",
37820c794b3Sgavinm 				    cms.cms_modp);
37920c794b3Sgavinm 				return (0);
38020c794b3Sgavinm 			}
38120c794b3Sgavinm 
38220c794b3Sgavinm 			if (mdb_readstr(cmsmodnm, sizeof (cmsmodnm),
38320c794b3Sgavinm 			    (uintptr_t)cmsmodc.mod_modname) == -1) {
38420c794b3Sgavinm 				mdb_warn("Read of cms module name at 0x%p "
38520c794b3Sgavinm 				    "failed", cmsmodc.mod_modname);
38620c794b3Sgavinm 				return (0);
38720c794b3Sgavinm 			}
38820c794b3Sgavinm 		}
38920c794b3Sgavinm 	}
39020c794b3Sgavinm 
39120c794b3Sgavinm 	if (mdb_vread(&refcnt, sizeof (uint32_t),
39220c794b3Sgavinm 	    (uintptr_t)hdl->cmih_refcntp) != sizeof (uint32_t)) {
39320c794b3Sgavinm 		mdb_warn("Read of reference count for hdl 0x%p failed", hdl);
39420c794b3Sgavinm 		return (0);
39520c794b3Sgavinm 	}
39620c794b3Sgavinm 
39720c794b3Sgavinm 	if (native) {
39820c794b3Sgavinm 		cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
39920c794b3Sgavinm 
40020c794b3Sgavinm 		if (mdb_vread(cp, sizeof (cpu_t),
40120c794b3Sgavinm 		    (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
40220c794b3Sgavinm 			mdb_free(cp, sizeof (cpu_t));
40320c794b3Sgavinm 			mdb_warn("Read of cpu_t at 0x%p failed",
40420c794b3Sgavinm 			    hdl->cmih_hdlpriv);
40520c794b3Sgavinm 			return (0);
40620c794b3Sgavinm 		}
40720c794b3Sgavinm 	}
40820c794b3Sgavinm 
40920c794b3Sgavinm 	if (native) {
41020c794b3Sgavinm 		(void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "%d",
41120c794b3Sgavinm 		    cp->cpu_id);
41220c794b3Sgavinm 	} else {
41320c794b3Sgavinm 		(void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "-");
41420c794b3Sgavinm 	}
41520c794b3Sgavinm 
41620c794b3Sgavinm 	(void) mdb_snprintf(hwidstr, sizeof (hwidstr), "%d/%d/%d",
41720c794b3Sgavinm 	    hdl->cmih_chipid, hdl->cmih_coreid, hdl->cmih_strandid);
41820c794b3Sgavinm 
419728f047cSAdrian Frost 	mdb_printf("%16lx %3d %3s %8s %3s %2s %-13s %-24s\n", addr,
420728f047cSAdrian Frost 	    refcnt, cpuidstr, hwidstr, hdl->cmih_mstrand ? "M" : "S",
421728f047cSAdrian Frost 	    hdl->cmih_mcops ? "Y" : "N", cmimodnm, cmsmodnm);
42220c794b3Sgavinm 
42320c794b3Sgavinm 	if (native)
42420c794b3Sgavinm 		mdb_free(cp, sizeof (cpu_t));
42520c794b3Sgavinm 
42620c794b3Sgavinm 	return (1);
42720c794b3Sgavinm }
42820c794b3Sgavinm 
429728f047cSAdrian Frost #define	HDRFMT "%-16s %3s %3s %8s %3s %2s %-13s %-24s\n"
43020c794b3Sgavinm 
43120c794b3Sgavinm static int
cmihdl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)43220c794b3Sgavinm cmihdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
43320c794b3Sgavinm {
43420c794b3Sgavinm 	struct cmihdl_cb cb;
43520c794b3Sgavinm 	cmi_hdl_impl_t *hdl;
43620c794b3Sgavinm 
43720c794b3Sgavinm 	/*
43820c794b3Sgavinm 	 * If an address is given it must be that of a cmi handle.
43920c794b3Sgavinm 	 * Otherwise if the user has specified -c <cpuid> or
44020c794b3Sgavinm 	 * -c <chipid/coreid/strandid> we will lookup a matching handle.
44120c794b3Sgavinm 	 * Otherwise we'll walk and callback to this dcmd.
44220c794b3Sgavinm 	 */
44320c794b3Sgavinm 	if (!(flags & DCMD_ADDRSPEC)) {
44420c794b3Sgavinm 		char *p, *buf;
44520c794b3Sgavinm 		int len;
44620c794b3Sgavinm 
44720c794b3Sgavinm 		if (argc == 0)
44820c794b3Sgavinm 			return (mdb_walk_dcmd("cmihdl", "cmihdl", argc,
44920c794b3Sgavinm 			    argv) == 0 ? DCMD_OK : DCMD_ERR);
45020c794b3Sgavinm 
45120c794b3Sgavinm 
45220c794b3Sgavinm 		if (mdb_getopts(argc, argv,
45320c794b3Sgavinm 		    'c', MDB_OPT_STR, &p,
45420c794b3Sgavinm 		    NULL) != argc)
45520c794b3Sgavinm 			return (DCMD_USAGE);
45620c794b3Sgavinm 
45720c794b3Sgavinm 		if ((len = strlen(p)) == 0) {
45820c794b3Sgavinm 			return (DCMD_USAGE);
45920c794b3Sgavinm 		} else {
46020c794b3Sgavinm 			buf = mdb_alloc(len + 1, UM_SLEEP);
46120c794b3Sgavinm 			strcpy(buf, p);
46220c794b3Sgavinm 		}
46320c794b3Sgavinm 
46420c794b3Sgavinm 		cb.mod_cpuid = cb.mod_chipid = cb.mod_coreid =
46520c794b3Sgavinm 		    cb.mod_strandid = -1;
46620c794b3Sgavinm 
46720c794b3Sgavinm 		if ((p = strchr(buf, '/')) == NULL) {
46820c794b3Sgavinm 			/* Native cpuid */
46920c794b3Sgavinm 			cb.mod_cpuid = (int)mdb_strtoull(buf);
47020c794b3Sgavinm 		} else {
47120c794b3Sgavinm 			/* Comma-separated triplet chip,core,strand. */
47220c794b3Sgavinm 			char *q = buf;
47320c794b3Sgavinm 
47420c794b3Sgavinm 			*p = '\0';
47520c794b3Sgavinm 			cb.mod_chipid = (int)mdb_strtoull(q);
47620c794b3Sgavinm 
47720c794b3Sgavinm 			if ((q = p + 1) >= buf + len ||
47820c794b3Sgavinm 			    (p = strchr(q, '/')) == NULL) {
47920c794b3Sgavinm 				mdb_free(buf, len);
48020c794b3Sgavinm 				return (DCMD_USAGE);
48120c794b3Sgavinm 			}
48220c794b3Sgavinm 
48320c794b3Sgavinm 			*p = '\0';
48420c794b3Sgavinm 			cb.mod_coreid = (int)mdb_strtoull(q);
48520c794b3Sgavinm 
48620c794b3Sgavinm 			if ((q = p + 1) >= buf + len) {
48720c794b3Sgavinm 				mdb_free(buf, len);
48820c794b3Sgavinm 				return (DCMD_USAGE);
48920c794b3Sgavinm 			}
49020c794b3Sgavinm 
49120c794b3Sgavinm 			cb.mod_strandid = (int)mdb_strtoull(q);
49220c794b3Sgavinm 		}
49320c794b3Sgavinm 
49420c794b3Sgavinm 		mdb_free(buf, len);
49520c794b3Sgavinm 
496*892ad162SToomas Soome 		cb.mod_hdladdr = 0;
49720c794b3Sgavinm 		if (mdb_walk("cmihdl", cmihdl_cb, &cb) == -1) {
49820c794b3Sgavinm 			mdb_warn("cmi_hdl walk failed\n");
49920c794b3Sgavinm 			return (DCMD_ERR);
50020c794b3Sgavinm 		}
50120c794b3Sgavinm 
502*892ad162SToomas Soome 		if (cb.mod_hdladdr == 0) {
50320c794b3Sgavinm 			if (cb.mod_cpuid != -1) {
50420c794b3Sgavinm 				mdb_warn("No handle found for cpuid %d\n",
50520c794b3Sgavinm 				    cb.mod_cpuid);
50620c794b3Sgavinm 			} else {
50720c794b3Sgavinm 
50820c794b3Sgavinm 				mdb_warn("No handle found for chip %d "
50920c794b3Sgavinm 				    "core %d strand %d\n", cb.mod_chipid,
51020c794b3Sgavinm 				    cb.mod_coreid, cb.mod_strandid);
51120c794b3Sgavinm 			}
51220c794b3Sgavinm 			return (DCMD_ERR);
51320c794b3Sgavinm 		}
51420c794b3Sgavinm 
51520c794b3Sgavinm 		addr = cb.mod_hdladdr;
51620c794b3Sgavinm 	}
51720c794b3Sgavinm 
51820c794b3Sgavinm 	if (DCMD_HDRSPEC(flags)) {
51920c794b3Sgavinm 		char ul[] = "----------------------------";
52020c794b3Sgavinm 		char *p = ul + sizeof (ul) - 1;
52120c794b3Sgavinm 
52220c794b3Sgavinm 		mdb_printf(HDRFMT HDRFMT,
523728f047cSAdrian Frost 		    "HANDLE", "REF", "CPU", "CH/CR/ST", "CMT", "MC",
52420c794b3Sgavinm 		    "MODULE", "MODEL-SPECIFIC",
525728f047cSAdrian Frost 		    p - 16,  p - 3, p - 3, p - 8, p - 3, p - 2, p - 13, p - 24);
52620c794b3Sgavinm 	}
52720c794b3Sgavinm 
52820c794b3Sgavinm 	hdl = mdb_alloc(sizeof (cmi_hdl_impl_t), UM_SLEEP);
52920c794b3Sgavinm 
53020c794b3Sgavinm 	if (mdb_vread(hdl, sizeof (cmi_hdl_impl_t), addr) !=
53120c794b3Sgavinm 	    sizeof (cmi_hdl_impl_t)) {
53220c794b3Sgavinm 		mdb_free(hdl, sizeof (cmi_hdl_impl_t));
53320c794b3Sgavinm 		mdb_warn("Read of cmi handle at 0x%p failed", addr);
53420c794b3Sgavinm 		return (DCMD_ERR);
53520c794b3Sgavinm 	}
53620c794b3Sgavinm 
53720c794b3Sgavinm 	if (!cmihdl_disp(addr, hdl)) {
53820c794b3Sgavinm 		mdb_free(hdl, sizeof (cmi_hdl_impl_t));
53920c794b3Sgavinm 		return (DCMD_ERR);
54020c794b3Sgavinm 	}
54120c794b3Sgavinm 
54220c794b3Sgavinm 	mdb_free(hdl, sizeof (cmi_hdl_impl_t));
54320c794b3Sgavinm 
54420c794b3Sgavinm 	return (DCMD_OK);
54520c794b3Sgavinm }
54620c794b3Sgavinm 
54720c794b3Sgavinm /*ARGSUSED*/
54820c794b3Sgavinm static int
gcpu_mpt_dump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)54920c794b3Sgavinm gcpu_mpt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
55020c794b3Sgavinm {
55120c794b3Sgavinm 	static const char *const whatstrs[] = {
552e4b86885SCheng Sean Ye 		"ntv-cyc-poll",		/* GCPU_MPT_WHAT_CYC_ERR */
553e4b86885SCheng Sean Ye 		"poll-poked",		/* GCPU_MPT_WHAT_POKE_ERR */
554e4b86885SCheng Sean Ye 		"unfaulting",		/* GCPU_MPT_WHAT_UNFAULTING */
555e4b86885SCheng Sean Ye 		"#MC",			/* GCPU_MPT_WHAT_MC_ERR */
556e4b86885SCheng Sean Ye 		"CMCI-int",		/* GCPU_MPT_WHAT_CMCI_ERR */
557e4b86885SCheng Sean Ye 		"xpv-virq-nrec",	/* GCPU_MPT_WHAT_XPV_VIRQ */
558e4b86885SCheng Sean Ye 		"xpv-virq-lgout",	/* GCPU_MPT_WHAT_XPV_VIRQ_LOGOUT */
55920c794b3Sgavinm 	};
56020c794b3Sgavinm 
561e4b86885SCheng Sean Ye 	gcpu_poll_trace_t mpt;
56220c794b3Sgavinm 	const char *what;
56320c794b3Sgavinm 
56420c794b3Sgavinm 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
56520c794b3Sgavinm 		return (DCMD_USAGE);
56620c794b3Sgavinm 
56720c794b3Sgavinm 	if (mdb_vread(&mpt, sizeof (mpt), addr) != sizeof (mpt)) {
568e4b86885SCheng Sean Ye 		mdb_warn("failed to read gcpu_poll_trace_t at 0x%p", addr);
56920c794b3Sgavinm 		return (DCMD_ERR);
57020c794b3Sgavinm 	}
57120c794b3Sgavinm 
57220c794b3Sgavinm 	if (DCMD_HDRSPEC(flags)) {
573e4b86885SCheng Sean Ye 		mdb_printf("%<u>%?s%</u> %<u>%?s%</u> %<u>%15s%</u> "
57420c794b3Sgavinm 		    "%<u>%4s%</u>\n", "ADDR", "WHEN", "WHAT", "NERR");
57520c794b3Sgavinm 	}
57620c794b3Sgavinm 
57720c794b3Sgavinm 	if (mpt.mpt_what < sizeof (whatstrs) / sizeof (char *))
57820c794b3Sgavinm 		what = whatstrs[mpt.mpt_what];
57920c794b3Sgavinm 	else
58020c794b3Sgavinm 		what = "???";
58120c794b3Sgavinm 
582e4b86885SCheng Sean Ye 	mdb_printf("%?p %?p %15s %4u\n", addr, mpt.mpt_when, what,
58320c794b3Sgavinm 	    mpt.mpt_nerr);
58420c794b3Sgavinm 
58520c794b3Sgavinm 	return (DCMD_OK);
58620c794b3Sgavinm }
58720c794b3Sgavinm 
58820c794b3Sgavinm typedef struct mptwalk_data {
58920c794b3Sgavinm 	uintptr_t mw_traceaddr;
590e4b86885SCheng Sean Ye 	gcpu_poll_trace_t *mw_trace;
59120c794b3Sgavinm 	size_t mw_tracesz;
59220c794b3Sgavinm 	uint_t mw_tracenent;
59320c794b3Sgavinm 	uint_t mw_curtrace;
59420c794b3Sgavinm } mptwalk_data_t;
59520c794b3Sgavinm 
59620c794b3Sgavinm static int
gcpu_mptwalk_init(mdb_walk_state_t * wsp)59720c794b3Sgavinm gcpu_mptwalk_init(mdb_walk_state_t *wsp)
59820c794b3Sgavinm {
599e4b86885SCheng Sean Ye 	gcpu_poll_trace_t *mpt;
60020c794b3Sgavinm 	mptwalk_data_t *mw;
60120c794b3Sgavinm 	GElf_Sym sym;
60220c794b3Sgavinm 	uint_t nent, i;
60320c794b3Sgavinm 	hrtime_t latest;
60420c794b3Sgavinm 
605*892ad162SToomas Soome 	if (wsp->walk_addr == 0) {
60620c794b3Sgavinm 		mdb_warn("the address of a poll trace array must be "
60720c794b3Sgavinm 		    "specified\n");
60820c794b3Sgavinm 		return (WALK_ERR);
60920c794b3Sgavinm 	}
61020c794b3Sgavinm 
611e4b86885SCheng Sean Ye 	if (mdb_lookup_by_name("gcpu_poll_trace_nent", &sym) < 0 ||
61220c794b3Sgavinm 	    sym.st_size != sizeof (uint_t) || mdb_vread(&nent, sizeof (uint_t),
61320c794b3Sgavinm 	    sym.st_value) != sizeof (uint_t)) {
614e4b86885SCheng Sean Ye 		mdb_warn("failed to read gcpu_poll_trace_nent from kernel");
61520c794b3Sgavinm 		return (WALK_ERR);
61620c794b3Sgavinm 	}
61720c794b3Sgavinm 
61820c794b3Sgavinm 	mw = mdb_alloc(sizeof (mptwalk_data_t), UM_SLEEP);
61920c794b3Sgavinm 	mw->mw_traceaddr = wsp->walk_addr;
62020c794b3Sgavinm 	mw->mw_tracenent = nent;
621e4b86885SCheng Sean Ye 	mw->mw_tracesz = nent * sizeof (gcpu_poll_trace_t);
62220c794b3Sgavinm 	mw->mw_trace = mdb_alloc(mw->mw_tracesz, UM_SLEEP);
62320c794b3Sgavinm 
62420c794b3Sgavinm 	if (mdb_vread(mw->mw_trace, mw->mw_tracesz, wsp->walk_addr) !=
62520c794b3Sgavinm 	    mw->mw_tracesz) {
62620c794b3Sgavinm 		mdb_free(mw->mw_trace, mw->mw_tracesz);
62720c794b3Sgavinm 		mdb_free(mw, sizeof (mptwalk_data_t));
62820c794b3Sgavinm 		mdb_warn("failed to read poll trace array from kernel");
62920c794b3Sgavinm 		return (WALK_ERR);
63020c794b3Sgavinm 	}
63120c794b3Sgavinm 
63220c794b3Sgavinm 	latest = 0;
63320c794b3Sgavinm 	mw->mw_curtrace = 0;
63420c794b3Sgavinm 	for (mpt = mw->mw_trace, i = 0; i < mw->mw_tracenent; i++, mpt++) {
63520c794b3Sgavinm 		if (mpt->mpt_when > latest) {
63620c794b3Sgavinm 			latest = mpt->mpt_when;
63720c794b3Sgavinm 			mw->mw_curtrace = i;
63820c794b3Sgavinm 		}
63920c794b3Sgavinm 	}
64020c794b3Sgavinm 
64120c794b3Sgavinm 	if (latest == 0) {
64220c794b3Sgavinm 		mdb_free(mw->mw_trace, mw->mw_tracesz);
64320c794b3Sgavinm 		mdb_free(mw, sizeof (mptwalk_data_t));
64420c794b3Sgavinm 		return (WALK_DONE); /* trace array is empty */
64520c794b3Sgavinm 	}
64620c794b3Sgavinm 
64720c794b3Sgavinm 	wsp->walk_data = mw;
64820c794b3Sgavinm 
64920c794b3Sgavinm 	return (WALK_NEXT);
65020c794b3Sgavinm }
65120c794b3Sgavinm 
65220c794b3Sgavinm static int
gcpu_mptwalk_step(mdb_walk_state_t * wsp)65320c794b3Sgavinm gcpu_mptwalk_step(mdb_walk_state_t *wsp)
65420c794b3Sgavinm {
65520c794b3Sgavinm 	mptwalk_data_t *mw = wsp->walk_data;
656e4b86885SCheng Sean Ye 	gcpu_poll_trace_t *thismpt, *prevmpt;
65720c794b3Sgavinm 	int prev, rv;
65820c794b3Sgavinm 
65920c794b3Sgavinm 	thismpt = &mw->mw_trace[mw->mw_curtrace];
66020c794b3Sgavinm 
66120c794b3Sgavinm 	rv = wsp->walk_callback(mw->mw_traceaddr + (mw->mw_curtrace *
662e4b86885SCheng Sean Ye 	    sizeof (gcpu_poll_trace_t)), thismpt, wsp->walk_cbdata);
66320c794b3Sgavinm 
66420c794b3Sgavinm 	if (rv != WALK_NEXT)
66520c794b3Sgavinm 		return (rv);
66620c794b3Sgavinm 
66720c794b3Sgavinm 	prev = (mw->mw_curtrace - 1) % mw->mw_tracenent;
66820c794b3Sgavinm 	prevmpt = &mw->mw_trace[prev];
66920c794b3Sgavinm 
67020c794b3Sgavinm 	if (prevmpt->mpt_when == 0 || prevmpt->mpt_when > thismpt->mpt_when)
67120c794b3Sgavinm 		return (WALK_DONE);
67220c794b3Sgavinm 
67320c794b3Sgavinm 	mw->mw_curtrace = prev;
67420c794b3Sgavinm 
67520c794b3Sgavinm 	return (WALK_NEXT);
67620c794b3Sgavinm }
67720c794b3Sgavinm 
67820c794b3Sgavinm static void
gcpu_mptwalk_fini(mdb_walk_state_t * wsp)67920c794b3Sgavinm gcpu_mptwalk_fini(mdb_walk_state_t *wsp)
68020c794b3Sgavinm {
68120c794b3Sgavinm 	mptwalk_data_t *mw = wsp->walk_data;
68220c794b3Sgavinm 
68320c794b3Sgavinm 	mdb_free(mw->mw_trace, mw->mw_tracesz);
68420c794b3Sgavinm 	mdb_free(mw, sizeof (mptwalk_data_t));
68520c794b3Sgavinm }
68620c794b3Sgavinm 
68720c794b3Sgavinm static const mdb_dcmd_t dcmds[] = {
68820c794b3Sgavinm 	{ "cmihdl", ": -c <cpuid>|<chip,core,strand> ",
68920c794b3Sgavinm 	    "dump a cmi_handle_t", cmihdl },
69020c794b3Sgavinm 	{ "gcpu_poll_trace", ":", "dump a poll trace buffer", gcpu_mpt_dump },
69120c794b3Sgavinm 	{ NULL }
69220c794b3Sgavinm };
69320c794b3Sgavinm 
69420c794b3Sgavinm static const mdb_walker_t walkers[] = {
69520c794b3Sgavinm 	{ "cmihdl", "walks cpu module interface handle list",
69620c794b3Sgavinm 	    cmih_walk_init, cmih_walk_step, cmih_walk_fini, NULL },
69720c794b3Sgavinm 	{ "gcpu_poll_trace", "walks poll trace buffers in reverse "
69820c794b3Sgavinm 	    "chronological order", gcpu_mptwalk_init, gcpu_mptwalk_step,
69920c794b3Sgavinm 	    gcpu_mptwalk_fini, NULL },
70020c794b3Sgavinm 	{ NULL }
70120c794b3Sgavinm };
70220c794b3Sgavinm 
70320c794b3Sgavinm static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
70420c794b3Sgavinm 
70520c794b3Sgavinm const mdb_modinfo_t *
_mdb_init(void)70620c794b3Sgavinm _mdb_init(void)
70720c794b3Sgavinm {
70820c794b3Sgavinm 	return (&modinfo);
70920c794b3Sgavinm }
710