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
interrupt_dump_apic(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
_mdb_init(void)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