xref: /onnv-gate/usr/src/cmd/mdb/sparc/modules/intr/intr.c (revision 965:5a2d334f6666)
1909Segillett /*
2909Segillett  * CDDL HEADER START
3909Segillett  *
4909Segillett  * The contents of this file are subject to the terms of the
5909Segillett  * Common Development and Distribution License, Version 1.0 only
6909Segillett  * (the "License").  You may not use this file except in compliance
7909Segillett  * with the License.
8909Segillett  *
9909Segillett  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10909Segillett  * or http://www.opensolaris.org/os/licensing.
11909Segillett  * See the License for the specific language governing permissions
12909Segillett  * and limitations under the License.
13909Segillett  *
14909Segillett  * When distributing Covered Code, include this CDDL HEADER in each
15909Segillett  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16909Segillett  * If applicable, add the following below this CDDL HEADER, with the
17909Segillett  * fields enclosed by brackets "[]" replaced with your own identifying
18909Segillett  * information: Portions Copyright [yyyy] [name of copyright owner]
19909Segillett  *
20909Segillett  * CDDL HEADER END
21909Segillett  */
22909Segillett /*
23909Segillett  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24909Segillett  * Use is subject to license terms.
25909Segillett  */
26909Segillett 
27909Segillett #pragma ident	"%Z%%M%	%I%	%E% SMI"
28909Segillett 
29909Segillett #include <sys/mdb_modapi.h>
30909Segillett #include <mdb/mdb_ks.h>
31909Segillett #include <sys/async.h>		/* ecc_flt for pci_ecc.h */
32909Segillett #include <sys/ddi_subrdefs.h>
33909Segillett #include <sys/pci/pci_obj.h>
34909Segillett #include "px_obj.h"
35909Segillett 
36909Segillett static int intr_pci_walk_step(mdb_walk_state_t *);
37909Segillett static int intr_px_walk_step(mdb_walk_state_t *);
38909Segillett static void intr_pci_print_items(mdb_walk_state_t *);
39909Segillett static void intr_px_print_items(mdb_walk_state_t *);
40909Segillett static char *intr_get_intr_type(msiq_rec_type_t);
41909Segillett static void intr_print_banner(void);
42909Segillett 
43909Segillett typedef struct intr_info {
44909Segillett 	uint32_t	cpuid;
45909Segillett 	uint32_t	inum;
46909Segillett 	uint32_t	num;
47909Segillett 	uint32_t	pil;
48909Segillett 	uint16_t	mondo;
49909Segillett 	uint8_t		ino_ino;
50909Segillett 	uint_t		intr_state;
51909Segillett 	int		instance;
52909Segillett 	int		shared;
53909Segillett 	msiq_rec_type_t intr_type;
54909Segillett 	char		driver_name[12];
55909Segillett 	char		pathname[MAXNAMELEN];
56909Segillett }
57909Segillett intr_info_t;
58909Segillett 
59909Segillett static void intr_print_elements(intr_info_t);
60909Segillett static int detailed = 0; /* Print detailed view */
61909Segillett 
62909Segillett 
63909Segillett static int
64909Segillett intr_walk_init(mdb_walk_state_t *wsp)
65909Segillett {
66909Segillett 	wsp->walk_addr = NULL;
67909Segillett 
68909Segillett 	return (WALK_NEXT);
69909Segillett }
70909Segillett 
71909Segillett static int
72909Segillett intr_walk_step(mdb_walk_state_t *wsp)
73909Segillett {
74909Segillett 	pci_t		*pci_per_p;
75909Segillett 	px_t		*px_state_p;
76909Segillett 
77909Segillett 	/* read globally declared structures in the pci driver */
78909Segillett 	if (mdb_readvar(&pci_per_p, "per_pci_state") != -1) {
79909Segillett 		wsp->walk_addr = (uintptr_t)pci_per_p;
80909Segillett 		intr_pci_walk_step(wsp);
81909Segillett 	}
82909Segillett 
83909Segillett 	/* read globally declared structures in the px driver */
84909Segillett 	if (mdb_readvar(&px_state_p, "px_state_p") != -1) {
85909Segillett 		wsp->walk_addr = (uintptr_t)px_state_p;
86909Segillett 		intr_px_walk_step(wsp);
87909Segillett 	}
88909Segillett 
89909Segillett 	return (WALK_DONE);
90909Segillett }
91909Segillett 
92909Segillett static int
93909Segillett intr_pci_walk_step(mdb_walk_state_t *wsp)
94909Segillett {
95909Segillett 	pci_t		*pci_per_p;
96909Segillett 	pci_t		pci_per;
97909Segillett 	uintptr_t	start_addr;
98909Segillett 
99909Segillett 	/* Read start of state structure array */
100909Segillett 	if (mdb_vread(&pci_per_p, sizeof (uintptr_t),
101909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
102909Segillett 		mdb_warn("intr: failed to read the initial pci_per_p "
103909Segillett 		    "structure\n");
104909Segillett 		return (WALK_ERR);
105909Segillett 	}
106909Segillett 
107909Segillett 	/* Figure out how many items are here */
108909Segillett 	start_addr = (uintptr_t)pci_per_p;
109909Segillett 
110*965Sgovinda 	intr_print_banner();
111*965Sgovinda 
112909Segillett 	while (mdb_vread(&pci_per_p, sizeof (uintptr_t),
113909Segillett 	    (uintptr_t)start_addr) != -1) {
114909Segillett 		/* Read until nothing is left */
115909Segillett 		if (mdb_vread(&pci_per, sizeof (pci_t),
116909Segillett 		    (uintptr_t)pci_per_p) == -1) {
117909Segillett 			return (WALK_DONE);
118909Segillett 		}
119909Segillett 
120909Segillett 		wsp->walk_addr = (uintptr_t)pci_per.pci_ib_p;
121909Segillett 		intr_pci_print_items(wsp);
122909Segillett 
123909Segillett 		start_addr += sizeof (uintptr_t);
124909Segillett 	}
125909Segillett 
126909Segillett 	return (WALK_DONE);
127909Segillett }
128909Segillett 
129909Segillett static int
130909Segillett intr_px_walk_step(mdb_walk_state_t *wsp)
131909Segillett {
132909Segillett 	px_t		*px_state_p;
133909Segillett 	px_t		px_state;
134909Segillett 	uintptr_t	start_addr;
135909Segillett 
136909Segillett 	/* Read start of state structure array */
137909Segillett 	if (mdb_vread(&px_state_p, sizeof (uintptr_t),
138909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
139909Segillett 		mdb_warn("intr: failed to read the initial px_per_p "
140909Segillett 		    "structure\n");
141909Segillett 		return (WALK_ERR);
142909Segillett 	}
143909Segillett 
144909Segillett 	/* Figure out how many items are here */
145909Segillett 	start_addr = (uintptr_t)px_state_p;
146909Segillett 
147*965Sgovinda 	intr_print_banner();
148*965Sgovinda 
149909Segillett 	while (mdb_vread(&px_state_p, sizeof (uintptr_t),
150909Segillett 	    (uintptr_t)start_addr) != -1) {
151909Segillett 		/* Read until nothing is left */
152909Segillett 		if (mdb_vread(&px_state, sizeof (px_t),
153909Segillett 		    (uintptr_t)px_state_p) == -1) {
154909Segillett 			return (WALK_DONE);
155909Segillett 		}
156909Segillett 
157909Segillett 		wsp->walk_addr = (uintptr_t)px_state.px_ib_p;
158909Segillett 		intr_px_print_items(wsp);
159909Segillett 
160909Segillett 		start_addr += sizeof (uintptr_t);
161909Segillett 	}
162909Segillett 
163909Segillett 	return (WALK_DONE);
164909Segillett }
165909Segillett 
166909Segillett static void
167909Segillett intr_pci_print_items(mdb_walk_state_t *wsp)
168909Segillett {
169909Segillett 	ib_t			pci_ib;
170909Segillett 	ib_ino_info_t		*ib_ino_lst;
171909Segillett 	ib_ino_info_t		list;
172909Segillett 	ih_t			ih;
173909Segillett 	int			count;
174909Segillett 	char			name[MODMAXNAMELEN + 1];
175909Segillett 	struct dev_info		devinfo;
176909Segillett 	intr_info_t		info;
177909Segillett 
178909Segillett 	if (mdb_vread(&pci_ib, sizeof (ib_t),
179909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
180909Segillett 		mdb_warn("intr: failed to read pci interrupt block "
181909Segillett 		    "structure\n");
182909Segillett 		return;
183909Segillett 	}
184909Segillett 
185909Segillett 	/* Read in ib_ino_info_t structure at address */
186909Segillett 	ib_ino_lst = pci_ib.ib_ino_lst;
187909Segillett 	if (mdb_vread(&list, sizeof (ib_ino_info_t),
188909Segillett 	    (uintptr_t)ib_ino_lst) == -1) {
189909Segillett 		/* Nothing here to read from */
190909Segillett 		return;
191909Segillett 	}
192909Segillett 
193909Segillett 	do {
194909Segillett 		if (mdb_vread(&ih, sizeof (ih_t),
195909Segillett 		    (uintptr_t)list.ino_ih_start) == -1) {
196909Segillett 			mdb_warn("intr: failed to read pci interrupt entry "
197909Segillett 			    "structure\n");
198909Segillett 			return;
199909Segillett 		}
200909Segillett 
201909Segillett 		count = 0;
202909Segillett 
203909Segillett 		do {
204909Segillett 			bzero((void *)&info, sizeof (intr_info_t));
205909Segillett 
206909Segillett 			if (list.ino_ih_size > 1) {
207909Segillett 				info.shared = 1;
208909Segillett 			}
209909Segillett 
210909Segillett 			(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
211909Segillett 			    name, sizeof (name));
212909Segillett 
213909Segillett 			(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
214909Segillett 			    info.pathname, sizeof (info.pathname));
215909Segillett 
216909Segillett 			/* Get instance */
217909Segillett 			if (mdb_vread(&devinfo, sizeof (struct dev_info),
218909Segillett 			    (uintptr_t)ih.ih_dip) == -1) {
219909Segillett 				mdb_warn("intr: failed to read DIP "
220909Segillett 				    "structure\n");
221909Segillett 				return;
222909Segillett 			}
223909Segillett 
224909Segillett 			/* Make sure the name doesn't over run */
225909Segillett 			(void) mdb_snprintf(info.driver_name,
226909Segillett 			    sizeof (info.driver_name), "%s", name);
227909Segillett 
228909Segillett 			info.instance = devinfo.devi_instance;
229909Segillett 			info.inum = ih.ih_inum;
230909Segillett 			info.intr_type = INTX_REC;
231909Segillett 			info.num = 0;
232909Segillett 			info.intr_state = ih.ih_intr_state;
233909Segillett 			info.ino_ino = list.ino_ino;
234909Segillett 			info.mondo = list.ino_mondo;
235909Segillett 			info.pil = list.ino_pil;
236909Segillett 			info.cpuid = list.ino_cpuid;
237909Segillett 
238909Segillett 			intr_print_elements(info);
239909Segillett 			count++;
240909Segillett 
241909Segillett 			(void) mdb_vread(&ih, sizeof (ih_t),
242909Segillett 			    (uintptr_t)ih.ih_next);
243909Segillett 
244909Segillett 		} while (count < list.ino_ih_size);
245909Segillett 
246909Segillett 	} while (mdb_vread(&list, sizeof (ib_ino_info_t),
247909Segillett 	    (uintptr_t)list.ino_next) != -1);
248909Segillett }
249909Segillett 
250909Segillett static void
251909Segillett intr_px_print_items(mdb_walk_state_t *wsp)
252909Segillett {
253909Segillett 	px_ib_t			px_ib;
254909Segillett 	px_ib_ino_info_t	*px_ib_ino_lst;
255909Segillett 	px_ib_ino_info_t	px_list;
256909Segillett 	px_ih_t			px_ih;
257909Segillett 	int			count;
258909Segillett 	char			name[MODMAXNAMELEN + 1];
259909Segillett 	struct dev_info		devinfo;
260909Segillett 	intr_info_t		info;
261909Segillett 
262909Segillett 	if (mdb_vread(&px_ib, sizeof (px_ib_t), wsp->walk_addr) == -1) {
263909Segillett 		mdb_warn("intr: failed to read px interrupt block "
264909Segillett 		    "structure\n");
265909Segillett 		return;
266909Segillett 	}
267909Segillett 
268909Segillett 	/* Read in px_ib_ino_info_t structure at address */
269909Segillett 	px_ib_ino_lst = px_ib.ib_ino_lst;
270909Segillett 	if (mdb_vread(&px_list, sizeof (px_ib_ino_info_t),
271909Segillett 	    (uintptr_t)px_ib_ino_lst) == -1) {
272909Segillett 		/* Nothing here to read from */
273909Segillett 		return;
274909Segillett 	}
275909Segillett 
276909Segillett 	do {
277909Segillett 		if (mdb_vread(&px_ih, sizeof (px_ih_t),
278909Segillett 		    (uintptr_t)px_list.ino_ih_start) == -1) {
279909Segillett 			mdb_warn("intr: failed to read px interrupt entry "
280909Segillett 			    "structure\n");
281909Segillett 			return;
282909Segillett 		}
283909Segillett 
284909Segillett 		count = 0;
285909Segillett 
286909Segillett 		do {
287909Segillett 			bzero((void *)&info, sizeof (intr_info_t));
288909Segillett 
289909Segillett 			if (px_list.ino_ih_size > 1) {
290909Segillett 				info.shared = 1;
291909Segillett 			}
292909Segillett 
293909Segillett 			(void) mdb_devinfo2driver((uintptr_t)px_ih.ih_dip,
294909Segillett 			    name, sizeof (name));
295909Segillett 
296909Segillett 			(void) mdb_ddi_pathname((uintptr_t)px_ih.ih_dip,
297909Segillett 			    info.pathname, sizeof (info.pathname));
298909Segillett 
299909Segillett 			/* Get instance */
300909Segillett 			if (mdb_vread(&devinfo, sizeof (struct dev_info),
301909Segillett 			    (uintptr_t)px_ih.ih_dip) == -1) {
302909Segillett 				mdb_warn("intr: failed to read DIP "
303909Segillett 				    "structure\n");
304909Segillett 				return;
305909Segillett 			}
306909Segillett 
307909Segillett 			/* Make sure the name doesn't over run */
308909Segillett 			(void) mdb_snprintf(info.driver_name,
309909Segillett 			    sizeof (info.driver_name), "%s", name);
310909Segillett 
311909Segillett 			info.instance = devinfo.devi_instance;
312909Segillett 			info.inum = px_ih.ih_inum;
313909Segillett 			info.intr_type = px_ih.ih_rec_type;
314909Segillett 			info.num = px_ih.ih_msg_code;
315909Segillett 			info.intr_state = px_ih.ih_intr_state;
316909Segillett 			info.ino_ino = px_list.ino_ino;
317909Segillett 			info.mondo = px_list.ino_sysino;
318909Segillett 			info.pil = px_list.ino_pil;
319909Segillett 			info.cpuid = px_list.ino_cpuid;
320909Segillett 
321909Segillett 			intr_print_elements(info);
322909Segillett 			count++;
323909Segillett 
324909Segillett 			(void) mdb_vread(&px_ih, sizeof (ih_t),
325909Segillett 			    (uintptr_t)px_ih.ih_next);
326909Segillett 
327909Segillett 		} while (count < px_list.ino_ih_size);
328909Segillett 
329909Segillett 	} while (mdb_vread(&px_list, sizeof (px_ib_ino_info_t),
330909Segillett 	    (uintptr_t)px_list.ino_next) != -1);
331909Segillett }
332909Segillett 
333909Segillett static char *
334909Segillett intr_get_intr_type(msiq_rec_type_t rec_type)
335909Segillett {
336909Segillett 	switch (rec_type) {
337909Segillett 		case	MSG_REC:
338909Segillett 			return ("PCIe");
339909Segillett 		case	MSI32_REC:
340909Segillett 		case	MSI64_REC:
341909Segillett 			return ("MSI");
342909Segillett 		case	INTX_REC:
343909Segillett 		default:
344909Segillett 			return ("Fixed");
345909Segillett 	}
346909Segillett }
347909Segillett 
348909Segillett static void
349909Segillett intr_print_banner(void)
350909Segillett {
351909Segillett 	if (!detailed) {
352*965Sgovinda 		mdb_printf("\n%<u>\tDevice\t"
353*965Sgovinda 		    " Shared\t"
354*965Sgovinda 		    " Type\t"
355*965Sgovinda 		    " MSG #\t"
356*965Sgovinda 		    " State\t"
357*965Sgovinda 		    " INO\t"
358*965Sgovinda 		    " Mondo\t"
359*965Sgovinda 		    "  Pil\t"
360*965Sgovinda 		    " CPU   %</u>"
361*965Sgovinda 		    "\n");
362909Segillett 	}
363909Segillett }
364909Segillett 
365909Segillett static void
366909Segillett intr_print_elements(intr_info_t info)
367909Segillett {
368909Segillett 	if (!detailed) {
369*965Sgovinda 		mdb_printf(" %11s#%d\t", info.driver_name, info.instance);
370*965Sgovinda 		mdb_printf(" %5s\t",
371909Segillett 		    info.shared ? "yes" : "no");
372*965Sgovinda 		mdb_printf(" %s\t", intr_get_intr_type(info.intr_type));
373909Segillett 		if (strcmp("Fixed", intr_get_intr_type(info.intr_type)) == 0) {
374*965Sgovinda 			mdb_printf("  --- \t");
375909Segillett 		} else {
376*965Sgovinda 			mdb_printf(" %4d\t", info.num);
377909Segillett 		}
378909Segillett 
379*965Sgovinda 		mdb_printf(" %2s\t",
380909Segillett 		    info.intr_state ? "enbl" : "disbl");
381*965Sgovinda 		mdb_printf(" 0x%x\t", info.ino_ino);
382*965Sgovinda 		mdb_printf(" 0x%x\t", info.mondo);
383*965Sgovinda 		mdb_printf(" %4d\t", info.pil);
384*965Sgovinda 		mdb_printf(" %3d \n", info.cpuid);
385909Segillett 	} else {
386909Segillett 		mdb_printf("\n-------------------------------------------\n");
387909Segillett 		mdb_printf("Device:\t\t%s\n", info.driver_name);
388909Segillett 		mdb_printf("Instance:\t%d\n", info.instance);
389909Segillett 		mdb_printf("Path:\t\t%s\n", info.pathname);
390909Segillett 		mdb_printf("Inum:\t\t%d\n", info.inum);
391909Segillett 		mdb_printf("Interrupt Type:\t%s\n",
392909Segillett 		    intr_get_intr_type(info.intr_type));
393909Segillett 		if (strcmp("MSI", intr_get_intr_type(info.intr_type)) == 0)
394909Segillett 			mdb_printf("MSI/X Number:\t%s\n", info.num);
395909Segillett 
396909Segillett 		mdb_printf("Shared Intr:\t%s\n",
397909Segillett 		    info.shared ? "yes" : "no");
398909Segillett 		mdb_printf("State:\t\t%d (%s)\n", info.intr_state,
399909Segillett 		    info.intr_state ? "Enabled" : "Disabled");
400909Segillett 		mdb_printf("INO:\t\t0x%x\n", info.ino_ino);
401909Segillett 		mdb_printf("Mondo:\t\t0x%x\n", info.mondo);
402909Segillett 		mdb_printf("Pil:\t\t%d\n", info.pil);
403909Segillett 		mdb_printf("CPU:\t\t%d\n", info.cpuid);
404909Segillett 	}
405909Segillett }
406909Segillett 
407909Segillett /*ARGSUSED*/
408909Segillett static void
409909Segillett intr_walk_fini(mdb_walk_state_t *wsp)
410909Segillett {
411909Segillett 	/* Nothing to do here */
412909Segillett }
413909Segillett 
414909Segillett /*ARGSUSED*/
415909Segillett static int
416909Segillett intr_intr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
417909Segillett {
418909Segillett 	detailed = 0;
419909Segillett 
420909Segillett 	if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &detailed,
421909Segillett 	    NULL) != argc)
422909Segillett 		return (DCMD_USAGE);
423909Segillett 
424909Segillett 	if (!(flags & DCMD_ADDRSPEC)) {
425909Segillett 		if (mdb_walk_dcmd("interrupts", "interrupts", argc, argv)
426909Segillett 		    == -1) {
427909Segillett 			mdb_warn("can't walk pci/px buffer entries\n");
428909Segillett 			return (DCMD_ERR);
429909Segillett 		}
430909Segillett 		return (DCMD_OK);
431909Segillett 	}
432909Segillett 
433909Segillett 	return (DCMD_OK);
434909Segillett }
435909Segillett 
436909Segillett /*
437909Segillett  * MDB module linkage information:
438909Segillett  */
439909Segillett 
440909Segillett static const mdb_dcmd_t dcmds[] = {
441909Segillett 	{ "interrupts", "[-d]", "display the interrupt info registered with "
442909Segillett 	    "the PCI/PX nexus drivers", intr_intr },
443909Segillett 	{ NULL }
444909Segillett };
445909Segillett 
446909Segillett static const mdb_walker_t walkers[] = {
447909Segillett 	{ "interrupts", "walk PCI/PX interrupt structures",
448909Segillett 		intr_walk_init, intr_walk_step, intr_walk_fini },
449909Segillett 	{ NULL }
450909Segillett };
451909Segillett 
452909Segillett static const mdb_modinfo_t modinfo = {
453909Segillett 	MDB_API_VERSION, dcmds, walkers
454909Segillett };
455909Segillett 
456909Segillett const mdb_modinfo_t *
457909Segillett _mdb_init(void)
458909Segillett {
459909Segillett 	return (&modinfo);
460909Segillett }
461