1*a60fc142Srf157361 /* 2*a60fc142Srf157361 * CDDL HEADER START 3*a60fc142Srf157361 * 4*a60fc142Srf157361 * The contents of this file are subject to the terms of the 5*a60fc142Srf157361 * Common Development and Distribution License (the "License"). 6*a60fc142Srf157361 * You may not use this file except in compliance with the License. 7*a60fc142Srf157361 * 8*a60fc142Srf157361 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a60fc142Srf157361 * or http://www.opensolaris.org/os/licensing. 10*a60fc142Srf157361 * See the License for the specific language governing permissions 11*a60fc142Srf157361 * and limitations under the License. 12*a60fc142Srf157361 * 13*a60fc142Srf157361 * When distributing Covered Code, include this CDDL HEADER in each 14*a60fc142Srf157361 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a60fc142Srf157361 * If applicable, add the following below this CDDL HEADER, with the 16*a60fc142Srf157361 * fields enclosed by brackets "[]" replaced with your own identifying 17*a60fc142Srf157361 * information: Portions Copyright [yyyy] [name of copyright owner] 18*a60fc142Srf157361 * 19*a60fc142Srf157361 * CDDL HEADER END 20*a60fc142Srf157361 */ 21*a60fc142Srf157361 /* 22*a60fc142Srf157361 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*a60fc142Srf157361 * Use is subject to license terms. 24*a60fc142Srf157361 */ 25*a60fc142Srf157361 26*a60fc142Srf157361 #pragma ident "%Z%%M% %I% %E% SMI" 27*a60fc142Srf157361 28*a60fc142Srf157361 #include <sys/types.h> 29*a60fc142Srf157361 #include <sys/time.h> 30*a60fc142Srf157361 #include <sys/sysmacros.h> 31*a60fc142Srf157361 #include <ctype.h> 32*a60fc142Srf157361 #include <sys/mdb_modapi.h> 33*a60fc142Srf157361 #include <sys/cpuvar.h> 34*a60fc142Srf157361 #include <sys/machcpuvar.h> 35*a60fc142Srf157361 #include <sys/error.h> 36*a60fc142Srf157361 37*a60fc142Srf157361 38*a60fc142Srf157361 /*ARGSUSED*/ 39*a60fc142Srf157361 int 40*a60fc142Srf157361 resumable(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 41*a60fc142Srf157361 { 42*a60fc142Srf157361 uint_t verbose = 0; 43*a60fc142Srf157361 cpu_t cpu; 44*a60fc142Srf157361 uintptr_t current, first; 45*a60fc142Srf157361 46*a60fc142Srf157361 if (flags & DCMD_ADDRSPEC) 47*a60fc142Srf157361 return (DCMD_USAGE); 48*a60fc142Srf157361 49*a60fc142Srf157361 if (mdb_getopts(argc, argv, 50*a60fc142Srf157361 'v', MDB_OPT_SETBITS, 1, &verbose, NULL) != argc) 51*a60fc142Srf157361 return (DCMD_USAGE); 52*a60fc142Srf157361 53*a60fc142Srf157361 if (mdb_readvar(&first, "cpu_list") == -1) { 54*a60fc142Srf157361 mdb_warn("failed to read 'cpu_list'"); 55*a60fc142Srf157361 return (DCMD_ERR); 56*a60fc142Srf157361 } 57*a60fc142Srf157361 58*a60fc142Srf157361 if (verbose) 59*a60fc142Srf157361 mdb_printf("CPUID ADDRESS\n"); 60*a60fc142Srf157361 61*a60fc142Srf157361 current = first; 62*a60fc142Srf157361 do { 63*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu), current) == -1) { 64*a60fc142Srf157361 mdb_warn("failed to read cpu at %p", current); 65*a60fc142Srf157361 return (DCMD_ERR); 66*a60fc142Srf157361 } 67*a60fc142Srf157361 68*a60fc142Srf157361 if (verbose) { 69*a60fc142Srf157361 if (cpu.cpu_m.cpu_rq_lastre == 0) 70*a60fc142Srf157361 mdb_printf("%-5d empty\n", cpu.cpu_id); 71*a60fc142Srf157361 else 72*a60fc142Srf157361 mdb_printf("%-5d %lx\n", cpu.cpu_id, 73*a60fc142Srf157361 cpu.cpu_m.cpu_rq_lastre); 74*a60fc142Srf157361 } else if (cpu.cpu_m.cpu_rq_lastre != 0) 75*a60fc142Srf157361 mdb_printf("%lx\n", cpu.cpu_m.cpu_rq_lastre); 76*a60fc142Srf157361 } while ((current = (uintptr_t)cpu.cpu_next) != first); 77*a60fc142Srf157361 78*a60fc142Srf157361 return (DCMD_OK); 79*a60fc142Srf157361 } 80*a60fc142Srf157361 81*a60fc142Srf157361 /*ARGSUSED*/ 82*a60fc142Srf157361 int 83*a60fc142Srf157361 nonresumable(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 84*a60fc142Srf157361 { 85*a60fc142Srf157361 uint_t verbose = 0; 86*a60fc142Srf157361 cpu_t cpu; 87*a60fc142Srf157361 uintptr_t current, first; 88*a60fc142Srf157361 89*a60fc142Srf157361 if (flags & DCMD_ADDRSPEC) 90*a60fc142Srf157361 return (DCMD_USAGE); 91*a60fc142Srf157361 92*a60fc142Srf157361 if (mdb_getopts(argc, argv, 93*a60fc142Srf157361 'v', MDB_OPT_SETBITS, 1, &verbose, NULL) != argc) 94*a60fc142Srf157361 return (DCMD_USAGE); 95*a60fc142Srf157361 96*a60fc142Srf157361 if (mdb_readvar(&first, "cpu_list") == -1) { 97*a60fc142Srf157361 mdb_warn("failed to read 'cpu_list'"); 98*a60fc142Srf157361 return (DCMD_ERR); 99*a60fc142Srf157361 } 100*a60fc142Srf157361 101*a60fc142Srf157361 if (verbose) 102*a60fc142Srf157361 mdb_printf("CPUID ADDRESS\n"); 103*a60fc142Srf157361 104*a60fc142Srf157361 current = first; 105*a60fc142Srf157361 do { 106*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu), current) == -1) { 107*a60fc142Srf157361 mdb_warn("failed to read cpu at %p", current); 108*a60fc142Srf157361 return (DCMD_ERR); 109*a60fc142Srf157361 } 110*a60fc142Srf157361 111*a60fc142Srf157361 if (verbose) { 112*a60fc142Srf157361 if (cpu.cpu_m.cpu_nrq_lastnre == 0) 113*a60fc142Srf157361 mdb_printf("%-5d empty\n", cpu.cpu_id); 114*a60fc142Srf157361 else 115*a60fc142Srf157361 mdb_printf("%-5d %lx\n", cpu.cpu_id, 116*a60fc142Srf157361 cpu.cpu_m.cpu_nrq_lastnre); 117*a60fc142Srf157361 } else if (cpu.cpu_m.cpu_nrq_lastnre != 0) 118*a60fc142Srf157361 mdb_printf("%lx\n", cpu.cpu_m.cpu_nrq_lastnre); 119*a60fc142Srf157361 } while ((current = (uintptr_t)cpu.cpu_next) != first); 120*a60fc142Srf157361 121*a60fc142Srf157361 return (DCMD_OK); 122*a60fc142Srf157361 } 123*a60fc142Srf157361 124*a60fc142Srf157361 /*ARGSUSED*/ 125*a60fc142Srf157361 int 126*a60fc142Srf157361 rqueue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 127*a60fc142Srf157361 { 128*a60fc142Srf157361 uint_t verbose = 0; 129*a60fc142Srf157361 cpu_t cpu; 130*a60fc142Srf157361 uintptr_t ao, lower, upper, current; 131*a60fc142Srf157361 132*a60fc142Srf157361 if (!(flags & DCMD_ADDRSPEC)) 133*a60fc142Srf157361 return (DCMD_USAGE); 134*a60fc142Srf157361 135*a60fc142Srf157361 if (mdb_getopts(argc, argv, 136*a60fc142Srf157361 'v', MDB_OPT_SETBITS, 1, &verbose, NULL) != argc) 137*a60fc142Srf157361 return (DCMD_USAGE); 138*a60fc142Srf157361 139*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu_t), addr) == -1) { 140*a60fc142Srf157361 mdb_warn("failed to find cpu at %p", addr); 141*a60fc142Srf157361 return (DCMD_ERR); 142*a60fc142Srf157361 } 143*a60fc142Srf157361 144*a60fc142Srf157361 ao = (uintptr_t)cpu.cpu_m.cpu_rq_lastre; /* beginning and end */ 145*a60fc142Srf157361 lower = (uintptr_t)cpu.cpu_m.cpu_rq_va + CPU_RQ_SIZE; 146*a60fc142Srf157361 upper = lower + CPU_RQ_SIZE - Q_ENTRY_SIZE; 147*a60fc142Srf157361 148*a60fc142Srf157361 if (ao < lower || upper < ao) { 149*a60fc142Srf157361 if (verbose) 150*a60fc142Srf157361 mdb_printf("empty\n"); 151*a60fc142Srf157361 return (DCMD_OK); 152*a60fc142Srf157361 } 153*a60fc142Srf157361 154*a60fc142Srf157361 for (current = ao; current >= lower; current -= Q_ENTRY_SIZE) 155*a60fc142Srf157361 mdb_printf("%lx\n", current); 156*a60fc142Srf157361 157*a60fc142Srf157361 for (current = upper; current > ao; current -= Q_ENTRY_SIZE) 158*a60fc142Srf157361 mdb_printf("%lx\n", current); 159*a60fc142Srf157361 160*a60fc142Srf157361 return (DCMD_OK); 161*a60fc142Srf157361 } 162*a60fc142Srf157361 163*a60fc142Srf157361 /*ARGSUSED*/ 164*a60fc142Srf157361 int 165*a60fc142Srf157361 nrqueue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 166*a60fc142Srf157361 { 167*a60fc142Srf157361 uint_t verbose = 0; 168*a60fc142Srf157361 cpu_t cpu; 169*a60fc142Srf157361 uintptr_t lower, ao, upper; 170*a60fc142Srf157361 uintptr_t current; 171*a60fc142Srf157361 172*a60fc142Srf157361 if (!(flags & DCMD_ADDRSPEC)) 173*a60fc142Srf157361 return (DCMD_USAGE); 174*a60fc142Srf157361 175*a60fc142Srf157361 if (mdb_getopts(argc, argv, 176*a60fc142Srf157361 'v', MDB_OPT_SETBITS, 1, &verbose, NULL) != argc) 177*a60fc142Srf157361 return (DCMD_USAGE); 178*a60fc142Srf157361 179*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu_t), addr) == -1) { 180*a60fc142Srf157361 mdb_warn("failed to find cpu at %p", addr); 181*a60fc142Srf157361 return (DCMD_ERR); 182*a60fc142Srf157361 } 183*a60fc142Srf157361 184*a60fc142Srf157361 ao = (uintptr_t)cpu.cpu_m.cpu_nrq_lastnre; /* beginning and end */ 185*a60fc142Srf157361 lower = (uintptr_t)cpu.cpu_m.cpu_nrq_va + CPU_NRQ_SIZE; 186*a60fc142Srf157361 upper = lower + CPU_NRQ_SIZE - Q_ENTRY_SIZE; 187*a60fc142Srf157361 188*a60fc142Srf157361 if (ao < lower || upper < ao) { 189*a60fc142Srf157361 if (verbose) 190*a60fc142Srf157361 mdb_printf("empty\n"); 191*a60fc142Srf157361 return (DCMD_OK); 192*a60fc142Srf157361 } 193*a60fc142Srf157361 194*a60fc142Srf157361 for (current = ao; current >= lower; current -= Q_ENTRY_SIZE) 195*a60fc142Srf157361 mdb_printf("%lx\n", current); 196*a60fc142Srf157361 197*a60fc142Srf157361 for (current = upper; current > ao; current -= Q_ENTRY_SIZE) 198*a60fc142Srf157361 mdb_printf("%lx\n", current); 199*a60fc142Srf157361 200*a60fc142Srf157361 return (DCMD_OK); 201*a60fc142Srf157361 } 202*a60fc142Srf157361 203*a60fc142Srf157361 /*ARGSUSED*/ 204*a60fc142Srf157361 int 205*a60fc142Srf157361 errh_prtaddr(uintptr_t addr, const void *data, void *private) 206*a60fc142Srf157361 { 207*a60fc142Srf157361 mdb_printf("%lx\n", addr); 208*a60fc142Srf157361 return (WALK_NEXT); 209*a60fc142Srf157361 } 210*a60fc142Srf157361 211*a60fc142Srf157361 /*ARGSUSED*/ 212*a60fc142Srf157361 int 213*a60fc142Srf157361 rq_walk_init(mdb_walk_state_t *wsp) 214*a60fc142Srf157361 { 215*a60fc142Srf157361 cpu_t cpu; 216*a60fc142Srf157361 uintptr_t *ao, *lower, *upper; 217*a60fc142Srf157361 218*a60fc142Srf157361 if (wsp->walk_addr == NULL) { 219*a60fc142Srf157361 mdb_warn("address of struct cpu_t is required\n"); 220*a60fc142Srf157361 return (WALK_ERR); 221*a60fc142Srf157361 } 222*a60fc142Srf157361 223*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu_t), wsp->walk_addr) == -1) { 224*a60fc142Srf157361 mdb_warn("failed to find cpu at %p", wsp->walk_addr); 225*a60fc142Srf157361 return (WALK_ERR); 226*a60fc142Srf157361 } 227*a60fc142Srf157361 228*a60fc142Srf157361 wsp->walk_callback = (mdb_walk_cb_t)errh_prtaddr; 229*a60fc142Srf157361 wsp->walk_addr = (uintptr_t)cpu.cpu_m.cpu_rq_lastre; 230*a60fc142Srf157361 wsp->walk_data = mdb_alloc(sizeof (uintptr_t) * 3, UM_SLEEP); 231*a60fc142Srf157361 232*a60fc142Srf157361 ao = lower = upper = wsp->walk_data; 233*a60fc142Srf157361 lower += 1; 234*a60fc142Srf157361 upper += 2; 235*a60fc142Srf157361 236*a60fc142Srf157361 *ao = (uintptr_t)wsp->walk_addr; /* beginning and end */ 237*a60fc142Srf157361 *lower = (uintptr_t)cpu.cpu_m.cpu_rq_va + CPU_RQ_SIZE; 238*a60fc142Srf157361 *upper = (uintptr_t)*lower + CPU_RQ_SIZE - Q_ENTRY_SIZE; 239*a60fc142Srf157361 240*a60fc142Srf157361 if (wsp->walk_addr < *lower || *upper < wsp->walk_addr) { 241*a60fc142Srf157361 mdb_free(wsp->walk_data, sizeof (uintptr_t) * 3); 242*a60fc142Srf157361 return (WALK_DONE); 243*a60fc142Srf157361 } 244*a60fc142Srf157361 245*a60fc142Srf157361 return (WALK_NEXT); 246*a60fc142Srf157361 } 247*a60fc142Srf157361 248*a60fc142Srf157361 /*ARGSUSED*/ 249*a60fc142Srf157361 int 250*a60fc142Srf157361 nrq_walk_init(mdb_walk_state_t *wsp) 251*a60fc142Srf157361 { 252*a60fc142Srf157361 cpu_t cpu; 253*a60fc142Srf157361 uintptr_t *ao, *lower, *upper; 254*a60fc142Srf157361 255*a60fc142Srf157361 if (wsp->walk_addr == NULL) { 256*a60fc142Srf157361 mdb_warn("address of struct cpu_t is required\n"); 257*a60fc142Srf157361 return (WALK_ERR); 258*a60fc142Srf157361 } 259*a60fc142Srf157361 260*a60fc142Srf157361 if (mdb_vread(&cpu, sizeof (cpu_t), wsp->walk_addr) == -1) { 261*a60fc142Srf157361 mdb_warn("failed to find cpu at %p", wsp->walk_addr); 262*a60fc142Srf157361 return (WALK_ERR); 263*a60fc142Srf157361 } 264*a60fc142Srf157361 265*a60fc142Srf157361 wsp->walk_callback = (mdb_walk_cb_t)errh_prtaddr; 266*a60fc142Srf157361 wsp->walk_addr = (uintptr_t)cpu.cpu_m.cpu_nrq_lastnre; 267*a60fc142Srf157361 wsp->walk_data = mdb_alloc(sizeof (uintptr_t) * 3, UM_SLEEP); 268*a60fc142Srf157361 269*a60fc142Srf157361 ao = lower = upper = wsp->walk_data; 270*a60fc142Srf157361 lower += 1; 271*a60fc142Srf157361 upper += 2; 272*a60fc142Srf157361 273*a60fc142Srf157361 *ao = (uintptr_t)wsp->walk_addr; /* beginning and end */ 274*a60fc142Srf157361 *lower = (uintptr_t)cpu.cpu_m.cpu_nrq_va + CPU_NRQ_SIZE; 275*a60fc142Srf157361 *upper = (uintptr_t)*lower + CPU_NRQ_SIZE - Q_ENTRY_SIZE; 276*a60fc142Srf157361 277*a60fc142Srf157361 if (wsp->walk_addr < *lower || *upper < wsp->walk_addr) { 278*a60fc142Srf157361 mdb_free(wsp->walk_data, sizeof (uintptr_t) * 3); 279*a60fc142Srf157361 return (WALK_DONE); 280*a60fc142Srf157361 } 281*a60fc142Srf157361 282*a60fc142Srf157361 return (WALK_NEXT); 283*a60fc142Srf157361 } 284*a60fc142Srf157361 285*a60fc142Srf157361 /*ARGSUSED*/ 286*a60fc142Srf157361 int 287*a60fc142Srf157361 errh_walk_step(mdb_walk_state_t *wsp) 288*a60fc142Srf157361 { 289*a60fc142Srf157361 int status; 290*a60fc142Srf157361 uintptr_t *ao, *lower, *upper; 291*a60fc142Srf157361 292*a60fc142Srf157361 if (wsp->walk_addr == NULL) 293*a60fc142Srf157361 return (WALK_DONE); 294*a60fc142Srf157361 295*a60fc142Srf157361 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 296*a60fc142Srf157361 wsp->walk_cbdata); 297*a60fc142Srf157361 298*a60fc142Srf157361 wsp->walk_addr -= Q_ENTRY_SIZE; 299*a60fc142Srf157361 300*a60fc142Srf157361 ao = lower = upper = wsp->walk_data; 301*a60fc142Srf157361 lower += 1; 302*a60fc142Srf157361 upper += 2; 303*a60fc142Srf157361 304*a60fc142Srf157361 if (wsp->walk_addr < *lower) 305*a60fc142Srf157361 wsp->walk_addr = *upper; /* wrap around */ 306*a60fc142Srf157361 else if (wsp->walk_addr == *ao) 307*a60fc142Srf157361 return (WALK_DONE); /* end of loop */ 308*a60fc142Srf157361 309*a60fc142Srf157361 return (status); 310*a60fc142Srf157361 } 311*a60fc142Srf157361 312*a60fc142Srf157361 void 313*a60fc142Srf157361 errh_walk_fini(mdb_walk_state_t *wsp) 314*a60fc142Srf157361 { 315*a60fc142Srf157361 mdb_free(wsp->walk_data, sizeof (uintptr_t) * 3); 316*a60fc142Srf157361 } 317*a60fc142Srf157361 318*a60fc142Srf157361 /* 319*a60fc142Srf157361 * MDB module linkage information: 320*a60fc142Srf157361 * 321*a60fc142Srf157361 * Declare a list of structures describing dcmds, and a function 322*a60fc142Srf157361 * named _mdb_init to return a pointer to module information. 323*a60fc142Srf157361 */ 324*a60fc142Srf157361 325*a60fc142Srf157361 static const mdb_dcmd_t dcmds[] = { 326*a60fc142Srf157361 { "errhre", "[-v]", "addr of sun4v resumable error element", 327*a60fc142Srf157361 resumable }, 328*a60fc142Srf157361 { "errhnre", "[-v]", "addr of sun4v nonresumable error element", 329*a60fc142Srf157361 nonresumable }, 330*a60fc142Srf157361 { "errhrq", ":", "addr of sun4v resumable errors in RQ", rqueue }, 331*a60fc142Srf157361 { "errhnrq", ":", "addr of sun4v nonresumable errors in NRQ", nrqueue }, 332*a60fc142Srf157361 { NULL } 333*a60fc142Srf157361 }; 334*a60fc142Srf157361 335*a60fc142Srf157361 static const mdb_walker_t walkers[] = { 336*a60fc142Srf157361 { "errhrq", "walk a cpu-specific sun4v resumble error queue", 337*a60fc142Srf157361 rq_walk_init, errh_walk_step, errh_walk_fini, NULL }, 338*a60fc142Srf157361 { "errhnrq", "walk a cpu-specific sun4v nonresumble error queue", 339*a60fc142Srf157361 nrq_walk_init, errh_walk_step, errh_walk_fini, NULL }, 340*a60fc142Srf157361 { NULL } 341*a60fc142Srf157361 }; 342*a60fc142Srf157361 343*a60fc142Srf157361 static const mdb_modinfo_t modinfo = { 344*a60fc142Srf157361 MDB_API_VERSION, dcmds, walkers 345*a60fc142Srf157361 }; 346*a60fc142Srf157361 347*a60fc142Srf157361 const mdb_modinfo_t * 348*a60fc142Srf157361 _mdb_init(void) 349*a60fc142Srf157361 { 350*a60fc142Srf157361 return (&modinfo); 351*a60fc142Srf157361 } 352