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