1*9dd0f810Scindi /* 2*9dd0f810Scindi * CDDL HEADER START 3*9dd0f810Scindi * 4*9dd0f810Scindi * The contents of this file are subject to the terms of the 5*9dd0f810Scindi * Common Development and Distribution License (the "License"). 6*9dd0f810Scindi * You may not use this file except in compliance with the License. 7*9dd0f810Scindi * 8*9dd0f810Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9dd0f810Scindi * or http://www.opensolaris.org/os/licensing. 10*9dd0f810Scindi * See the License for the specific language governing permissions 11*9dd0f810Scindi * and limitations under the License. 12*9dd0f810Scindi * 13*9dd0f810Scindi * When distributing Covered Code, include this CDDL HEADER in each 14*9dd0f810Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9dd0f810Scindi * If applicable, add the following below this CDDL HEADER, with the 16*9dd0f810Scindi * fields enclosed by brackets "[]" replaced with your own identifying 17*9dd0f810Scindi * information: Portions Copyright [yyyy] [name of copyright owner] 18*9dd0f810Scindi * 19*9dd0f810Scindi * CDDL HEADER END 20*9dd0f810Scindi */ 21*9dd0f810Scindi /* 22*9dd0f810Scindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*9dd0f810Scindi * Use is subject to license terms. 24*9dd0f810Scindi */ 25*9dd0f810Scindi 26*9dd0f810Scindi #pragma ident "%Z%%M% %I% %E% SMI" 27*9dd0f810Scindi 28*9dd0f810Scindi #include <sys/types.h> 29*9dd0f810Scindi #include <sys/time.h> 30*9dd0f810Scindi #include <sys/sysmacros.h> 31*9dd0f810Scindi #include <sys/ddifm.h> 32*9dd0f810Scindi #include <sys/nvpair.h> 33*9dd0f810Scindi #include <sys/nvpair_impl.h> 34*9dd0f810Scindi #include <sys/errorq_impl.h> 35*9dd0f810Scindi #include <sys/errorq.h> 36*9dd0f810Scindi #include <sys/fm/protocol.h> 37*9dd0f810Scindi 38*9dd0f810Scindi #include <ctype.h> 39*9dd0f810Scindi #include <mdb/mdb_modapi.h> 40*9dd0f810Scindi #include <mdb/mdb_ks.h> 41*9dd0f810Scindi 42*9dd0f810Scindi #include "nvpair.h" 43*9dd0f810Scindi 44*9dd0f810Scindi int 45*9dd0f810Scindi ereportq_pend_walk_init(mdb_walk_state_t *wsp) 46*9dd0f810Scindi { 47*9dd0f810Scindi errorq_t eq; 48*9dd0f810Scindi uintptr_t addr; 49*9dd0f810Scindi 50*9dd0f810Scindi if (wsp->walk_addr == NULL && 51*9dd0f810Scindi mdb_readvar(&addr, "ereport_errorq") == -1) { 52*9dd0f810Scindi mdb_warn("failed to read ereport_errorq"); 53*9dd0f810Scindi return (WALK_ERR); 54*9dd0f810Scindi } 55*9dd0f810Scindi 56*9dd0f810Scindi if (mdb_vread(&eq, sizeof (eq), addr) == -1) { 57*9dd0f810Scindi mdb_warn("failed to read ereport_errorq at %p", addr); 58*9dd0f810Scindi return (WALK_ERR); 59*9dd0f810Scindi } 60*9dd0f810Scindi 61*9dd0f810Scindi if (!(eq.eq_flags & ERRORQ_NVLIST)) { 62*9dd0f810Scindi mdb_warn("errorq at %p does not service ereports", addr); 63*9dd0f810Scindi return (WALK_ERR); 64*9dd0f810Scindi } 65*9dd0f810Scindi 66*9dd0f810Scindi wsp->walk_addr = (uintptr_t)eq.eq_pend; 67*9dd0f810Scindi 68*9dd0f810Scindi return (WALK_NEXT); 69*9dd0f810Scindi } 70*9dd0f810Scindi 71*9dd0f810Scindi int 72*9dd0f810Scindi ereportq_pend_walk_step(mdb_walk_state_t *wsp) 73*9dd0f810Scindi { 74*9dd0f810Scindi uintptr_t addr = wsp->walk_addr; 75*9dd0f810Scindi nvlist_t nvl; 76*9dd0f810Scindi errorq_nvelem_t eqnp; 77*9dd0f810Scindi errorq_elem_t elem; 78*9dd0f810Scindi 79*9dd0f810Scindi if (addr == NULL) 80*9dd0f810Scindi return (WALK_DONE); 81*9dd0f810Scindi 82*9dd0f810Scindi if (mdb_vread(&elem, sizeof (elem), addr) != sizeof (elem) || 83*9dd0f810Scindi mdb_vread(&eqnp, sizeof (eqnp), (uintptr_t)elem.eqe_data) 84*9dd0f810Scindi != sizeof (eqnp) || mdb_vread(&nvl, sizeof (nvl), 85*9dd0f810Scindi (uintptr_t)eqnp.eqn_nvl) != sizeof (nvl)) { 86*9dd0f810Scindi mdb_warn("failed to read ereportq element at %p", addr); 87*9dd0f810Scindi return (WALK_ERR); 88*9dd0f810Scindi } 89*9dd0f810Scindi 90*9dd0f810Scindi wsp->walk_addr = (uintptr_t)elem.eqe_prev; 91*9dd0f810Scindi 92*9dd0f810Scindi return (wsp->walk_callback((uintptr_t)eqnp.eqn_nvl, &nvl, 93*9dd0f810Scindi wsp->walk_cbdata)); 94*9dd0f810Scindi } 95*9dd0f810Scindi 96*9dd0f810Scindi int 97*9dd0f810Scindi ereportq_dump_walk_init(mdb_walk_state_t *wsp) 98*9dd0f810Scindi { 99*9dd0f810Scindi errorq_t eq; 100*9dd0f810Scindi uintptr_t addr; 101*9dd0f810Scindi 102*9dd0f810Scindi if (wsp->walk_addr == NULL && 103*9dd0f810Scindi mdb_readvar(&addr, "ereport_errorq") == -1) { 104*9dd0f810Scindi mdb_warn("failed to read ereport_errorq"); 105*9dd0f810Scindi return (WALK_ERR); 106*9dd0f810Scindi } 107*9dd0f810Scindi 108*9dd0f810Scindi if (mdb_vread(&eq, sizeof (eq), addr) == -1) { 109*9dd0f810Scindi mdb_warn("failed to read ereport_errorq at %p", addr); 110*9dd0f810Scindi return (WALK_ERR); 111*9dd0f810Scindi } 112*9dd0f810Scindi 113*9dd0f810Scindi if (!(eq.eq_flags & ERRORQ_NVLIST)) { 114*9dd0f810Scindi mdb_warn("errorq at %p does not service ereports", addr); 115*9dd0f810Scindi return (WALK_ERR); 116*9dd0f810Scindi } 117*9dd0f810Scindi 118*9dd0f810Scindi wsp->walk_addr = (uintptr_t)eq.eq_dump; 119*9dd0f810Scindi 120*9dd0f810Scindi return (WALK_NEXT); 121*9dd0f810Scindi } 122*9dd0f810Scindi 123*9dd0f810Scindi int 124*9dd0f810Scindi ereportq_dump_walk_step(mdb_walk_state_t *wsp) 125*9dd0f810Scindi { 126*9dd0f810Scindi uintptr_t addr = wsp->walk_addr; 127*9dd0f810Scindi nvlist_t nvl; 128*9dd0f810Scindi errorq_nvelem_t eqnp; 129*9dd0f810Scindi errorq_elem_t elem; 130*9dd0f810Scindi 131*9dd0f810Scindi if (addr == NULL) 132*9dd0f810Scindi return (WALK_DONE); 133*9dd0f810Scindi 134*9dd0f810Scindi if (mdb_vread(&elem, sizeof (elem), addr) != sizeof (elem) || 135*9dd0f810Scindi mdb_vread(&eqnp, sizeof (eqnp), (uintptr_t)elem.eqe_data) 136*9dd0f810Scindi != sizeof (eqnp) || mdb_vread(&nvl, sizeof (nvl), 137*9dd0f810Scindi (uintptr_t)eqnp.eqn_nvl) != sizeof (nvl)) { 138*9dd0f810Scindi mdb_warn("failed to read ereportq element at %p", addr); 139*9dd0f810Scindi return (WALK_ERR); 140*9dd0f810Scindi } 141*9dd0f810Scindi 142*9dd0f810Scindi wsp->walk_addr = (uintptr_t)elem.eqe_dump; 143*9dd0f810Scindi 144*9dd0f810Scindi return (wsp->walk_callback((uintptr_t)eqnp.eqn_nvl, &nvl, 145*9dd0f810Scindi wsp->walk_cbdata)); 146*9dd0f810Scindi } 147*9dd0f810Scindi 148*9dd0f810Scindi /*ARGSUSED*/ 149*9dd0f810Scindi int 150*9dd0f810Scindi ereport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 151*9dd0f810Scindi { 152*9dd0f810Scindi int ret; 153*9dd0f810Scindi uint_t opt_v = 0; 154*9dd0f810Scindi char *class = NULL; 155*9dd0f810Scindi uint64_t ena = 0; 156*9dd0f810Scindi nvlist_t nvl; 157*9dd0f810Scindi nvpriv_t nvpriv; 158*9dd0f810Scindi i_nvp_t *nvcur, i_nvp; 159*9dd0f810Scindi 160*9dd0f810Scindi if (!(flags & DCMD_ADDRSPEC)) 161*9dd0f810Scindi return (DCMD_USAGE); 162*9dd0f810Scindi 163*9dd0f810Scindi if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 164*9dd0f810Scindi return (DCMD_USAGE); 165*9dd0f810Scindi 166*9dd0f810Scindi if (mdb_vread(&nvl, sizeof (nvl), addr) == -1) { 167*9dd0f810Scindi mdb_warn("failed to read nvlist at %p", addr); 168*9dd0f810Scindi return (DCMD_ERR); 169*9dd0f810Scindi } 170*9dd0f810Scindi 171*9dd0f810Scindi if (DCMD_HDRSPEC(flags) && !opt_v) { 172*9dd0f810Scindi mdb_printf("ENA CLASS\n"); 173*9dd0f810Scindi } 174*9dd0f810Scindi 175*9dd0f810Scindi /* 176*9dd0f810Scindi * The following code attempts to pretty print the ereport class 177*9dd0f810Scindi * and ENA. The code uses project private macros from libnvpair 178*9dd0f810Scindi * that could change and break this functionality. If we are unable 179*9dd0f810Scindi * to get a valid class and ENA from the nvpair list, we revert to 180*9dd0f810Scindi * dumping the nvlist (same as opt_v). 181*9dd0f810Scindi */ 182*9dd0f810Scindi if (mdb_vread(&nvpriv, sizeof (nvpriv), nvl.nvl_priv) == -1) { 183*9dd0f810Scindi mdb_warn("failed to read nvpriv at %p", nvl.nvl_priv); 184*9dd0f810Scindi return (DCMD_ERR); 185*9dd0f810Scindi } 186*9dd0f810Scindi 187*9dd0f810Scindi for (nvcur = nvpriv.nvp_list; nvcur != NULL; nvcur = i_nvp.nvi_next) { 188*9dd0f810Scindi nvpair_t *nvp, *nvpair; 189*9dd0f810Scindi int32_t size; 190*9dd0f810Scindi 191*9dd0f810Scindi if (opt_v) 192*9dd0f810Scindi break; 193*9dd0f810Scindi 194*9dd0f810Scindi if (mdb_vread(&i_nvp, sizeof (i_nvp), (uintptr_t)nvcur) == -1) { 195*9dd0f810Scindi mdb_warn("failed to read i_nvp at %p", nvcur); 196*9dd0f810Scindi return (DCMD_ERR); 197*9dd0f810Scindi } 198*9dd0f810Scindi 199*9dd0f810Scindi nvp = &i_nvp.nvi_nvp; 200*9dd0f810Scindi size = NVP_SIZE(nvp); 201*9dd0f810Scindi if (size == 0) { 202*9dd0f810Scindi mdb_warn("nvpair of size zero at %p", nvp); 203*9dd0f810Scindi return (DCMD_OK); 204*9dd0f810Scindi } 205*9dd0f810Scindi 206*9dd0f810Scindi /* read in the entire nvpair */ 207*9dd0f810Scindi nvpair = mdb_alloc(size, UM_SLEEP | UM_GC); 208*9dd0f810Scindi if (mdb_vread(nvpair, size, (uintptr_t)&nvcur->nvi_nvp) == -1) { 209*9dd0f810Scindi mdb_warn("failed to read nvpair and data at %p", nvp); 210*9dd0f810Scindi return (DCMD_ERR); 211*9dd0f810Scindi } 212*9dd0f810Scindi 213*9dd0f810Scindi if (strcmp(FM_CLASS, NVP_NAME(nvpair)) == 0 && 214*9dd0f810Scindi NVP_TYPE(nvpair) == DATA_TYPE_STRING && class == NULL) { 215*9dd0f810Scindi char *p = (char *)NVP_VALUE(nvpair); 216*9dd0f810Scindi 217*9dd0f810Scindi class = mdb_zalloc(strlen(p) + 1, UM_SLEEP | UM_GC); 218*9dd0f810Scindi bcopy(p, class, strlen(p)); 219*9dd0f810Scindi } else if (strcmp(FM_EREPORT_ENA, NVP_NAME(nvpair)) == 0 && 220*9dd0f810Scindi NVP_TYPE(nvpair) == DATA_TYPE_UINT64 && ena == 0) { 221*9dd0f810Scindi bcopy(NVP_VALUE(nvpair), (char *)&ena, 222*9dd0f810Scindi sizeof (uint64_t)); 223*9dd0f810Scindi } 224*9dd0f810Scindi 225*9dd0f810Scindi if (class != NULL && ena != 0) { 226*9dd0f810Scindi mdb_printf("0x%016llx %s\n", ena, class); 227*9dd0f810Scindi return (DCMD_OK); 228*9dd0f810Scindi } 229*9dd0f810Scindi 230*9dd0f810Scindi } 231*9dd0f810Scindi 232*9dd0f810Scindi /* 233*9dd0f810Scindi * Dump entire nvlist 234*9dd0f810Scindi */ 235*9dd0f810Scindi ret = mdb_call_dcmd("nvlist", addr, flags | DCMD_ADDRSPEC, 236*9dd0f810Scindi 0, argv); 237*9dd0f810Scindi mdb_printf("\n"); 238*9dd0f810Scindi 239*9dd0f810Scindi return (ret); 240*9dd0f810Scindi } 241