xref: /titanic_51/usr/src/cmd/mdb/sun4v/modules/errh/errh.c (revision a60fc142342386d0b786e65fba901234400d7020)
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