1*7ff178cdSJimmy Vetayases /*
2*7ff178cdSJimmy Vetayases * CDDL HEADER START
3*7ff178cdSJimmy Vetayases *
4*7ff178cdSJimmy Vetayases * The contents of this file are subject to the terms of the
5*7ff178cdSJimmy Vetayases * Common Development and Distribution License (the "License").
6*7ff178cdSJimmy Vetayases * You may not use this file except in compliance with the License.
7*7ff178cdSJimmy Vetayases *
8*7ff178cdSJimmy Vetayases * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7ff178cdSJimmy Vetayases * or http://www.opensolaris.org/os/licensing.
10*7ff178cdSJimmy Vetayases * See the License for the specific language governing permissions
11*7ff178cdSJimmy Vetayases * and limitations under the License.
12*7ff178cdSJimmy Vetayases *
13*7ff178cdSJimmy Vetayases * When distributing Covered Code, include this CDDL HEADER in each
14*7ff178cdSJimmy Vetayases * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7ff178cdSJimmy Vetayases * If applicable, add the following below this CDDL HEADER, with the
16*7ff178cdSJimmy Vetayases * fields enclosed by brackets "[]" replaced with your own identifying
17*7ff178cdSJimmy Vetayases * information: Portions Copyright [yyyy] [name of copyright owner]
18*7ff178cdSJimmy Vetayases *
19*7ff178cdSJimmy Vetayases * CDDL HEADER END
20*7ff178cdSJimmy Vetayases */
21*7ff178cdSJimmy Vetayases /*
22*7ff178cdSJimmy Vetayases * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*7ff178cdSJimmy Vetayases */
24*7ff178cdSJimmy Vetayases
25*7ff178cdSJimmy Vetayases #include "intr_common.h"
26*7ff178cdSJimmy Vetayases
27*7ff178cdSJimmy Vetayases /*
28*7ff178cdSJimmy Vetayases * Globals
29*7ff178cdSJimmy Vetayases */
30*7ff178cdSJimmy Vetayases static apic_irq_t *irq_tbl[APIC_MAX_VECTOR+1];
31*7ff178cdSJimmy Vetayases static char level_tbl[APIC_MAX_VECTOR+1];
32*7ff178cdSJimmy Vetayases static apix_impl_t *d_apixs[NCPU];
33*7ff178cdSJimmy Vetayases static int d_ncpus = NCPU;
34*7ff178cdSJimmy Vetayases
35*7ff178cdSJimmy Vetayases
36*7ff178cdSJimmy Vetayases /*
37*7ff178cdSJimmy Vetayases * Dump interrupt information for apix PSM.
38*7ff178cdSJimmy Vetayases */
39*7ff178cdSJimmy Vetayases /* ARGSUSED */
40*7ff178cdSJimmy Vetayases int
interrupt_dump_apix(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)41*7ff178cdSJimmy Vetayases interrupt_dump_apix(uintptr_t addr, uint_t flags, int argc,
42*7ff178cdSJimmy Vetayases const mdb_arg_t *argv)
43*7ff178cdSJimmy Vetayases {
44*7ff178cdSJimmy Vetayases int i, j;
45*7ff178cdSJimmy Vetayases apix_impl_t apix;
46*7ff178cdSJimmy Vetayases apix_vector_t apix_vector;
47*7ff178cdSJimmy Vetayases struct autovec av;
48*7ff178cdSJimmy Vetayases apic_irq_t apic_irq;
49*7ff178cdSJimmy Vetayases
50*7ff178cdSJimmy Vetayases option_flags = 0;
51*7ff178cdSJimmy Vetayases if (mdb_getopts(argc, argv,
52*7ff178cdSJimmy Vetayases 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags,
53*7ff178cdSJimmy Vetayases 'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags,
54*7ff178cdSJimmy Vetayases NULL) != argc)
55*7ff178cdSJimmy Vetayases return (DCMD_USAGE);
56*7ff178cdSJimmy Vetayases
57*7ff178cdSJimmy Vetayases if (mdb_readvar(&d_apixs, "apixs") == -1) {
58*7ff178cdSJimmy Vetayases mdb_warn("failed to read apixs");
59*7ff178cdSJimmy Vetayases return (DCMD_ERR);
60*7ff178cdSJimmy Vetayases }
61*7ff178cdSJimmy Vetayases
62*7ff178cdSJimmy Vetayases if (mdb_readvar(&d_ncpus, "apic_nproc") == -1) {
63*7ff178cdSJimmy Vetayases mdb_warn("failed to read apic_nproc");
64*7ff178cdSJimmy Vetayases d_ncpus = NCPU;
65*7ff178cdSJimmy Vetayases }
66*7ff178cdSJimmy Vetayases if (d_ncpus == 0 || d_ncpus > NCPU)
67*7ff178cdSJimmy Vetayases d_ncpus = NCPU;
68*7ff178cdSJimmy Vetayases
69*7ff178cdSJimmy Vetayases if (mdb_readvar(&irq_tbl, "apic_irq_table") == -1) {
70*7ff178cdSJimmy Vetayases mdb_warn("failed to read apic_irq_table");
71*7ff178cdSJimmy Vetayases return (DCMD_ERR);
72*7ff178cdSJimmy Vetayases }
73*7ff178cdSJimmy Vetayases
74*7ff178cdSJimmy Vetayases if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) {
75*7ff178cdSJimmy Vetayases mdb_warn("failed to read apic_level_intr");
76*7ff178cdSJimmy Vetayases return (DCMD_ERR);
77*7ff178cdSJimmy Vetayases }
78*7ff178cdSJimmy Vetayases
79*7ff178cdSJimmy Vetayases /* Print the header first */
80*7ff178cdSJimmy Vetayases if (option_flags & INTR_DISPLAY_INTRSTAT)
81*7ff178cdSJimmy Vetayases mdb_printf("%<u>CPU ");
82*7ff178cdSJimmy Vetayases else
83*7ff178cdSJimmy Vetayases mdb_printf("%<u>CPU/Vect IRQ IPL Bus Trg Type "
84*7ff178cdSJimmy Vetayases "Share APIC/INT# ");
85*7ff178cdSJimmy Vetayases mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ?
86*7ff178cdSJimmy Vetayases "Driver Name(s)" : "ISR");
87*7ff178cdSJimmy Vetayases
88*7ff178cdSJimmy Vetayases /* Walk all the entries */
89*7ff178cdSJimmy Vetayases for (i = 0; i < d_ncpus; i++) {
90*7ff178cdSJimmy Vetayases /* Read the per CPU apix entry */
91*7ff178cdSJimmy Vetayases if (mdb_vread(&apix, sizeof (apix_impl_t),
92*7ff178cdSJimmy Vetayases (uintptr_t)d_apixs[i]) == -1)
93*7ff178cdSJimmy Vetayases continue;
94*7ff178cdSJimmy Vetayases for (j = 0; j < APIX_NVECTOR; j++) {
95*7ff178cdSJimmy Vetayases /* Read the vector entry */
96*7ff178cdSJimmy Vetayases if (mdb_vread(&apix_vector, sizeof (apix_vector_t),
97*7ff178cdSJimmy Vetayases (uintptr_t)apix.x_vectbl[j]) == -1)
98*7ff178cdSJimmy Vetayases continue;
99*7ff178cdSJimmy Vetayases /* If invalid vector state; continue */
100*7ff178cdSJimmy Vetayases if (apix_vector.v_state == APIX_STATE_FREED ||
101*7ff178cdSJimmy Vetayases apix_vector.v_state == APIX_STATE_OBSOLETED)
102*7ff178cdSJimmy Vetayases continue;
103*7ff178cdSJimmy Vetayases if (apix_vector.v_type == APIX_TYPE_IPI)
104*7ff178cdSJimmy Vetayases continue;
105*7ff178cdSJimmy Vetayases if (mdb_vread(&av, sizeof (struct autovec),
106*7ff178cdSJimmy Vetayases (uintptr_t)(apix_vector.v_autovect)) == -1)
107*7ff178cdSJimmy Vetayases continue;
108*7ff178cdSJimmy Vetayases if ((apix_vector.v_type == APIX_TYPE_FIXED) &&
109*7ff178cdSJimmy Vetayases (mdb_vread(&apic_irq, sizeof (apic_irq_t),
110*7ff178cdSJimmy Vetayases (uintptr_t)irq_tbl[apix_vector.v_inum]) == -1))
111*7ff178cdSJimmy Vetayases continue;
112*7ff178cdSJimmy Vetayases
113*7ff178cdSJimmy Vetayases apix_interrupt_dump(&apix_vector, &apic_irq, &av,
114*7ff178cdSJimmy Vetayases NULL, level_tbl[apix_vector.v_inum]);
115*7ff178cdSJimmy Vetayases }
116*7ff178cdSJimmy Vetayases }
117*7ff178cdSJimmy Vetayases /* print IPIs */
118*7ff178cdSJimmy Vetayases if (mdb_vread(&apix, sizeof (apix_impl_t),
119*7ff178cdSJimmy Vetayases (uintptr_t)d_apixs[0]) != -1) {
120*7ff178cdSJimmy Vetayases for (j = 0; j < APIX_NVECTOR; j++) {
121*7ff178cdSJimmy Vetayases /* Read the vector entry */
122*7ff178cdSJimmy Vetayases if (mdb_vread(&apix_vector, sizeof (apix_vector_t),
123*7ff178cdSJimmy Vetayases (uintptr_t)apix.x_vectbl[j]) == -1)
124*7ff178cdSJimmy Vetayases continue;
125*7ff178cdSJimmy Vetayases /* If invalid vector state; continue */
126*7ff178cdSJimmy Vetayases if (apix_vector.v_state == APIX_STATE_FREED ||
127*7ff178cdSJimmy Vetayases apix_vector.v_state == APIX_STATE_OBSOLETED)
128*7ff178cdSJimmy Vetayases continue;
129*7ff178cdSJimmy Vetayases if (apix_vector.v_type != APIX_TYPE_IPI)
130*7ff178cdSJimmy Vetayases continue;
131*7ff178cdSJimmy Vetayases if (mdb_vread(&av, sizeof (struct autovec),
132*7ff178cdSJimmy Vetayases (uintptr_t)(apix_vector.v_autovect)) == -1) {
133*7ff178cdSJimmy Vetayases /* v_share for poke_cpu is 0 */
134*7ff178cdSJimmy Vetayases if (apix_vector.v_share != 0)
135*7ff178cdSJimmy Vetayases continue;
136*7ff178cdSJimmy Vetayases }
137*7ff178cdSJimmy Vetayases apix_interrupt_ipi_dump(&apix_vector, &av, NULL);
138*7ff178cdSJimmy Vetayases }
139*7ff178cdSJimmy Vetayases }
140*7ff178cdSJimmy Vetayases
141*7ff178cdSJimmy Vetayases return (DCMD_OK);
142*7ff178cdSJimmy Vetayases }
143*7ff178cdSJimmy Vetayases
144*7ff178cdSJimmy Vetayases /*
145*7ff178cdSJimmy Vetayases * MDB module linkage information:
146*7ff178cdSJimmy Vetayases *
147*7ff178cdSJimmy Vetayases * We declare a list of structures describing our dcmds, and a function
148*7ff178cdSJimmy Vetayases * named _mdb_init to return a pointer to our module information.
149*7ff178cdSJimmy Vetayases */
150*7ff178cdSJimmy Vetayases static const mdb_dcmd_t dcmds[] = {
151*7ff178cdSJimmy Vetayases { "interrupts", "?[-di]", "print interrupts", interrupt_dump_apix,
152*7ff178cdSJimmy Vetayases interrupt_help},
153*7ff178cdSJimmy Vetayases { "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump,
154*7ff178cdSJimmy Vetayases soft_interrupt_help},
1555cd376e8SJimmy Vetayases #ifdef _KMDB
156*7ff178cdSJimmy Vetayases { "apic", NULL, "print apic register contents", apic },
157*7ff178cdSJimmy Vetayases { "ioapic", NULL, "print ioapic register contents", ioapic },
1585cd376e8SJimmy Vetayases #endif /* _KMDB */
159*7ff178cdSJimmy Vetayases { NULL }
160*7ff178cdSJimmy Vetayases };
161*7ff178cdSJimmy Vetayases
162*7ff178cdSJimmy Vetayases static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL };
163*7ff178cdSJimmy Vetayases
164*7ff178cdSJimmy Vetayases const mdb_modinfo_t *
_mdb_init(void)165*7ff178cdSJimmy Vetayases _mdb_init(void)
166*7ff178cdSJimmy Vetayases {
167*7ff178cdSJimmy Vetayases GElf_Sym sym;
168*7ff178cdSJimmy Vetayases
169*7ff178cdSJimmy Vetayases if (mdb_lookup_by_name("gld_intr", &sym) != -1)
170*7ff178cdSJimmy Vetayases if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
171*7ff178cdSJimmy Vetayases gld_intr_addr = (uintptr_t)sym.st_value;
172*7ff178cdSJimmy Vetayases
173*7ff178cdSJimmy Vetayases return (&modinfo);
174*7ff178cdSJimmy Vetayases }
175