xref: /titanic_41/usr/src/cmd/mdb/sparc/modules/intr/intr.c (revision 4f85d229295a756a4e6f1759b47df7b97412db7d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/mdb_modapi.h>
30 #include <mdb/mdb_ks.h>
31 #include <sys/async.h>		/* ecc_flt for pci_ecc.h */
32 #include <sys/ddi_subrdefs.h>
33 #include <sys/pci/pci_obj.h>
34 #include "px_obj.h"
35 
36 static int intr_pci_walk_step(mdb_walk_state_t *);
37 static int intr_px_walk_step(mdb_walk_state_t *);
38 static void intr_pci_print_items(mdb_walk_state_t *);
39 static void intr_px_print_items(mdb_walk_state_t *);
40 static char *intr_get_intr_type(msiq_rec_type_t);
41 static void intr_print_banner(void);
42 
43 typedef struct intr_info {
44 	uint32_t	cpuid;
45 	uint32_t	inum;
46 	uint32_t	num;
47 	uint32_t	pil;
48 	uint16_t	mondo;
49 	uint8_t		ino_ino;
50 	uint_t		intr_state;
51 	int		instance;
52 	int		shared;
53 	msiq_rec_type_t intr_type;
54 	char		driver_name[12];
55 	char		pathname[MAXNAMELEN];
56 }
57 intr_info_t;
58 
59 static void intr_print_elements(intr_info_t);
60 static int detailed = 0; /* Print detailed view */
61 
62 
63 static int
64 intr_walk_init(mdb_walk_state_t *wsp)
65 {
66 	wsp->walk_addr = NULL;
67 
68 	return (WALK_NEXT);
69 }
70 
71 static int
72 intr_walk_step(mdb_walk_state_t *wsp)
73 {
74 	pci_t		*pci_per_p;
75 	px_t		*px_state_p;
76 
77 	/* read globally declared structures in the pci driver */
78 	if (mdb_readvar(&pci_per_p, "per_pci_state") != -1) {
79 		wsp->walk_addr = (uintptr_t)pci_per_p;
80 		intr_pci_walk_step(wsp);
81 	}
82 
83 	/* read globally declared structures in the px driver */
84 	if (mdb_readvar(&px_state_p, "px_state_p") != -1) {
85 		wsp->walk_addr = (uintptr_t)px_state_p;
86 		intr_px_walk_step(wsp);
87 	}
88 
89 	return (WALK_DONE);
90 }
91 
92 static int
93 intr_pci_walk_step(mdb_walk_state_t *wsp)
94 {
95 	pci_t		*pci_per_p;
96 	pci_t		pci_per;
97 	uintptr_t	start_addr;
98 
99 	/* Read start of state structure array */
100 	if (mdb_vread(&pci_per_p, sizeof (uintptr_t),
101 	    (uintptr_t)wsp->walk_addr) == -1) {
102 		mdb_warn("intr: failed to read the initial pci_per_p "
103 		    "structure\n");
104 		return (WALK_ERR);
105 	}
106 
107 	/* Figure out how many items are here */
108 	start_addr = (uintptr_t)pci_per_p;
109 
110 	intr_print_banner();
111 
112 	while (mdb_vread(&pci_per_p, sizeof (uintptr_t),
113 	    (uintptr_t)start_addr) != -1) {
114 		/* Read until nothing is left */
115 		if (mdb_vread(&pci_per, sizeof (pci_t),
116 		    (uintptr_t)pci_per_p) == -1) {
117 			return (WALK_DONE);
118 		}
119 
120 		wsp->walk_addr = (uintptr_t)pci_per.pci_ib_p;
121 		intr_pci_print_items(wsp);
122 
123 		start_addr += sizeof (uintptr_t);
124 	}
125 
126 	return (WALK_DONE);
127 }
128 
129 static int
130 intr_px_walk_step(mdb_walk_state_t *wsp)
131 {
132 	px_t		*px_state_p;
133 	px_t		px_state;
134 	uintptr_t	start_addr;
135 
136 	/* Read start of state structure array */
137 	if (mdb_vread(&px_state_p, sizeof (uintptr_t),
138 	    (uintptr_t)wsp->walk_addr) == -1) {
139 		mdb_warn("intr: failed to read the initial px_per_p "
140 		    "structure\n");
141 		return (WALK_ERR);
142 	}
143 
144 	/* Figure out how many items are here */
145 	start_addr = (uintptr_t)px_state_p;
146 
147 	intr_print_banner();
148 
149 	while (mdb_vread(&px_state_p, sizeof (uintptr_t),
150 	    (uintptr_t)start_addr) != -1) {
151 		/* Read until nothing is left */
152 		if (mdb_vread(&px_state, sizeof (px_t),
153 		    (uintptr_t)px_state_p) == -1) {
154 			return (WALK_DONE);
155 		}
156 
157 		wsp->walk_addr = (uintptr_t)px_state.px_ib_p;
158 		intr_px_print_items(wsp);
159 
160 		start_addr += sizeof (uintptr_t);
161 	}
162 
163 	return (WALK_DONE);
164 }
165 
166 static void
167 intr_pci_print_items(mdb_walk_state_t *wsp)
168 {
169 	ib_t			pci_ib;
170 	ib_ino_info_t		*ib_ino_lst;
171 	ib_ino_info_t		list;
172 	ih_t			ih;
173 	int			count;
174 	char			name[MODMAXNAMELEN + 1];
175 	struct dev_info		devinfo;
176 	intr_info_t		info;
177 
178 	if (mdb_vread(&pci_ib, sizeof (ib_t),
179 	    (uintptr_t)wsp->walk_addr) == -1) {
180 		mdb_warn("intr: failed to read pci interrupt block "
181 		    "structure\n");
182 		return;
183 	}
184 
185 	/* Read in ib_ino_info_t structure at address */
186 	ib_ino_lst = pci_ib.ib_ino_lst;
187 	if (mdb_vread(&list, sizeof (ib_ino_info_t),
188 	    (uintptr_t)ib_ino_lst) == -1) {
189 		/* Nothing here to read from */
190 		return;
191 	}
192 
193 	do {
194 		if (mdb_vread(&ih, sizeof (ih_t),
195 		    (uintptr_t)list.ino_ih_start) == -1) {
196 			mdb_warn("intr: failed to read pci interrupt entry "
197 			    "structure\n");
198 			return;
199 		}
200 
201 		count = 0;
202 
203 		do {
204 			bzero((void *)&info, sizeof (intr_info_t));
205 
206 			if (list.ino_ih_size > 1) {
207 				info.shared = 1;
208 			}
209 
210 			(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
211 			    name, sizeof (name));
212 
213 			(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
214 			    info.pathname, sizeof (info.pathname));
215 
216 			/* Get instance */
217 			if (mdb_vread(&devinfo, sizeof (struct dev_info),
218 			    (uintptr_t)ih.ih_dip) == -1) {
219 				mdb_warn("intr: failed to read DIP "
220 				    "structure\n");
221 				return;
222 			}
223 
224 			/* Make sure the name doesn't over run */
225 			(void) mdb_snprintf(info.driver_name,
226 			    sizeof (info.driver_name), "%s", name);
227 
228 			info.instance = devinfo.devi_instance;
229 			info.inum = ih.ih_inum;
230 			info.intr_type = INTX_REC;
231 			info.num = 0;
232 			info.intr_state = ih.ih_intr_state;
233 			info.ino_ino = list.ino_ino;
234 			info.mondo = list.ino_mondo;
235 			info.pil = list.ino_pil;
236 			info.cpuid = list.ino_cpuid;
237 
238 			intr_print_elements(info);
239 			count++;
240 
241 			(void) mdb_vread(&ih, sizeof (ih_t),
242 			    (uintptr_t)ih.ih_next);
243 
244 		} while (count < list.ino_ih_size);
245 
246 	} while (mdb_vread(&list, sizeof (ib_ino_info_t),
247 	    (uintptr_t)list.ino_next) != -1);
248 }
249 
250 static void
251 intr_px_print_items(mdb_walk_state_t *wsp)
252 {
253 	px_ib_t			px_ib;
254 	px_ib_ino_info_t	*px_ib_ino_lst;
255 	px_ib_ino_info_t	px_list;
256 	px_ih_t			px_ih;
257 	int			count;
258 	char			name[MODMAXNAMELEN + 1];
259 	struct dev_info		devinfo;
260 	intr_info_t		info;
261 
262 	if (mdb_vread(&px_ib, sizeof (px_ib_t), wsp->walk_addr) == -1) {
263 		mdb_warn("intr: failed to read px interrupt block "
264 		    "structure\n");
265 		return;
266 	}
267 
268 	/* Read in px_ib_ino_info_t structure at address */
269 	px_ib_ino_lst = px_ib.ib_ino_lst;
270 	if (mdb_vread(&px_list, sizeof (px_ib_ino_info_t),
271 	    (uintptr_t)px_ib_ino_lst) == -1) {
272 		/* Nothing here to read from */
273 		return;
274 	}
275 
276 	do {
277 		if (mdb_vread(&px_ih, sizeof (px_ih_t),
278 		    (uintptr_t)px_list.ino_ih_start) == -1) {
279 			mdb_warn("intr: failed to read px interrupt entry "
280 			    "structure\n");
281 			return;
282 		}
283 
284 		count = 0;
285 
286 		do {
287 			bzero((void *)&info, sizeof (intr_info_t));
288 
289 			if (px_list.ino_ih_size > 1) {
290 				info.shared = 1;
291 			}
292 
293 			(void) mdb_devinfo2driver((uintptr_t)px_ih.ih_dip,
294 			    name, sizeof (name));
295 
296 			(void) mdb_ddi_pathname((uintptr_t)px_ih.ih_dip,
297 			    info.pathname, sizeof (info.pathname));
298 
299 			/* Get instance */
300 			if (mdb_vread(&devinfo, sizeof (struct dev_info),
301 			    (uintptr_t)px_ih.ih_dip) == -1) {
302 				mdb_warn("intr: failed to read DIP "
303 				    "structure\n");
304 				return;
305 			}
306 
307 			/* Make sure the name doesn't over run */
308 			(void) mdb_snprintf(info.driver_name,
309 			    sizeof (info.driver_name), "%s", name);
310 
311 			info.instance = devinfo.devi_instance;
312 			info.inum = px_ih.ih_inum;
313 			info.intr_type = px_ih.ih_rec_type;
314 			info.num = px_ih.ih_msg_code;
315 			info.intr_state = px_ih.ih_intr_state;
316 			info.ino_ino = px_list.ino_ino;
317 			info.mondo = px_list.ino_sysino;
318 			info.pil = px_list.ino_pil;
319 			info.cpuid = px_list.ino_cpuid;
320 
321 			intr_print_elements(info);
322 			count++;
323 
324 			(void) mdb_vread(&px_ih, sizeof (ih_t),
325 			    (uintptr_t)px_ih.ih_next);
326 
327 		} while (count < px_list.ino_ih_size);
328 
329 	} while (mdb_vread(&px_list, sizeof (px_ib_ino_info_t),
330 	    (uintptr_t)px_list.ino_next) != -1);
331 }
332 
333 static char *
334 intr_get_intr_type(msiq_rec_type_t rec_type)
335 {
336 	switch (rec_type) {
337 		case	MSG_REC:
338 			return ("PCIe");
339 		case	MSI32_REC:
340 		case	MSI64_REC:
341 			return ("MSI");
342 		case	INTX_REC:
343 		default:
344 			return ("Fixed");
345 	}
346 }
347 
348 static void
349 intr_print_banner(void)
350 {
351 	if (!detailed) {
352 		mdb_printf("\n%<u>\tDevice\t"
353 		    " Shared\t"
354 		    " Type\t"
355 		    " MSG #\t"
356 		    " State\t"
357 		    " INO\t"
358 		    " Mondo\t"
359 		    "  Pil\t"
360 		    " CPU   %</u>"
361 		    "\n");
362 	}
363 }
364 
365 static void
366 intr_print_elements(intr_info_t info)
367 {
368 	if (!detailed) {
369 		mdb_printf(" %11s#%d\t", info.driver_name, info.instance);
370 		mdb_printf(" %5s\t",
371 		    info.shared ? "yes" : "no");
372 		mdb_printf(" %s\t", intr_get_intr_type(info.intr_type));
373 		if (strcmp("Fixed", intr_get_intr_type(info.intr_type)) == 0) {
374 			mdb_printf("  --- \t");
375 		} else {
376 			mdb_printf(" %4d\t", info.num);
377 		}
378 
379 		mdb_printf(" %2s\t",
380 		    info.intr_state ? "enbl" : "disbl");
381 		mdb_printf(" 0x%x\t", info.ino_ino);
382 		mdb_printf(" 0x%x\t", info.mondo);
383 		mdb_printf(" %4d\t", info.pil);
384 		mdb_printf(" %3d \n", info.cpuid);
385 	} else {
386 		mdb_printf("\n-------------------------------------------\n");
387 		mdb_printf("Device:\t\t%s\n", info.driver_name);
388 		mdb_printf("Instance:\t%d\n", info.instance);
389 		mdb_printf("Path:\t\t%s\n", info.pathname);
390 		mdb_printf("Inum:\t\t%d\n", info.inum);
391 		mdb_printf("Interrupt Type:\t%s\n",
392 		    intr_get_intr_type(info.intr_type));
393 		if (strcmp("MSI", intr_get_intr_type(info.intr_type)) == 0)
394 			mdb_printf("MSI/X Number:\t%s\n", info.num);
395 
396 		mdb_printf("Shared Intr:\t%s\n",
397 		    info.shared ? "yes" : "no");
398 		mdb_printf("State:\t\t%d (%s)\n", info.intr_state,
399 		    info.intr_state ? "Enabled" : "Disabled");
400 		mdb_printf("INO:\t\t0x%x\n", info.ino_ino);
401 		mdb_printf("Mondo:\t\t0x%x\n", info.mondo);
402 		mdb_printf("Pil:\t\t%d\n", info.pil);
403 		mdb_printf("CPU:\t\t%d\n", info.cpuid);
404 	}
405 }
406 
407 /*ARGSUSED*/
408 static void
409 intr_walk_fini(mdb_walk_state_t *wsp)
410 {
411 	/* Nothing to do here */
412 }
413 
414 /*ARGSUSED*/
415 static int
416 intr_intr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
417 {
418 	detailed = 0;
419 
420 	if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &detailed,
421 	    NULL) != argc)
422 		return (DCMD_USAGE);
423 
424 	if (!(flags & DCMD_ADDRSPEC)) {
425 		if (mdb_walk_dcmd("interrupts", "interrupts", argc, argv)
426 		    == -1) {
427 			mdb_warn("can't walk pci/px buffer entries\n");
428 			return (DCMD_ERR);
429 		}
430 		return (DCMD_OK);
431 	}
432 
433 	return (DCMD_OK);
434 }
435 
436 /*
437  * MDB module linkage information:
438  */
439 
440 static const mdb_dcmd_t dcmds[] = {
441 	{ "interrupts", "[-d]", "display the interrupt info registered with "
442 	    "the PCI/PX nexus drivers", intr_intr },
443 	{ NULL }
444 };
445 
446 static const mdb_walker_t walkers[] = {
447 	{ "interrupts", "walk PCI/PX interrupt structures",
448 		intr_walk_init, intr_walk_step, intr_walk_fini },
449 	{ NULL }
450 };
451 
452 static const mdb_modinfo_t modinfo = {
453 	MDB_API_VERSION, dcmds, walkers
454 };
455 
456 const mdb_modinfo_t *
457 _mdb_init(void)
458 {
459 	return (&modinfo);
460 }
461