xref: /illumos-gate/usr/src/cmd/mdb/i86pc/modules/pcplusmp/pcplusmp.c (revision 41afdfa77f9af46beb3aaab2eccc0d9afe660d31)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include "intr_common.h"
26 #include <sys/apic_timer.h>
27 
28 /*
29  * Globals
30  */
31 static struct av_head	avec_tbl[APIC_MAX_VECTOR+1];
32 static apic_irq_t	*irq_tbl[APIC_MAX_VECTOR+1], airq;
33 static char		level_tbl[APIC_MAX_VECTOR+1];
34 
35 /*
36  * Dump interrupt information for pcplusmp PSM.
37  */
38 /* ARGSUSED */
39 int
40 interrupt_dump_apic(uintptr_t addr, uint_t flags, int argc,
41     const mdb_arg_t *argv)
42 {
43 	int		i;
44 
45 	option_flags = 0;
46 	if (mdb_getopts(argc, argv,
47 	    'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags,
48 	    'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags,
49 	    NULL) != argc)
50 		return (DCMD_USAGE);
51 
52 	if (mdb_readvar(&irq_tbl, "apic_irq_table") == -1) {
53 		mdb_warn("failed to read apic_irq_table");
54 		return (DCMD_ERR);
55 	}
56 
57 	if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) {
58 		mdb_warn("failed to read apic_level_intr");
59 		return (DCMD_ERR);
60 	}
61 
62 	if (mdb_readvar(&avec_tbl, "autovect") == -1) {
63 		mdb_warn("failed to read autovect");
64 		return (DCMD_ERR);
65 	}
66 
67 	/* Print the header first */
68 	if (option_flags & INTR_DISPLAY_INTRSTAT)
69 		mdb_printf("%<u>CPU ");
70 	else
71 		mdb_printf(
72 		    "%<u>IRQ  Vect IPL Bus    Trg Type   CPU Share APIC/INT# ");
73 	mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ?
74 	    "Driver Name(s)" : "ISR(s)");
75 
76 	/* Walk all the entries */
77 	for (i = 0; i < APIC_MAX_VECTOR + 1; i++) {
78 		/* Read the entry */
79 		if (mdb_vread(&airq, sizeof (apic_irq_t),
80 		    (uintptr_t)irq_tbl[i]) == -1)
81 			continue;
82 
83 		apic_interrupt_dump(&airq, &avec_tbl[i], i, NULL, level_tbl[i]);
84 	}
85 
86 	return (DCMD_OK);
87 }
88 
89 
90 /*
91  * MDB module linkage information:
92  *
93  * We declare a list of structures describing our dcmds, and a function
94  * named _mdb_init to return a pointer to our module information.
95  */
96 static const mdb_dcmd_t dcmds[] = {
97 	{ "interrupts", "?[-di]", "print interrupts", interrupt_dump_apic,
98 	    interrupt_help},
99 	{ "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump,
100 	    soft_interrupt_help},
101 #ifdef _KMDB
102 	{ "apic", NULL, "print apic register contents", apic },
103 	{ "ioapic", NULL, "print ioapic register contents", ioapic },
104 #endif /* _KMDB */
105 	{ NULL }
106 };
107 
108 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL };
109 
110 const mdb_modinfo_t *
111 _mdb_init(void)
112 {
113 	GElf_Sym	sym;
114 
115 	if (mdb_lookup_by_name("gld_intr", &sym) != -1)
116 		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
117 			gld_intr_addr = (uintptr_t)sym.st_value;
118 
119 	return (&modinfo);
120 }
121