17532SSean.Ye@Sun.COM /*
27532SSean.Ye@Sun.COM * CDDL HEADER START
37532SSean.Ye@Sun.COM *
47532SSean.Ye@Sun.COM * The contents of this file are subject to the terms of the
57532SSean.Ye@Sun.COM * Common Development and Distribution License (the "License").
67532SSean.Ye@Sun.COM * You may not use this file except in compliance with the License.
77532SSean.Ye@Sun.COM *
87532SSean.Ye@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97532SSean.Ye@Sun.COM * or http://www.opensolaris.org/os/licensing.
107532SSean.Ye@Sun.COM * See the License for the specific language governing permissions
117532SSean.Ye@Sun.COM * and limitations under the License.
127532SSean.Ye@Sun.COM *
137532SSean.Ye@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147532SSean.Ye@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157532SSean.Ye@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167532SSean.Ye@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177532SSean.Ye@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187532SSean.Ye@Sun.COM *
197532SSean.Ye@Sun.COM * CDDL HEADER END
207532SSean.Ye@Sun.COM */
217532SSean.Ye@Sun.COM
227532SSean.Ye@Sun.COM /*
23*12261SVuong.Nguyen@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
247532SSean.Ye@Sun.COM */
257532SSean.Ye@Sun.COM
267532SSean.Ye@Sun.COM #include <mdb/mdb_modapi.h>
277532SSean.Ye@Sun.COM #include <generic_cpu/gcpu.h>
287532SSean.Ye@Sun.COM #include <sys/cpu_module_impl.h>
297532SSean.Ye@Sun.COM #include <sys/cpu_module_ms_impl.h>
307532SSean.Ye@Sun.COM
317532SSean.Ye@Sun.COM typedef struct cmi_hdl_impl {
327532SSean.Ye@Sun.COM enum cmi_hdl_class cmih_class; /* Handle nature */
337532SSean.Ye@Sun.COM struct cmi_hdl_ops *cmih_ops; /* Operations vector */
347532SSean.Ye@Sun.COM uint_t cmih_chipid; /* Chipid of cpu resource */
3510947SSrihari.Venkatesan@Sun.COM uint_t cmih_procnodeid; /* Nodeid of cpu resource */
367532SSean.Ye@Sun.COM uint_t cmih_coreid; /* Core within die */
377532SSean.Ye@Sun.COM uint_t cmih_strandid; /* Thread within core */
3811013SSrihari.Venkatesan@Sun.COM uint_t cmih_procnodes_per_pkg; /* Nodes in a processor */
397532SSean.Ye@Sun.COM boolean_t cmih_mstrand; /* cores are multithreaded */
407532SSean.Ye@Sun.COM volatile uint32_t *cmih_refcntp; /* Reference count pointer */
417532SSean.Ye@Sun.COM uint64_t cmih_msrsrc; /* MSR data source flags */
427532SSean.Ye@Sun.COM void *cmih_hdlpriv; /* cmi_hw.c private data */
437532SSean.Ye@Sun.COM void *cmih_spec; /* cmi_hdl_{set,get}_specific */
447532SSean.Ye@Sun.COM void *cmih_cmi; /* cpu mod control structure */
457532SSean.Ye@Sun.COM void *cmih_cmidata; /* cpu mod private data */
467532SSean.Ye@Sun.COM const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */
477532SSean.Ye@Sun.COM void *cmih_mcdata; /* Memory-controller data */
487532SSean.Ye@Sun.COM uint64_t cmih_flags;
4910942STom.Pothier@Sun.COM uint16_t cmih_smbiosid; /* SMBIOS Type 4 struct ID */
5010942STom.Pothier@Sun.COM uint_t cmih_smb_chipid; /* smbios chipid */
5110942STom.Pothier@Sun.COM nvlist_t *cmih_smb_bboard; /* smbios bboard */
527532SSean.Ye@Sun.COM } cmi_hdl_impl_t;
537532SSean.Ye@Sun.COM
549090SVuong.Nguyen@Sun.COM typedef struct cmi_hdl_ent {
557532SSean.Ye@Sun.COM volatile uint32_t cmae_refcnt;
567532SSean.Ye@Sun.COM cmi_hdl_impl_t *cmae_hdlp;
579090SVuong.Nguyen@Sun.COM } cmi_hdl_ent_t;
587532SSean.Ye@Sun.COM
597532SSean.Ye@Sun.COM typedef struct cmi {
607532SSean.Ye@Sun.COM struct cmi *cmi_next;
617532SSean.Ye@Sun.COM struct cmi *cmi_prev;
627532SSean.Ye@Sun.COM const cmi_ops_t *cmi_ops;
637532SSean.Ye@Sun.COM struct modctl *cmi_modp;
647532SSean.Ye@Sun.COM uint_t cmi_refcnt;
657532SSean.Ye@Sun.COM } cmi_t;
667532SSean.Ye@Sun.COM
677532SSean.Ye@Sun.COM typedef struct cms {
687532SSean.Ye@Sun.COM struct cms *cms_next;
697532SSean.Ye@Sun.COM struct cms *cms_prev;
707532SSean.Ye@Sun.COM const cms_ops_t *cms_ops;
717532SSean.Ye@Sun.COM struct modctl *cms_modp;
727532SSean.Ye@Sun.COM uint_t cms_refcnt;
737532SSean.Ye@Sun.COM } cms_t;
747532SSean.Ye@Sun.COM
757532SSean.Ye@Sun.COM struct cms_ctl {
767532SSean.Ye@Sun.COM cms_t *cs_cms;
777532SSean.Ye@Sun.COM void *cs_cmsdata;
787532SSean.Ye@Sun.COM };
797532SSean.Ye@Sun.COM
809090SVuong.Nguyen@Sun.COM #define CMI_MAX_CHIPID_NBITS 6 /* max chipid of 63 */
819090SVuong.Nguyen@Sun.COM
829090SVuong.Nguyen@Sun.COM #define CMI_MAX_CHIPID ((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
83*12261SVuong.Nguyen@Sun.COM #define CMI_MAX_CORES_PER_CHIP(cbits) (1 << (cbits))
84*12261SVuong.Nguyen@Sun.COM #define CMI_MAX_COREID(cbits) ((1 << (cbits)) - 1)
85*12261SVuong.Nguyen@Sun.COM #define CMI_MAX_STRANDS_PER_CORE(sbits) (1 << (sbits))
86*12261SVuong.Nguyen@Sun.COM #define CMI_MAX_STRANDID(sbits) ((1 << (sbits)) - 1)
87*12261SVuong.Nguyen@Sun.COM #define CMI_MAX_STRANDS_PER_CHIP(cbits, sbits) \
88*12261SVuong.Nguyen@Sun.COM (CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
899090SVuong.Nguyen@Sun.COM
909090SVuong.Nguyen@Sun.COM #define CMI_CHIPID_ARR_SZ (1 << CMI_MAX_CHIPID_NBITS)
917532SSean.Ye@Sun.COM
927532SSean.Ye@Sun.COM struct cmih_walk_state {
939090SVuong.Nguyen@Sun.COM int chipid, coreid, strandid; /* currently visited cpu */
949090SVuong.Nguyen@Sun.COM cmi_hdl_ent_t *chip_tab[CMI_CHIPID_ARR_SZ];
95*12261SVuong.Nguyen@Sun.COM uint_t core_nbits;
96*12261SVuong.Nguyen@Sun.COM uint_t strand_nbits;
977532SSean.Ye@Sun.COM };
987532SSean.Ye@Sun.COM
999090SVuong.Nguyen@Sun.COM /*
1009090SVuong.Nguyen@Sun.COM * Advance the <chipid,coreid,strandid> tuple to the next strand entry
1019090SVuong.Nguyen@Sun.COM * Return true upon sucessful result. Otherwise return false if already reach
1029090SVuong.Nguyen@Sun.COM * the highest strand.
1039090SVuong.Nguyen@Sun.COM */
1049090SVuong.Nguyen@Sun.COM static boolean_t
cmih_ent_next(struct cmih_walk_state * wsp)1059090SVuong.Nguyen@Sun.COM cmih_ent_next(struct cmih_walk_state *wsp)
1069090SVuong.Nguyen@Sun.COM {
1079090SVuong.Nguyen@Sun.COM uint_t carry = 0;
1089090SVuong.Nguyen@Sun.COM
1099090SVuong.Nguyen@Sun.COM /* Check for end of the table */
110*12261SVuong.Nguyen@Sun.COM if (wsp->chipid >= CMI_MAX_CHIPID &&
111*12261SVuong.Nguyen@Sun.COM wsp->coreid >= CMI_MAX_COREID(wsp->core_nbits) &&
112*12261SVuong.Nguyen@Sun.COM wsp->strandid >= CMI_MAX_STRANDID(wsp->strand_nbits))
1139090SVuong.Nguyen@Sun.COM return (B_FALSE);
1149090SVuong.Nguyen@Sun.COM
1159090SVuong.Nguyen@Sun.COM /* increment the strand id */
1169090SVuong.Nguyen@Sun.COM wsp->strandid++;
117*12261SVuong.Nguyen@Sun.COM carry = wsp->strandid >> wsp->strand_nbits;
118*12261SVuong.Nguyen@Sun.COM wsp->strandid = wsp->strandid & CMI_MAX_STRANDID(wsp->strand_nbits);
1199090SVuong.Nguyen@Sun.COM if (carry == 0)
1209090SVuong.Nguyen@Sun.COM return (B_TRUE);
1219090SVuong.Nguyen@Sun.COM
1229090SVuong.Nguyen@Sun.COM /* increment the core id */
1239090SVuong.Nguyen@Sun.COM wsp->coreid++;
124*12261SVuong.Nguyen@Sun.COM carry = wsp->coreid >> wsp->core_nbits;
125*12261SVuong.Nguyen@Sun.COM wsp->coreid = wsp->coreid & CMI_MAX_COREID(wsp->core_nbits);
1269090SVuong.Nguyen@Sun.COM if (carry == 0)
1279090SVuong.Nguyen@Sun.COM return (B_TRUE);
1289090SVuong.Nguyen@Sun.COM
1299090SVuong.Nguyen@Sun.COM /* increment the chip id */
1309090SVuong.Nguyen@Sun.COM wsp->chipid = ++wsp->chipid & (CMI_MAX_CHIPID);
1319090SVuong.Nguyen@Sun.COM
1329090SVuong.Nguyen@Sun.COM return (B_TRUE);
1339090SVuong.Nguyen@Sun.COM }
1349090SVuong.Nguyen@Sun.COM
1359090SVuong.Nguyen@Sun.COM /*
136*12261SVuong.Nguyen@Sun.COM * Lookup for the hdl entry of a given <chip,core,strand> tuple
1379090SVuong.Nguyen@Sun.COM */
1389090SVuong.Nguyen@Sun.COM static cmi_hdl_ent_t *
cmih_ent_lookup(struct cmih_walk_state * wsp)1399090SVuong.Nguyen@Sun.COM cmih_ent_lookup(struct cmih_walk_state *wsp)
1409090SVuong.Nguyen@Sun.COM {
1419090SVuong.Nguyen@Sun.COM if (wsp == NULL || wsp->chip_tab[wsp->chipid] == NULL)
1429090SVuong.Nguyen@Sun.COM return (NULL); /* chip is not present */
1439090SVuong.Nguyen@Sun.COM
1449090SVuong.Nguyen@Sun.COM return (wsp->chip_tab[wsp->chipid] +
145*12261SVuong.Nguyen@Sun.COM (((wsp->coreid & CMI_MAX_COREID(wsp->core_nbits)) <<
146*12261SVuong.Nguyen@Sun.COM wsp->strand_nbits) |
147*12261SVuong.Nguyen@Sun.COM ((wsp->strandid) & CMI_MAX_STRANDID(wsp->strand_nbits))));
1489090SVuong.Nguyen@Sun.COM }
1499090SVuong.Nguyen@Sun.COM
1509090SVuong.Nguyen@Sun.COM /* forward decls */
1519090SVuong.Nguyen@Sun.COM static void
1529090SVuong.Nguyen@Sun.COM cmih_walk_fini(mdb_walk_state_t *wsp);
1539090SVuong.Nguyen@Sun.COM
1547532SSean.Ye@Sun.COM static int
cmih_walk_init(mdb_walk_state_t * wsp)1557532SSean.Ye@Sun.COM cmih_walk_init(mdb_walk_state_t *wsp)
1567532SSean.Ye@Sun.COM {
1579090SVuong.Nguyen@Sun.COM int i;
1589090SVuong.Nguyen@Sun.COM ssize_t sz;
1597532SSean.Ye@Sun.COM struct cmih_walk_state *awsp;
1609090SVuong.Nguyen@Sun.COM void *pg;
1619090SVuong.Nguyen@Sun.COM cmi_hdl_ent_t *ent;
1627532SSean.Ye@Sun.COM
1637532SSean.Ye@Sun.COM if (wsp->walk_addr != NULL) {
1647532SSean.Ye@Sun.COM mdb_warn("cmihdl is a global walker\n");
1657532SSean.Ye@Sun.COM return (WALK_ERR);
1667532SSean.Ye@Sun.COM }
1677532SSean.Ye@Sun.COM
1687532SSean.Ye@Sun.COM wsp->walk_data = awsp =
1697532SSean.Ye@Sun.COM mdb_zalloc(sizeof (struct cmih_walk_state), UM_SLEEP);
1707532SSean.Ye@Sun.COM
171*12261SVuong.Nguyen@Sun.COM /* read the number of core bits and strand bits */
172*12261SVuong.Nguyen@Sun.COM if (mdb_readvar(&awsp->core_nbits, "cmi_core_nbits") == -1) {
173*12261SVuong.Nguyen@Sun.COM mdb_warn("read of cmi_core_nbits failed");
174*12261SVuong.Nguyen@Sun.COM mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
175*12261SVuong.Nguyen@Sun.COM wsp->walk_data = NULL;
176*12261SVuong.Nguyen@Sun.COM return (WALK_ERR);
177*12261SVuong.Nguyen@Sun.COM }
178*12261SVuong.Nguyen@Sun.COM if (mdb_readvar(&awsp->strand_nbits, "cmi_strand_nbits") == -1) {
179*12261SVuong.Nguyen@Sun.COM mdb_warn("read of cmi_strand_nbits failed");
180*12261SVuong.Nguyen@Sun.COM mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
181*12261SVuong.Nguyen@Sun.COM wsp->walk_data = NULL;
182*12261SVuong.Nguyen@Sun.COM return (WALK_ERR);
183*12261SVuong.Nguyen@Sun.COM }
184*12261SVuong.Nguyen@Sun.COM
1859090SVuong.Nguyen@Sun.COM /* table of chipid entries */
1869090SVuong.Nguyen@Sun.COM if ((sz = mdb_readvar(&awsp->chip_tab, "cmi_chip_tab")) == -1) {
1879090SVuong.Nguyen@Sun.COM mdb_warn("read of cmi_chip_tab failed");
1889090SVuong.Nguyen@Sun.COM mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1899090SVuong.Nguyen@Sun.COM wsp->walk_data = NULL;
1909090SVuong.Nguyen@Sun.COM return (WALK_ERR);
1919090SVuong.Nguyen@Sun.COM } else if (sz < sizeof (awsp->chip_tab)) {
1929090SVuong.Nguyen@Sun.COM mdb_warn("Unexpected cmi_chip_tab size (exp=%ld, actual=%ld)",
1939090SVuong.Nguyen@Sun.COM sizeof (awsp->chip_tab), sz);
1949090SVuong.Nguyen@Sun.COM mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
1959090SVuong.Nguyen@Sun.COM wsp->walk_data = NULL;
1967532SSean.Ye@Sun.COM return (WALK_ERR);
1977532SSean.Ye@Sun.COM }
1987532SSean.Ye@Sun.COM
1999090SVuong.Nguyen@Sun.COM /* read the per-chip table that contains all strands of the chip */
200*12261SVuong.Nguyen@Sun.COM sz = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits, awsp->strand_nbits) *
201*12261SVuong.Nguyen@Sun.COM sizeof (cmi_hdl_ent_t);
2029090SVuong.Nguyen@Sun.COM for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
2039090SVuong.Nguyen@Sun.COM if (awsp->chip_tab[i] == NULL)
2049090SVuong.Nguyen@Sun.COM continue; /* this chip(i) is not present */
2059090SVuong.Nguyen@Sun.COM pg = mdb_alloc(sz, UM_SLEEP);
2069090SVuong.Nguyen@Sun.COM if (mdb_vread(pg, sz, (uintptr_t)awsp->chip_tab[i]) != sz) {
2079090SVuong.Nguyen@Sun.COM mdb_warn("read of cmi_hdl(%i) array at 0x%p failed",
2089090SVuong.Nguyen@Sun.COM i, awsp->chip_tab[i]);
2099090SVuong.Nguyen@Sun.COM mdb_free(pg, sz);
2109090SVuong.Nguyen@Sun.COM cmih_walk_fini(wsp);
2119090SVuong.Nguyen@Sun.COM return (WALK_ERR);
2129090SVuong.Nguyen@Sun.COM }
2139090SVuong.Nguyen@Sun.COM awsp->chip_tab[i] = pg;
2149090SVuong.Nguyen@Sun.COM }
2159090SVuong.Nguyen@Sun.COM
2169090SVuong.Nguyen@Sun.COM /* Look up the hdl of the first strand <0,0,0> */
2179090SVuong.Nguyen@Sun.COM wsp->walk_addr = NULL;
2189090SVuong.Nguyen@Sun.COM if ((ent = cmih_ent_lookup(awsp)) != NULL)
2199090SVuong.Nguyen@Sun.COM wsp->walk_addr = (uintptr_t)ent->cmae_hdlp;
2207532SSean.Ye@Sun.COM
2217532SSean.Ye@Sun.COM return (WALK_NEXT);
2227532SSean.Ye@Sun.COM }
2237532SSean.Ye@Sun.COM
2247532SSean.Ye@Sun.COM static int
cmih_walk_step(mdb_walk_state_t * wsp)2257532SSean.Ye@Sun.COM cmih_walk_step(mdb_walk_state_t *wsp)
2267532SSean.Ye@Sun.COM {
2277532SSean.Ye@Sun.COM struct cmih_walk_state *awsp = wsp->walk_data;
2289090SVuong.Nguyen@Sun.COM uintptr_t addr = NULL;
2297532SSean.Ye@Sun.COM cmi_hdl_impl_t hdl;
2309090SVuong.Nguyen@Sun.COM cmi_hdl_ent_t *ent;
2317532SSean.Ye@Sun.COM int rv;
2327532SSean.Ye@Sun.COM
2339090SVuong.Nguyen@Sun.COM if ((ent = cmih_ent_lookup(awsp)) != NULL)
2349090SVuong.Nguyen@Sun.COM addr = (uintptr_t)ent->cmae_hdlp;
2357532SSean.Ye@Sun.COM if (wsp->walk_addr == NULL || addr == NULL)
2369090SVuong.Nguyen@Sun.COM return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
2377532SSean.Ye@Sun.COM
2387532SSean.Ye@Sun.COM if (mdb_vread(&hdl, sizeof (hdl), addr) != sizeof (hdl)) {
2397532SSean.Ye@Sun.COM mdb_warn("read of handle at 0x%p failed", addr);
2407532SSean.Ye@Sun.COM return (WALK_DONE);
2417532SSean.Ye@Sun.COM }
2427532SSean.Ye@Sun.COM
2437532SSean.Ye@Sun.COM if ((rv = wsp->walk_callback(addr, (void *)&hdl,
2447532SSean.Ye@Sun.COM wsp->walk_cbdata)) != WALK_NEXT)
2457532SSean.Ye@Sun.COM return (rv);
2467532SSean.Ye@Sun.COM
2479090SVuong.Nguyen@Sun.COM return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
2487532SSean.Ye@Sun.COM }
2497532SSean.Ye@Sun.COM
2507532SSean.Ye@Sun.COM static void
cmih_walk_fini(mdb_walk_state_t * wsp)2517532SSean.Ye@Sun.COM cmih_walk_fini(mdb_walk_state_t *wsp)
2527532SSean.Ye@Sun.COM {
2537532SSean.Ye@Sun.COM struct cmih_walk_state *awsp = wsp->walk_data;
2547532SSean.Ye@Sun.COM
2557532SSean.Ye@Sun.COM if (awsp != NULL) {
2569090SVuong.Nguyen@Sun.COM int i;
257*12261SVuong.Nguyen@Sun.COM int max_strands = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits,
258*12261SVuong.Nguyen@Sun.COM awsp->strand_nbits);
2599090SVuong.Nguyen@Sun.COM for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
2609090SVuong.Nguyen@Sun.COM /* free the per-chip table */
2619090SVuong.Nguyen@Sun.COM if (awsp->chip_tab[i] != NULL) {
2629090SVuong.Nguyen@Sun.COM mdb_free((void *)awsp->chip_tab[i],
263*12261SVuong.Nguyen@Sun.COM max_strands * sizeof (cmi_hdl_ent_t));
2649090SVuong.Nguyen@Sun.COM awsp->chip_tab[i] = NULL;
2659090SVuong.Nguyen@Sun.COM }
2669090SVuong.Nguyen@Sun.COM }
2677532SSean.Ye@Sun.COM mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
2689090SVuong.Nguyen@Sun.COM wsp->walk_data = NULL;
2697532SSean.Ye@Sun.COM }
2707532SSean.Ye@Sun.COM }
2717532SSean.Ye@Sun.COM
2727532SSean.Ye@Sun.COM struct cmihdl_cb {
2737532SSean.Ye@Sun.COM int mod_cpuid;
2747532SSean.Ye@Sun.COM int mod_chipid;
2757532SSean.Ye@Sun.COM int mod_coreid;
2767532SSean.Ye@Sun.COM int mod_strandid;
2777532SSean.Ye@Sun.COM uintptr_t mod_hdladdr;
2787532SSean.Ye@Sun.COM };
2797532SSean.Ye@Sun.COM
2807532SSean.Ye@Sun.COM static int
cmihdl_cb(uintptr_t addr,const void * arg,void * data)2817532SSean.Ye@Sun.COM cmihdl_cb(uintptr_t addr, const void *arg, void *data)
2827532SSean.Ye@Sun.COM {
2837532SSean.Ye@Sun.COM cmi_hdl_impl_t *hdl = (cmi_hdl_impl_t *)arg;
2847532SSean.Ye@Sun.COM struct cmihdl_cb *cbp = data;
2857532SSean.Ye@Sun.COM cpu_t *cp;
2867532SSean.Ye@Sun.COM int rv;
2877532SSean.Ye@Sun.COM
2887532SSean.Ye@Sun.COM if (cbp->mod_cpuid != -1) {
2897532SSean.Ye@Sun.COM cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
2907532SSean.Ye@Sun.COM if (mdb_vread(cp, sizeof (cpu_t),
2917532SSean.Ye@Sun.COM (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
2927532SSean.Ye@Sun.COM mdb_warn("Read of cpu_t at 0x%p failed",
2937532SSean.Ye@Sun.COM hdl->cmih_hdlpriv);
2947532SSean.Ye@Sun.COM mdb_free(cp, sizeof (cpu_t));
2957532SSean.Ye@Sun.COM return (WALK_ERR);
2967532SSean.Ye@Sun.COM }
2977532SSean.Ye@Sun.COM
2987532SSean.Ye@Sun.COM if (cp->cpu_id == cbp->mod_cpuid) {
2997532SSean.Ye@Sun.COM cbp->mod_hdladdr = addr;
3007532SSean.Ye@Sun.COM rv = WALK_DONE;
3017532SSean.Ye@Sun.COM } else {
3027532SSean.Ye@Sun.COM rv = WALK_NEXT;
3037532SSean.Ye@Sun.COM }
3047532SSean.Ye@Sun.COM
3057532SSean.Ye@Sun.COM mdb_free(cp, sizeof (cpu_t));
3067532SSean.Ye@Sun.COM return (rv);
3077532SSean.Ye@Sun.COM } else {
3087532SSean.Ye@Sun.COM if (hdl->cmih_chipid == cbp->mod_chipid &&
3097532SSean.Ye@Sun.COM hdl->cmih_coreid == cbp->mod_coreid &&
3107532SSean.Ye@Sun.COM hdl->cmih_strandid == cbp->mod_strandid) {
3117532SSean.Ye@Sun.COM cbp->mod_hdladdr = addr;
3127532SSean.Ye@Sun.COM return (WALK_DONE);
3137532SSean.Ye@Sun.COM } else {
3147532SSean.Ye@Sun.COM return (WALK_NEXT);
3157532SSean.Ye@Sun.COM }
3167532SSean.Ye@Sun.COM }
3177532SSean.Ye@Sun.COM }
3187532SSean.Ye@Sun.COM
3197532SSean.Ye@Sun.COM static int
cmihdl_disp(uintptr_t addr,cmi_hdl_impl_t * hdl)3207532SSean.Ye@Sun.COM cmihdl_disp(uintptr_t addr, cmi_hdl_impl_t *hdl)
3217532SSean.Ye@Sun.COM {
3227532SSean.Ye@Sun.COM struct cms_ctl cmsctl; /* 16 bytes max */
3237532SSean.Ye@Sun.COM struct modctl cmimodc, cmsmodc; /* 288 bytes max */
3247532SSean.Ye@Sun.COM cmi_t cmi; /* 40 bytes max */
3257532SSean.Ye@Sun.COM cms_t cms; /* 40 bytes max */
3267532SSean.Ye@Sun.COM cpu_t *cp;
3277532SSean.Ye@Sun.COM char cmimodnm[25], cmsmodnm[25]; /* 50 bytes */
3287532SSean.Ye@Sun.COM char cpuidstr[4], hwidstr[16];
3297532SSean.Ye@Sun.COM int native = hdl->cmih_class == CMI_HDL_NATIVE;
3307532SSean.Ye@Sun.COM uint32_t refcnt;
3317532SSean.Ye@Sun.COM
3327532SSean.Ye@Sun.COM cmimodnm[0] = cmsmodnm[0] = '-';
3337532SSean.Ye@Sun.COM cmimodnm[1] = cmsmodnm[1] = '\0';
3347532SSean.Ye@Sun.COM
3357532SSean.Ye@Sun.COM if (hdl->cmih_cmi != NULL) {
3367532SSean.Ye@Sun.COM if (mdb_vread(&cmi, sizeof (cmi_t),
3377532SSean.Ye@Sun.COM (uintptr_t)hdl->cmih_cmi) != sizeof (cmi)) {
3387532SSean.Ye@Sun.COM mdb_warn("Read of cmi_t at 0x%p failed",
3397532SSean.Ye@Sun.COM hdl->cmih_cmi);
3407532SSean.Ye@Sun.COM return (0);
3417532SSean.Ye@Sun.COM }
3427532SSean.Ye@Sun.COM
3437532SSean.Ye@Sun.COM if (cmi.cmi_modp != NULL) {
3447532SSean.Ye@Sun.COM if (mdb_vread(&cmimodc, sizeof (struct modctl),
3457532SSean.Ye@Sun.COM (uintptr_t)cmi.cmi_modp) != sizeof (cmimodc)) {
3467532SSean.Ye@Sun.COM mdb_warn("Read of modctl at 0x%p failed",
3477532SSean.Ye@Sun.COM cmi.cmi_modp);
3487532SSean.Ye@Sun.COM return (0);
3497532SSean.Ye@Sun.COM }
3507532SSean.Ye@Sun.COM
3517532SSean.Ye@Sun.COM if (mdb_readstr(cmimodnm, sizeof (cmimodnm),
3527532SSean.Ye@Sun.COM (uintptr_t)cmimodc.mod_modname) == -1) {
3537532SSean.Ye@Sun.COM mdb_warn("Read of cmi module name at 0x%p "
3547532SSean.Ye@Sun.COM "failed", cmimodc.mod_modname);
3557532SSean.Ye@Sun.COM return (0);
3567532SSean.Ye@Sun.COM }
3577532SSean.Ye@Sun.COM }
3587532SSean.Ye@Sun.COM }
3597532SSean.Ye@Sun.COM
3607532SSean.Ye@Sun.COM if (hdl->cmih_spec != NULL) {
3617532SSean.Ye@Sun.COM if (mdb_vread(&cmsctl, sizeof (struct cms_ctl),
3627532SSean.Ye@Sun.COM (uintptr_t)hdl->cmih_spec) != sizeof (cmsctl)) {
3637532SSean.Ye@Sun.COM mdb_warn("Read of struct cms_ctl at 0x%p failed",
3647532SSean.Ye@Sun.COM hdl->cmih_spec);
3657532SSean.Ye@Sun.COM return (0);
3667532SSean.Ye@Sun.COM }
3677532SSean.Ye@Sun.COM
3687532SSean.Ye@Sun.COM if (mdb_vread(&cms, sizeof (cms_t),
3697532SSean.Ye@Sun.COM (uintptr_t)cmsctl.cs_cms) != sizeof (cms)) {
3707532SSean.Ye@Sun.COM mdb_warn("Read of cms_t at 0x%p failed", cmsctl.cs_cms);
3717532SSean.Ye@Sun.COM return (0);
3727532SSean.Ye@Sun.COM }
3737532SSean.Ye@Sun.COM
3747532SSean.Ye@Sun.COM if (cms.cms_modp != NULL) {
3757532SSean.Ye@Sun.COM if (mdb_vread(&cmsmodc, sizeof (struct modctl),
3767532SSean.Ye@Sun.COM (uintptr_t)cms.cms_modp) != sizeof (cmsmodc)) {
3777532SSean.Ye@Sun.COM mdb_warn("Read of modctl at 0x%p failed",
3787532SSean.Ye@Sun.COM cms.cms_modp);
3797532SSean.Ye@Sun.COM return (0);
3807532SSean.Ye@Sun.COM }
3817532SSean.Ye@Sun.COM
3827532SSean.Ye@Sun.COM if (mdb_readstr(cmsmodnm, sizeof (cmsmodnm),
3837532SSean.Ye@Sun.COM (uintptr_t)cmsmodc.mod_modname) == -1) {
3847532SSean.Ye@Sun.COM mdb_warn("Read of cms module name at 0x%p "
3857532SSean.Ye@Sun.COM "failed", cmsmodc.mod_modname);
3867532SSean.Ye@Sun.COM return (0);
3877532SSean.Ye@Sun.COM }
3887532SSean.Ye@Sun.COM }
3897532SSean.Ye@Sun.COM }
3907532SSean.Ye@Sun.COM
3917532SSean.Ye@Sun.COM if (mdb_vread(&refcnt, sizeof (uint32_t),
3927532SSean.Ye@Sun.COM (uintptr_t)hdl->cmih_refcntp) != sizeof (uint32_t)) {
3937532SSean.Ye@Sun.COM mdb_warn("Read of reference count for hdl 0x%p failed", hdl);
3947532SSean.Ye@Sun.COM return (0);
3957532SSean.Ye@Sun.COM }
3967532SSean.Ye@Sun.COM
3977532SSean.Ye@Sun.COM if (native) {
3987532SSean.Ye@Sun.COM cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
3997532SSean.Ye@Sun.COM
4007532SSean.Ye@Sun.COM if (mdb_vread(cp, sizeof (cpu_t),
4017532SSean.Ye@Sun.COM (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
4027532SSean.Ye@Sun.COM mdb_free(cp, sizeof (cpu_t));
4037532SSean.Ye@Sun.COM mdb_warn("Read of cpu_t at 0x%p failed",
4047532SSean.Ye@Sun.COM hdl->cmih_hdlpriv);
4057532SSean.Ye@Sun.COM return (0);
4067532SSean.Ye@Sun.COM }
4077532SSean.Ye@Sun.COM }
4087532SSean.Ye@Sun.COM
4097532SSean.Ye@Sun.COM if (native) {
4107532SSean.Ye@Sun.COM (void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "%d",
4117532SSean.Ye@Sun.COM cp->cpu_id);
4127532SSean.Ye@Sun.COM } else {
4137532SSean.Ye@Sun.COM (void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "-");
4147532SSean.Ye@Sun.COM }
4157532SSean.Ye@Sun.COM
4167532SSean.Ye@Sun.COM (void) mdb_snprintf(hwidstr, sizeof (hwidstr), "%d/%d/%d",
4177532SSean.Ye@Sun.COM hdl->cmih_chipid, hdl->cmih_coreid, hdl->cmih_strandid);
4187532SSean.Ye@Sun.COM
4197532SSean.Ye@Sun.COM mdb_printf("%16lx %3d %3s %8s %3s %2s %-13s %-24s\n", addr,
4207532SSean.Ye@Sun.COM refcnt, cpuidstr, hwidstr, hdl->cmih_mstrand ? "M" : "S",
4217532SSean.Ye@Sun.COM hdl->cmih_mcops ? "Y" : "N", cmimodnm, cmsmodnm);
4227532SSean.Ye@Sun.COM
4237532SSean.Ye@Sun.COM if (native)
4247532SSean.Ye@Sun.COM mdb_free(cp, sizeof (cpu_t));
4257532SSean.Ye@Sun.COM
4267532SSean.Ye@Sun.COM return (1);
4277532SSean.Ye@Sun.COM }
4287532SSean.Ye@Sun.COM
4297532SSean.Ye@Sun.COM #define HDRFMT "%-16s %3s %3s %8s %3s %2s %-13s %-24s\n"
4307532SSean.Ye@Sun.COM
4317532SSean.Ye@Sun.COM static int
cmihdl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4327532SSean.Ye@Sun.COM cmihdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4337532SSean.Ye@Sun.COM {
4347532SSean.Ye@Sun.COM struct cmihdl_cb cb;
4357532SSean.Ye@Sun.COM cmi_hdl_impl_t *hdl;
4367532SSean.Ye@Sun.COM
4377532SSean.Ye@Sun.COM /*
4387532SSean.Ye@Sun.COM * If an address is given it must be that of a cmi handle.
4397532SSean.Ye@Sun.COM * Otherwise if the user has specified -c <cpuid> or
4407532SSean.Ye@Sun.COM * -c <chipid/coreid/strandid> we will lookup a matching handle.
4417532SSean.Ye@Sun.COM * Otherwise we'll walk and callback to this dcmd.
4427532SSean.Ye@Sun.COM */
4437532SSean.Ye@Sun.COM if (!(flags & DCMD_ADDRSPEC)) {
4447532SSean.Ye@Sun.COM char *p, *buf;
4457532SSean.Ye@Sun.COM int len;
4467532SSean.Ye@Sun.COM
4477532SSean.Ye@Sun.COM if (argc == 0)
4487532SSean.Ye@Sun.COM return (mdb_walk_dcmd("cmihdl", "cmihdl", argc,
4497532SSean.Ye@Sun.COM argv) == 0 ? DCMD_OK : DCMD_ERR);
4507532SSean.Ye@Sun.COM
4517532SSean.Ye@Sun.COM
4527532SSean.Ye@Sun.COM if (mdb_getopts(argc, argv,
4537532SSean.Ye@Sun.COM 'c', MDB_OPT_STR, &p,
4547532SSean.Ye@Sun.COM NULL) != argc)
4557532SSean.Ye@Sun.COM return (DCMD_USAGE);
4567532SSean.Ye@Sun.COM
4577532SSean.Ye@Sun.COM if ((len = strlen(p)) == 0) {
4587532SSean.Ye@Sun.COM return (DCMD_USAGE);
4597532SSean.Ye@Sun.COM } else {
4607532SSean.Ye@Sun.COM buf = mdb_alloc(len + 1, UM_SLEEP);
4617532SSean.Ye@Sun.COM strcpy(buf, p);
4627532SSean.Ye@Sun.COM }
4637532SSean.Ye@Sun.COM
4647532SSean.Ye@Sun.COM cb.mod_cpuid = cb.mod_chipid = cb.mod_coreid =
4657532SSean.Ye@Sun.COM cb.mod_strandid = -1;
4667532SSean.Ye@Sun.COM
4677532SSean.Ye@Sun.COM if ((p = strchr(buf, '/')) == NULL) {
4687532SSean.Ye@Sun.COM /* Native cpuid */
4697532SSean.Ye@Sun.COM cb.mod_cpuid = (int)mdb_strtoull(buf);
4707532SSean.Ye@Sun.COM } else {
4717532SSean.Ye@Sun.COM /* Comma-separated triplet chip,core,strand. */
4727532SSean.Ye@Sun.COM char *q = buf;
4737532SSean.Ye@Sun.COM
4747532SSean.Ye@Sun.COM *p = '\0';
4757532SSean.Ye@Sun.COM cb.mod_chipid = (int)mdb_strtoull(q);
4767532SSean.Ye@Sun.COM
4777532SSean.Ye@Sun.COM if ((q = p + 1) >= buf + len ||
4787532SSean.Ye@Sun.COM (p = strchr(q, '/')) == NULL) {
4797532SSean.Ye@Sun.COM mdb_free(buf, len);
4807532SSean.Ye@Sun.COM return (DCMD_USAGE);
4817532SSean.Ye@Sun.COM }
4827532SSean.Ye@Sun.COM
4837532SSean.Ye@Sun.COM *p = '\0';
4847532SSean.Ye@Sun.COM cb.mod_coreid = (int)mdb_strtoull(q);
4857532SSean.Ye@Sun.COM
4867532SSean.Ye@Sun.COM if ((q = p + 1) >= buf + len) {
4877532SSean.Ye@Sun.COM mdb_free(buf, len);
4887532SSean.Ye@Sun.COM return (DCMD_USAGE);
4897532SSean.Ye@Sun.COM }
4907532SSean.Ye@Sun.COM
4917532SSean.Ye@Sun.COM cb.mod_strandid = (int)mdb_strtoull(q);
4927532SSean.Ye@Sun.COM }
4937532SSean.Ye@Sun.COM
4947532SSean.Ye@Sun.COM mdb_free(buf, len);
4957532SSean.Ye@Sun.COM
4967532SSean.Ye@Sun.COM cb.mod_hdladdr = NULL;
4977532SSean.Ye@Sun.COM if (mdb_walk("cmihdl", cmihdl_cb, &cb) == -1) {
4987532SSean.Ye@Sun.COM mdb_warn("cmi_hdl walk failed\n");
4997532SSean.Ye@Sun.COM return (DCMD_ERR);
5007532SSean.Ye@Sun.COM }
5017532SSean.Ye@Sun.COM
5027532SSean.Ye@Sun.COM if (cb.mod_hdladdr == NULL) {
5037532SSean.Ye@Sun.COM if (cb.mod_cpuid != -1) {
5047532SSean.Ye@Sun.COM mdb_warn("No handle found for cpuid %d\n",
5057532SSean.Ye@Sun.COM cb.mod_cpuid);
5067532SSean.Ye@Sun.COM } else {
5077532SSean.Ye@Sun.COM
5087532SSean.Ye@Sun.COM mdb_warn("No handle found for chip %d "
5097532SSean.Ye@Sun.COM "core %d strand %d\n", cb.mod_chipid,
5107532SSean.Ye@Sun.COM cb.mod_coreid, cb.mod_strandid);
5117532SSean.Ye@Sun.COM }
5127532SSean.Ye@Sun.COM return (DCMD_ERR);
5137532SSean.Ye@Sun.COM }
5147532SSean.Ye@Sun.COM
5157532SSean.Ye@Sun.COM addr = cb.mod_hdladdr;
5167532SSean.Ye@Sun.COM }
5177532SSean.Ye@Sun.COM
5187532SSean.Ye@Sun.COM if (DCMD_HDRSPEC(flags)) {
5197532SSean.Ye@Sun.COM char ul[] = "----------------------------";
5207532SSean.Ye@Sun.COM char *p = ul + sizeof (ul) - 1;
5217532SSean.Ye@Sun.COM
5227532SSean.Ye@Sun.COM mdb_printf(HDRFMT HDRFMT,
5237532SSean.Ye@Sun.COM "HANDLE", "REF", "CPU", "CH/CR/ST", "CMT", "MC",
5247532SSean.Ye@Sun.COM "MODULE", "MODEL-SPECIFIC",
5257532SSean.Ye@Sun.COM p - 16, p - 3, p - 3, p - 8, p - 3, p - 2, p - 13, p - 24);
5267532SSean.Ye@Sun.COM }
5277532SSean.Ye@Sun.COM
5287532SSean.Ye@Sun.COM hdl = mdb_alloc(sizeof (cmi_hdl_impl_t), UM_SLEEP);
5297532SSean.Ye@Sun.COM
5307532SSean.Ye@Sun.COM if (mdb_vread(hdl, sizeof (cmi_hdl_impl_t), addr) !=
5317532SSean.Ye@Sun.COM sizeof (cmi_hdl_impl_t)) {
5327532SSean.Ye@Sun.COM mdb_free(hdl, sizeof (cmi_hdl_impl_t));
5337532SSean.Ye@Sun.COM mdb_warn("Read of cmi handle at 0x%p failed", addr);
5347532SSean.Ye@Sun.COM return (DCMD_ERR);
5357532SSean.Ye@Sun.COM }
5367532SSean.Ye@Sun.COM
5377532SSean.Ye@Sun.COM if (!cmihdl_disp(addr, hdl)) {
5387532SSean.Ye@Sun.COM mdb_free(hdl, sizeof (cmi_hdl_impl_t));
5397532SSean.Ye@Sun.COM return (DCMD_ERR);
5407532SSean.Ye@Sun.COM }
5417532SSean.Ye@Sun.COM
5427532SSean.Ye@Sun.COM mdb_free(hdl, sizeof (cmi_hdl_impl_t));
5437532SSean.Ye@Sun.COM
5447532SSean.Ye@Sun.COM return (DCMD_OK);
5457532SSean.Ye@Sun.COM }
5467532SSean.Ye@Sun.COM
5477532SSean.Ye@Sun.COM /*ARGSUSED*/
5487532SSean.Ye@Sun.COM static int
gcpu_mpt_dump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5497532SSean.Ye@Sun.COM gcpu_mpt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5507532SSean.Ye@Sun.COM {
5517532SSean.Ye@Sun.COM static const char *const whatstrs[] = {
5527532SSean.Ye@Sun.COM "ntv-cyc-poll", /* GCPU_MPT_WHAT_CYC_ERR */
5537532SSean.Ye@Sun.COM "poll-poked", /* GCPU_MPT_WHAT_POKE_ERR */
5547532SSean.Ye@Sun.COM "unfaulting", /* GCPU_MPT_WHAT_UNFAULTING */
5557532SSean.Ye@Sun.COM "#MC", /* GCPU_MPT_WHAT_MC_ERR */
5567532SSean.Ye@Sun.COM "CMCI-int", /* GCPU_MPT_WHAT_CMCI_ERR */
5577532SSean.Ye@Sun.COM "xpv-virq-nrec", /* GCPU_MPT_WHAT_XPV_VIRQ */
5587532SSean.Ye@Sun.COM "xpv-virq-lgout", /* GCPU_MPT_WHAT_XPV_VIRQ_LOGOUT */
5597532SSean.Ye@Sun.COM };
5607532SSean.Ye@Sun.COM
5617532SSean.Ye@Sun.COM gcpu_poll_trace_t mpt;
5627532SSean.Ye@Sun.COM const char *what;
5637532SSean.Ye@Sun.COM
5647532SSean.Ye@Sun.COM if (argc != 0 || !(flags & DCMD_ADDRSPEC))
5657532SSean.Ye@Sun.COM return (DCMD_USAGE);
5667532SSean.Ye@Sun.COM
5677532SSean.Ye@Sun.COM if (mdb_vread(&mpt, sizeof (mpt), addr) != sizeof (mpt)) {
5687532SSean.Ye@Sun.COM mdb_warn("failed to read gcpu_poll_trace_t at 0x%p", addr);
5697532SSean.Ye@Sun.COM return (DCMD_ERR);
5707532SSean.Ye@Sun.COM }
5717532SSean.Ye@Sun.COM
5727532SSean.Ye@Sun.COM if (DCMD_HDRSPEC(flags)) {
5737532SSean.Ye@Sun.COM mdb_printf("%<u>%?s%</u> %<u>%?s%</u> %<u>%15s%</u> "
5747532SSean.Ye@Sun.COM "%<u>%4s%</u>\n", "ADDR", "WHEN", "WHAT", "NERR");
5757532SSean.Ye@Sun.COM }
5767532SSean.Ye@Sun.COM
5777532SSean.Ye@Sun.COM if (mpt.mpt_what < sizeof (whatstrs) / sizeof (char *))
5787532SSean.Ye@Sun.COM what = whatstrs[mpt.mpt_what];
5797532SSean.Ye@Sun.COM else
5807532SSean.Ye@Sun.COM what = "???";
5817532SSean.Ye@Sun.COM
5827532SSean.Ye@Sun.COM mdb_printf("%?p %?p %15s %4u\n", addr, mpt.mpt_when, what,
5837532SSean.Ye@Sun.COM mpt.mpt_nerr);
5847532SSean.Ye@Sun.COM
5857532SSean.Ye@Sun.COM return (DCMD_OK);
5867532SSean.Ye@Sun.COM }
5877532SSean.Ye@Sun.COM
5887532SSean.Ye@Sun.COM typedef struct mptwalk_data {
5897532SSean.Ye@Sun.COM uintptr_t mw_traceaddr;
5907532SSean.Ye@Sun.COM gcpu_poll_trace_t *mw_trace;
5917532SSean.Ye@Sun.COM size_t mw_tracesz;
5927532SSean.Ye@Sun.COM uint_t mw_tracenent;
5937532SSean.Ye@Sun.COM uint_t mw_curtrace;
5947532SSean.Ye@Sun.COM } mptwalk_data_t;
5957532SSean.Ye@Sun.COM
5967532SSean.Ye@Sun.COM static int
gcpu_mptwalk_init(mdb_walk_state_t * wsp)5977532SSean.Ye@Sun.COM gcpu_mptwalk_init(mdb_walk_state_t *wsp)
5987532SSean.Ye@Sun.COM {
5997532SSean.Ye@Sun.COM gcpu_poll_trace_t *mpt;
6007532SSean.Ye@Sun.COM mptwalk_data_t *mw;
6017532SSean.Ye@Sun.COM GElf_Sym sym;
6027532SSean.Ye@Sun.COM uint_t nent, i;
6037532SSean.Ye@Sun.COM hrtime_t latest;
6047532SSean.Ye@Sun.COM
6057532SSean.Ye@Sun.COM if (wsp->walk_addr == NULL) {
6067532SSean.Ye@Sun.COM mdb_warn("the address of a poll trace array must be "
6077532SSean.Ye@Sun.COM "specified\n");
6087532SSean.Ye@Sun.COM return (WALK_ERR);
6097532SSean.Ye@Sun.COM }
6107532SSean.Ye@Sun.COM
6117532SSean.Ye@Sun.COM if (mdb_lookup_by_name("gcpu_poll_trace_nent", &sym) < 0 ||
6127532SSean.Ye@Sun.COM sym.st_size != sizeof (uint_t) || mdb_vread(&nent, sizeof (uint_t),
6137532SSean.Ye@Sun.COM sym.st_value) != sizeof (uint_t)) {
6147532SSean.Ye@Sun.COM mdb_warn("failed to read gcpu_poll_trace_nent from kernel");
6157532SSean.Ye@Sun.COM return (WALK_ERR);
6167532SSean.Ye@Sun.COM }
6177532SSean.Ye@Sun.COM
6187532SSean.Ye@Sun.COM mw = mdb_alloc(sizeof (mptwalk_data_t), UM_SLEEP);
6197532SSean.Ye@Sun.COM mw->mw_traceaddr = wsp->walk_addr;
6207532SSean.Ye@Sun.COM mw->mw_tracenent = nent;
6217532SSean.Ye@Sun.COM mw->mw_tracesz = nent * sizeof (gcpu_poll_trace_t);
6227532SSean.Ye@Sun.COM mw->mw_trace = mdb_alloc(mw->mw_tracesz, UM_SLEEP);
6237532SSean.Ye@Sun.COM
6247532SSean.Ye@Sun.COM if (mdb_vread(mw->mw_trace, mw->mw_tracesz, wsp->walk_addr) !=
6257532SSean.Ye@Sun.COM mw->mw_tracesz) {
6267532SSean.Ye@Sun.COM mdb_free(mw->mw_trace, mw->mw_tracesz);
6277532SSean.Ye@Sun.COM mdb_free(mw, sizeof (mptwalk_data_t));
6287532SSean.Ye@Sun.COM mdb_warn("failed to read poll trace array from kernel");
6297532SSean.Ye@Sun.COM return (WALK_ERR);
6307532SSean.Ye@Sun.COM }
6317532SSean.Ye@Sun.COM
6327532SSean.Ye@Sun.COM latest = 0;
6337532SSean.Ye@Sun.COM mw->mw_curtrace = 0;
6347532SSean.Ye@Sun.COM for (mpt = mw->mw_trace, i = 0; i < mw->mw_tracenent; i++, mpt++) {
6357532SSean.Ye@Sun.COM if (mpt->mpt_when > latest) {
6367532SSean.Ye@Sun.COM latest = mpt->mpt_when;
6377532SSean.Ye@Sun.COM mw->mw_curtrace = i;
6387532SSean.Ye@Sun.COM }
6397532SSean.Ye@Sun.COM }
6407532SSean.Ye@Sun.COM
6417532SSean.Ye@Sun.COM if (latest == 0) {
6427532SSean.Ye@Sun.COM mdb_free(mw->mw_trace, mw->mw_tracesz);
6437532SSean.Ye@Sun.COM mdb_free(mw, sizeof (mptwalk_data_t));
6447532SSean.Ye@Sun.COM return (WALK_DONE); /* trace array is empty */
6457532SSean.Ye@Sun.COM }
6467532SSean.Ye@Sun.COM
6477532SSean.Ye@Sun.COM wsp->walk_data = mw;
6487532SSean.Ye@Sun.COM
6497532SSean.Ye@Sun.COM return (WALK_NEXT);
6507532SSean.Ye@Sun.COM }
6517532SSean.Ye@Sun.COM
6527532SSean.Ye@Sun.COM static int
gcpu_mptwalk_step(mdb_walk_state_t * wsp)6537532SSean.Ye@Sun.COM gcpu_mptwalk_step(mdb_walk_state_t *wsp)
6547532SSean.Ye@Sun.COM {
6557532SSean.Ye@Sun.COM mptwalk_data_t *mw = wsp->walk_data;
6567532SSean.Ye@Sun.COM gcpu_poll_trace_t *thismpt, *prevmpt;
6577532SSean.Ye@Sun.COM int prev, rv;
6587532SSean.Ye@Sun.COM
6597532SSean.Ye@Sun.COM thismpt = &mw->mw_trace[mw->mw_curtrace];
6607532SSean.Ye@Sun.COM
6617532SSean.Ye@Sun.COM rv = wsp->walk_callback(mw->mw_traceaddr + (mw->mw_curtrace *
6627532SSean.Ye@Sun.COM sizeof (gcpu_poll_trace_t)), thismpt, wsp->walk_cbdata);
6637532SSean.Ye@Sun.COM
6647532SSean.Ye@Sun.COM if (rv != WALK_NEXT)
6657532SSean.Ye@Sun.COM return (rv);
6667532SSean.Ye@Sun.COM
6677532SSean.Ye@Sun.COM prev = (mw->mw_curtrace - 1) % mw->mw_tracenent;
6687532SSean.Ye@Sun.COM prevmpt = &mw->mw_trace[prev];
6697532SSean.Ye@Sun.COM
6707532SSean.Ye@Sun.COM if (prevmpt->mpt_when == 0 || prevmpt->mpt_when > thismpt->mpt_when)
6717532SSean.Ye@Sun.COM return (WALK_DONE);
6727532SSean.Ye@Sun.COM
6737532SSean.Ye@Sun.COM mw->mw_curtrace = prev;
6747532SSean.Ye@Sun.COM
6757532SSean.Ye@Sun.COM return (WALK_NEXT);
6767532SSean.Ye@Sun.COM }
6777532SSean.Ye@Sun.COM
6787532SSean.Ye@Sun.COM static void
gcpu_mptwalk_fini(mdb_walk_state_t * wsp)6797532SSean.Ye@Sun.COM gcpu_mptwalk_fini(mdb_walk_state_t *wsp)
6807532SSean.Ye@Sun.COM {
6817532SSean.Ye@Sun.COM mptwalk_data_t *mw = wsp->walk_data;
6827532SSean.Ye@Sun.COM
6837532SSean.Ye@Sun.COM mdb_free(mw->mw_trace, mw->mw_tracesz);
6847532SSean.Ye@Sun.COM mdb_free(mw, sizeof (mptwalk_data_t));
6857532SSean.Ye@Sun.COM }
6867532SSean.Ye@Sun.COM
6877532SSean.Ye@Sun.COM static const mdb_dcmd_t dcmds[] = {
6887532SSean.Ye@Sun.COM { "cmihdl", ": -c <cpuid>|<chip,core,strand> ",
6897532SSean.Ye@Sun.COM "dump a cmi_handle_t", cmihdl },
6907532SSean.Ye@Sun.COM { "gcpu_poll_trace", ":", "dump a poll trace buffer", gcpu_mpt_dump },
6917532SSean.Ye@Sun.COM { NULL }
6927532SSean.Ye@Sun.COM };
6937532SSean.Ye@Sun.COM
6947532SSean.Ye@Sun.COM static const mdb_walker_t walkers[] = {
6957532SSean.Ye@Sun.COM { "cmihdl", "walks cpu module interface handle list",
6967532SSean.Ye@Sun.COM cmih_walk_init, cmih_walk_step, cmih_walk_fini, NULL },
6977532SSean.Ye@Sun.COM { "gcpu_poll_trace", "walks poll trace buffers in reverse "
6987532SSean.Ye@Sun.COM "chronological order", gcpu_mptwalk_init, gcpu_mptwalk_step,
6997532SSean.Ye@Sun.COM gcpu_mptwalk_fini, NULL },
7007532SSean.Ye@Sun.COM { NULL }
7017532SSean.Ye@Sun.COM };
7027532SSean.Ye@Sun.COM
7037532SSean.Ye@Sun.COM static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
7047532SSean.Ye@Sun.COM
7057532SSean.Ye@Sun.COM const mdb_modinfo_t *
_mdb_init(void)7067532SSean.Ye@Sun.COM _mdb_init(void)
7077532SSean.Ye@Sun.COM {
7087532SSean.Ye@Sun.COM return (&modinfo);
7097532SSean.Ye@Sun.COM }
710