1cc7a88b5Smrj /*
2cc7a88b5Smrj * CDDL HEADER START
3cc7a88b5Smrj *
4cc7a88b5Smrj * The contents of this file are subject to the terms of the
5cc7a88b5Smrj * Common Development and Distribution License (the "License").
6cc7a88b5Smrj * You may not use this file except in compliance with the License.
7cc7a88b5Smrj *
8cc7a88b5Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cc7a88b5Smrj * or http://www.opensolaris.org/os/licensing.
10cc7a88b5Smrj * See the License for the specific language governing permissions
11cc7a88b5Smrj * and limitations under the License.
12cc7a88b5Smrj *
13cc7a88b5Smrj * When distributing Covered Code, include this CDDL HEADER in each
14cc7a88b5Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cc7a88b5Smrj * If applicable, add the following below this CDDL HEADER, with the
16cc7a88b5Smrj * fields enclosed by brackets "[]" replaced with your own identifying
17cc7a88b5Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
18cc7a88b5Smrj *
19cc7a88b5Smrj * CDDL HEADER END
20cc7a88b5Smrj */
21cc7a88b5Smrj /*
22cc7a88b5Smrj * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23cc7a88b5Smrj * Use is subject to license terms.
24cc7a88b5Smrj */
2528e4da25SMatthew Ahrens /*
2628e4da25SMatthew Ahrens * Copyright (c) 2013 by Delphix. All rights reserved.
2728e4da25SMatthew Ahrens */
28cc7a88b5Smrj
29cc7a88b5Smrj #include <mdb/mdb_modapi.h>
30cc7a88b5Smrj #include <mdb/mdb_ks.h>
31cc7a88b5Smrj #include <mdb/mdb_ctf.h>
32cc7a88b5Smrj #include <sys/evtchn_impl.h>
33cc7a88b5Smrj
34cc7a88b5Smrj #include "intr_common.h"
35cc7a88b5Smrj
3628e4da25SMatthew Ahrens typedef struct mdb_shared_info {
3728e4da25SMatthew Ahrens unsigned long evtchn_pending[sizeof (unsigned long) * NBBY];
3828e4da25SMatthew Ahrens unsigned long evtchn_mask[sizeof (unsigned long) * NBBY];
3928e4da25SMatthew Ahrens } mdb_shared_info_t;
4028e4da25SMatthew Ahrens
4128e4da25SMatthew Ahrens static mdb_shared_info_t shared_info;
42cc7a88b5Smrj static struct av_head avec_tbl[NR_IRQS];
43cc7a88b5Smrj static uint16_t shared_tbl[MAX_ISA_IRQ + 1];
44cc7a88b5Smrj static irq_info_t irq_tbl[NR_IRQS];
45cc7a88b5Smrj static mec_info_t virq_tbl[NR_VIRQS];
46cc7a88b5Smrj static short evtchn_tbl[NR_EVENT_CHANNELS];
47cc7a88b5Smrj
48cc7a88b5Smrj static int
update_tables(void)49cc7a88b5Smrj update_tables(void)
50cc7a88b5Smrj {
51cc7a88b5Smrj uintptr_t shared_info_addr;
52cc7a88b5Smrj
53cc7a88b5Smrj if (mdb_readvar(&irq_tbl, "irq_info") == -1) {
54cc7a88b5Smrj mdb_warn("failed to read irq_info");
55cc7a88b5Smrj return (0);
56cc7a88b5Smrj }
57cc7a88b5Smrj
58cc7a88b5Smrj if (mdb_readvar(&virq_tbl, "virq_info") == -1) {
59cc7a88b5Smrj mdb_warn("failed to read virq_info");
60cc7a88b5Smrj return (0);
61cc7a88b5Smrj }
62cc7a88b5Smrj
63cc7a88b5Smrj if (mdb_readvar(&evtchn_tbl, "evtchn_to_irq") == -1) {
64cc7a88b5Smrj mdb_warn("failed to read evtchn_to_irq");
65cc7a88b5Smrj return (0);
66cc7a88b5Smrj }
67cc7a88b5Smrj
68cc7a88b5Smrj if (mdb_readvar(&avec_tbl, "autovect") == -1) {
69cc7a88b5Smrj mdb_warn("failed to read autovect");
70cc7a88b5Smrj return (0);
71cc7a88b5Smrj }
72cc7a88b5Smrj
73cc7a88b5Smrj if (mdb_readvar(&shared_tbl, "xen_uppc_irq_shared_table") == -1) {
74cc7a88b5Smrj mdb_warn("failed to read xen_uppc_irq_shared_table");
75cc7a88b5Smrj return (0);
76cc7a88b5Smrj }
77cc7a88b5Smrj
78cc7a88b5Smrj if (mdb_readvar(&shared_info_addr, "HYPERVISOR_shared_info") == -1) {
79cc7a88b5Smrj mdb_warn("failed to read HYPERVISOR_shared_info");
80cc7a88b5Smrj return (0);
81cc7a88b5Smrj }
82cc7a88b5Smrj
8328e4da25SMatthew Ahrens if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t",
8428e4da25SMatthew Ahrens shared_info_addr, 0) == -1)
85cc7a88b5Smrj return (0);
86cc7a88b5Smrj
87cc7a88b5Smrj return (1);
88cc7a88b5Smrj }
89cc7a88b5Smrj
90cc7a88b5Smrj
91cc7a88b5Smrj static char *
interrupt_print_bus(uintptr_t dip_addr)92cc7a88b5Smrj interrupt_print_bus(uintptr_t dip_addr)
93cc7a88b5Smrj {
94cc7a88b5Smrj char bind_name[MAXPATHLEN + 1];
95cc7a88b5Smrj struct dev_info dev_info;
96cc7a88b5Smrj
97cc7a88b5Smrj if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) {
98cc7a88b5Smrj mdb_warn("failed to read child dip");
99cc7a88b5Smrj return ("-");
100cc7a88b5Smrj }
101cc7a88b5Smrj
102cc7a88b5Smrj while (dev_info.devi_parent != 0) {
103cc7a88b5Smrj if (mdb_vread(&dev_info, sizeof (dev_info),
104cc7a88b5Smrj (uintptr_t)dev_info.devi_parent) == -1)
105cc7a88b5Smrj break;
106cc7a88b5Smrj
107cc7a88b5Smrj (void) mdb_readstr(bind_name, sizeof (bind_name),
108cc7a88b5Smrj (uintptr_t)dev_info.devi_binding_name);
109cc7a88b5Smrj if (strcmp(bind_name, "isa") == 0)
110cc7a88b5Smrj return ("ISA");
111cc7a88b5Smrj else if (strcmp(bind_name, "pci") == 0 ||
112cc7a88b5Smrj strcmp(bind_name, "npe") == 0)
113cc7a88b5Smrj return ("PCI");
114cc7a88b5Smrj }
115cc7a88b5Smrj return ("-");
116cc7a88b5Smrj }
117cc7a88b5Smrj
118cc7a88b5Smrj static const char *
virq_type(int irq)119cc7a88b5Smrj virq_type(int irq)
120cc7a88b5Smrj {
121cc7a88b5Smrj int i;
122cc7a88b5Smrj
123cc7a88b5Smrj for (i = 0; i < NR_VIRQS; i++) {
124cc7a88b5Smrj if (virq_tbl[i].mi_irq == irq)
125cc7a88b5Smrj break;
126cc7a88b5Smrj }
127cc7a88b5Smrj
128cc7a88b5Smrj switch (i) {
129cc7a88b5Smrj case VIRQ_TIMER:
130cc7a88b5Smrj return ("virq:timer");
131cc7a88b5Smrj case VIRQ_DEBUG:
132cc7a88b5Smrj return ("virq:debug");
133cc7a88b5Smrj case VIRQ_CONSOLE:
134cc7a88b5Smrj return ("virq:console");
135cc7a88b5Smrj case VIRQ_DOM_EXC:
136cc7a88b5Smrj return ("virq:dom exc");
137cc7a88b5Smrj case VIRQ_DEBUGGER:
138cc7a88b5Smrj return ("virq:debugger");
139cc7a88b5Smrj default:
140cc7a88b5Smrj break;
141cc7a88b5Smrj }
142cc7a88b5Smrj
143cc7a88b5Smrj return ("virq:?");
144cc7a88b5Smrj }
145cc7a88b5Smrj
146cc7a88b5Smrj static const char *
irq_type(int irq,int extended)147cc7a88b5Smrj irq_type(int irq, int extended)
148cc7a88b5Smrj {
149cc7a88b5Smrj switch (irq_tbl[irq].ii_type) {
150cc7a88b5Smrj case IRQT_UNBOUND:
151cc7a88b5Smrj return ("unset");
152cc7a88b5Smrj case IRQT_PIRQ:
153cc7a88b5Smrj return ("pirq");
154cc7a88b5Smrj case IRQT_VIRQ:
155cc7a88b5Smrj if (extended)
156cc7a88b5Smrj return (virq_type(irq));
157cc7a88b5Smrj return ("virq");
158cc7a88b5Smrj case IRQT_IPI:
159cc7a88b5Smrj return ("ipi");
160cc7a88b5Smrj case IRQT_EVTCHN:
161cc7a88b5Smrj return ("evtchn");
162cc7a88b5Smrj case IRQT_DEV_EVTCHN:
163cc7a88b5Smrj return ("device");
164cc7a88b5Smrj }
165cc7a88b5Smrj
166cc7a88b5Smrj return ("?");
167cc7a88b5Smrj }
168cc7a88b5Smrj
169cc7a88b5Smrj static void
print_isr(int i)170cc7a88b5Smrj print_isr(int i)
171cc7a88b5Smrj {
172cc7a88b5Smrj struct autovec avhp;
173cc7a88b5Smrj
174cc7a88b5Smrj if (avec_tbl[i].avh_link == NULL)
175cc7a88b5Smrj return;
176cc7a88b5Smrj
177cc7a88b5Smrj (void) mdb_vread(&avhp, sizeof (struct autovec),
178cc7a88b5Smrj (uintptr_t)avec_tbl[i].avh_link);
179cc7a88b5Smrj
180cc7a88b5Smrj interrupt_print_isr((uintptr_t)avhp.av_vector,
181cc7a88b5Smrj (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip);
182cc7a88b5Smrj
183cc7a88b5Smrj while (avhp.av_link != NULL &&
184cc7a88b5Smrj mdb_vread(&avhp, sizeof (struct autovec),
185cc7a88b5Smrj (uintptr_t)avhp.av_link) != -1) {
186cc7a88b5Smrj mdb_printf(", ");
187cc7a88b5Smrj interrupt_print_isr((uintptr_t)avhp.av_vector,
188cc7a88b5Smrj (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip);
189cc7a88b5Smrj }
190cc7a88b5Smrj }
191cc7a88b5Smrj
192cc7a88b5Smrj static int
evtchn_masked(int i)193cc7a88b5Smrj evtchn_masked(int i)
194cc7a88b5Smrj {
195cc7a88b5Smrj return (TEST_EVTCHN_BIT(i, &shared_info.evtchn_mask[0]) != 0);
196cc7a88b5Smrj }
197cc7a88b5Smrj
198cc7a88b5Smrj static int
evtchn_pending(int i)199cc7a88b5Smrj evtchn_pending(int i)
200cc7a88b5Smrj {
201cc7a88b5Smrj return (TEST_EVTCHN_BIT(i, &shared_info.evtchn_pending[0]) != 0);
202cc7a88b5Smrj }
203cc7a88b5Smrj
204cc7a88b5Smrj static void
pic_interrupt_dump(int i,struct autovec * avhp,int evtchn)205cc7a88b5Smrj pic_interrupt_dump(int i, struct autovec *avhp, int evtchn)
206cc7a88b5Smrj {
207cc7a88b5Smrj if (option_flags & INTR_DISPLAY_INTRSTAT) {
208cc7a88b5Smrj mdb_printf("%-3d ", 0);
209cc7a88b5Smrj print_isr(i);
210cc7a88b5Smrj mdb_printf("\n");
211cc7a88b5Smrj return;
212cc7a88b5Smrj }
213cc7a88b5Smrj
214cc7a88b5Smrj mdb_printf("%-3d 0x%2x %-6d %6d/%-2d %-3s %-6s %-5d ",
215cc7a88b5Smrj i, i + PIC_VECTBASE, evtchn, avec_tbl[i].avh_lo_pri,
216cc7a88b5Smrj avec_tbl[i].avh_hi_pri, avhp->av_dip ?
217cc7a88b5Smrj interrupt_print_bus((uintptr_t)avhp->av_dip) : "-",
218cc7a88b5Smrj irq_type(i, 0), shared_tbl[i]);
219cc7a88b5Smrj
220cc7a88b5Smrj print_isr(i);
221cc7a88b5Smrj
222cc7a88b5Smrj mdb_printf("\n");
223cc7a88b5Smrj }
224cc7a88b5Smrj
225cc7a88b5Smrj static void
ec_interrupt_dump(int i)226cc7a88b5Smrj ec_interrupt_dump(int i)
227cc7a88b5Smrj {
228cc7a88b5Smrj irq_info_t *irqp = &irq_tbl[i];
229cc7a88b5Smrj struct autovec avhp;
230cc7a88b5Smrj char evtchn[8];
231cc7a88b5Smrj
232cc7a88b5Smrj if (irqp->ii_type == IRQT_UNBOUND)
233cc7a88b5Smrj return;
234cc7a88b5Smrj
235cc7a88b5Smrj if (option_flags & INTR_DISPLAY_INTRSTAT) {
236cc7a88b5Smrj mdb_printf("%-3d ", 0);
237cc7a88b5Smrj print_isr(i);
238cc7a88b5Smrj mdb_printf("\n");
239cc7a88b5Smrj return;
240cc7a88b5Smrj }
241cc7a88b5Smrj
242cc7a88b5Smrj
243cc7a88b5Smrj memset(&avhp, 0, sizeof (avhp));
244cc7a88b5Smrj if (avec_tbl[i].avh_link != NULL)
245cc7a88b5Smrj (void) mdb_vread(&avhp, sizeof (struct autovec),
246cc7a88b5Smrj (uintptr_t)avec_tbl[i].avh_link);
247cc7a88b5Smrj
248cc7a88b5Smrj switch (irqp->ii_type) {
249cc7a88b5Smrj case IRQT_EVTCHN:
250cc7a88b5Smrj case IRQT_VIRQ:
251cc7a88b5Smrj if (irqp->ii_u.index == VIRQ_TIMER) {
252cc7a88b5Smrj strcpy(evtchn, "T");
253cc7a88b5Smrj } else {
254cc7a88b5Smrj mdb_snprintf(evtchn, sizeof (evtchn), "%-7d",
255cc7a88b5Smrj irqp->ii_u.evtchn);
256cc7a88b5Smrj }
257cc7a88b5Smrj break;
258cc7a88b5Smrj case IRQT_IPI:
259cc7a88b5Smrj strcpy(evtchn, "I");
260cc7a88b5Smrj break;
261cc7a88b5Smrj case IRQT_DEV_EVTCHN:
262cc7a88b5Smrj strcpy(evtchn, "D");
263cc7a88b5Smrj break;
264cc7a88b5Smrj }
265cc7a88b5Smrj
266cc7a88b5Smrj /* IRQ */
267cc7a88b5Smrj mdb_printf("%3d ", i);
268cc7a88b5Smrj /* Vector */
269cc7a88b5Smrj mdb_printf("- ");
270cc7a88b5Smrj /* Evtchn */
271cc7a88b5Smrj mdb_printf("%-7s", evtchn);
272cc7a88b5Smrj /* IPL */
273cc7a88b5Smrj mdb_printf("%6d/%-2d ", irq_tbl[i].ii_u2.ipl, irq_tbl[i].ii_u2.ipl);
274cc7a88b5Smrj /* Bus */
275cc7a88b5Smrj mdb_printf("%-3s ", avhp.av_dip
276cc7a88b5Smrj ? interrupt_print_bus((uintptr_t)avhp.av_dip) : "-");
277cc7a88b5Smrj /* Type */
278cc7a88b5Smrj mdb_printf("%-6s ", irq_type(i, 0));
279cc7a88b5Smrj /* Share */
280cc7a88b5Smrj mdb_printf("- ");
281cc7a88b5Smrj
282cc7a88b5Smrj print_isr(i);
283cc7a88b5Smrj
284cc7a88b5Smrj mdb_printf("\n");
285cc7a88b5Smrj }
286cc7a88b5Smrj
287cc7a88b5Smrj /*
288cc7a88b5Smrj * uppc_interrupt_dump:
289*bbf21555SRichard Lowe * Dump uppc(4D) interrupt information.
290cc7a88b5Smrj */
291cc7a88b5Smrj /* ARGSUSED */
292cc7a88b5Smrj int
xen_uppc_interrupt_dump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)293cc7a88b5Smrj xen_uppc_interrupt_dump(uintptr_t addr, uint_t flags, int argc,
294cc7a88b5Smrj const mdb_arg_t *argv)
295cc7a88b5Smrj {
296cc7a88b5Smrj int i;
297cc7a88b5Smrj boolean_t found = B_FALSE;
298cc7a88b5Smrj struct autovec avhp;
299cc7a88b5Smrj
300cc7a88b5Smrj option_flags = 0;
301cc7a88b5Smrj if (mdb_getopts(argc, argv,
302cc7a88b5Smrj 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags,
303cc7a88b5Smrj 'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags,
304cc7a88b5Smrj NULL) != argc)
305cc7a88b5Smrj return (DCMD_USAGE);
306cc7a88b5Smrj
307cc7a88b5Smrj if (!update_tables())
308cc7a88b5Smrj return (DCMD_ERR);
309cc7a88b5Smrj
310cc7a88b5Smrj /*
311*bbf21555SRichard Lowe * By default, on all x86 systems ::interrupts from xen_uppc(4D) gets
312*bbf21555SRichard Lowe * loaded first. For APIC systems the ::interrupts from xpv_psm(4D)
313cc7a88b5Smrj * ought to be executed. Confusion stems as both modules export the
314cc7a88b5Smrj * same dcmd.
315cc7a88b5Smrj */
316cc7a88b5Smrj for (i = 0; i < MAX_ISA_IRQ + 1; i++)
317cc7a88b5Smrj if (shared_tbl[i]) {
318cc7a88b5Smrj found = B_TRUE;
319cc7a88b5Smrj break;
320cc7a88b5Smrj }
321cc7a88b5Smrj
322cc7a88b5Smrj if (found == B_FALSE) {
323cc7a88b5Smrj if (mdb_lookup_by_obj("xpv_psm", "apic_irq_table",
324cc7a88b5Smrj NULL) == 0) {
325cc7a88b5Smrj return (mdb_call_dcmd("xpv_psm`interrupts",
326cc7a88b5Smrj addr, flags, argc, argv));
327cc7a88b5Smrj }
328cc7a88b5Smrj }
329cc7a88b5Smrj
330cc7a88b5Smrj /* Print the header first */
331cc7a88b5Smrj if (option_flags & INTR_DISPLAY_INTRSTAT)
332cc7a88b5Smrj mdb_printf("%<u>CPU ");
333cc7a88b5Smrj else
334cc7a88b5Smrj mdb_printf("%<u>IRQ Vect Evtchn IPL(lo/hi) Bus Type Share ");
335cc7a88b5Smrj mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ?
336cc7a88b5Smrj "Driver Name(s)" : "ISR(s)");
337cc7a88b5Smrj
338cc7a88b5Smrj for (i = 0; i < NR_IRQS; i++) {
339cc7a88b5Smrj if (irq_tbl[i].ii_type == IRQT_PIRQ) {
340cc7a88b5Smrj if (irq_tbl[i].ii_u.evtchn == 0)
341cc7a88b5Smrj continue;
342cc7a88b5Smrj
343cc7a88b5Smrj /* Read the entry, if invalid continue */
344cc7a88b5Smrj if (mdb_vread(&avhp, sizeof (struct autovec),
345cc7a88b5Smrj (uintptr_t)avec_tbl[i].avh_link) == -1)
346cc7a88b5Smrj continue;
347cc7a88b5Smrj
348cc7a88b5Smrj pic_interrupt_dump(i, &avhp, irq_tbl[i].ii_u.evtchn);
349cc7a88b5Smrj continue;
350cc7a88b5Smrj }
351cc7a88b5Smrj
352cc7a88b5Smrj ec_interrupt_dump(i);
353cc7a88b5Smrj }
354cc7a88b5Smrj
355cc7a88b5Smrj return (DCMD_OK);
356cc7a88b5Smrj }
357cc7a88b5Smrj
358cc7a88b5Smrj
359cc7a88b5Smrj static void
evtchn_dump(int i)360cc7a88b5Smrj evtchn_dump(int i)
361cc7a88b5Smrj {
362cc7a88b5Smrj int irq = evtchn_tbl[i];
363cc7a88b5Smrj
364cc7a88b5Smrj if (irq == INVALID_IRQ) {
365cc7a88b5Smrj mdb_printf("%-14s%-7d%-4s%-7s", "unassigned", i, "-", "-");
366cc7a88b5Smrj mdb_printf("%-4d", 0);
367cc7a88b5Smrj mdb_printf("%-7d", evtchn_masked(i));
368cc7a88b5Smrj mdb_printf("%-8d", evtchn_pending(i));
369cc7a88b5Smrj mdb_printf("\n");
370cc7a88b5Smrj return;
371cc7a88b5Smrj }
372cc7a88b5Smrj
373cc7a88b5Smrj /* Type */
374cc7a88b5Smrj mdb_printf("%-14s", irq_type(irq, 1));
375cc7a88b5Smrj /* Evtchn */
376cc7a88b5Smrj mdb_printf("%-7d", i);
377cc7a88b5Smrj /* IRQ */
378cc7a88b5Smrj mdb_printf("%-4d", irq);
379cc7a88b5Smrj /* IPL */
380cc7a88b5Smrj mdb_printf("%6d/%-2d ", irq_tbl[irq].ii_u2.ipl,
381cc7a88b5Smrj irq_tbl[irq].ii_u2.ipl);
382cc7a88b5Smrj /* CPU */
383cc7a88b5Smrj mdb_printf("%-4d", 0);
384cc7a88b5Smrj /* Masked/Pending */
385cc7a88b5Smrj mdb_printf("%-7d", evtchn_masked(i));
386cc7a88b5Smrj mdb_printf("%-8d", evtchn_pending(i));
387cc7a88b5Smrj /* ISR */
388cc7a88b5Smrj print_isr(irq);
389cc7a88b5Smrj
390cc7a88b5Smrj mdb_printf("\n");
391cc7a88b5Smrj }
392cc7a88b5Smrj
393cc7a88b5Smrj /* ARGSUSED */
394cc7a88b5Smrj static int
evtchns_dump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)395cc7a88b5Smrj evtchns_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
396cc7a88b5Smrj {
397cc7a88b5Smrj int i;
398cc7a88b5Smrj boolean_t found = B_FALSE;
399cc7a88b5Smrj
400cc7a88b5Smrj option_flags = 0;
401cc7a88b5Smrj if (mdb_getopts(argc, argv,
402cc7a88b5Smrj 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags,
403cc7a88b5Smrj NULL) != argc)
404cc7a88b5Smrj return (DCMD_USAGE);
405cc7a88b5Smrj
406cc7a88b5Smrj if (!update_tables())
407cc7a88b5Smrj return (DCMD_ERR);
408cc7a88b5Smrj
409cc7a88b5Smrj /*
410*bbf21555SRichard Lowe * By default, on all x86 systems ::evtchns from xen_uppc(4D) gets
411*bbf21555SRichard Lowe * loaded first. For APIC systems the ::evtchns from xpv_psm(4D)
412cc7a88b5Smrj * ought to be executed. Confusion stems as both modules export the
413cc7a88b5Smrj * same dcmd.
414cc7a88b5Smrj */
415cc7a88b5Smrj for (i = 0; i < MAX_ISA_IRQ + 1; i++)
416cc7a88b5Smrj if (shared_tbl[i]) {
417cc7a88b5Smrj found = B_TRUE;
418cc7a88b5Smrj break;
419cc7a88b5Smrj }
420cc7a88b5Smrj
421cc7a88b5Smrj if (found == B_FALSE) {
422cc7a88b5Smrj if (mdb_lookup_by_obj("xpv_psm", "apic_irq_table",
423cc7a88b5Smrj NULL) == 0) {
424cc7a88b5Smrj return (mdb_call_dcmd("xpv_psm`evtchns",
425cc7a88b5Smrj addr, flags, argc, argv));
426cc7a88b5Smrj }
427cc7a88b5Smrj }
428cc7a88b5Smrj
429cc7a88b5Smrj if (flags & DCMD_ADDRSPEC) {
430cc7a88b5Smrj /*
431cc7a88b5Smrj * Note: we allow the invalid evtchn 0, as it can help catch if
432cc7a88b5Smrj * we incorrectly try to configure it.
433cc7a88b5Smrj */
434cc7a88b5Smrj if ((int)addr >= NR_EVENT_CHANNELS) {
435cc7a88b5Smrj mdb_warn("Invalid event channel %d.\n", (int)addr);
436cc7a88b5Smrj return (DCMD_ERR);
437cc7a88b5Smrj }
438cc7a88b5Smrj }
439cc7a88b5Smrj
440cc7a88b5Smrj mdb_printf("%<u>Type Evtchn IRQ IPL(lo/hi) CPU "
441cc7a88b5Smrj "Masked Pending ");
442cc7a88b5Smrj mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ?
443cc7a88b5Smrj "Driver Name(s)" : "ISR(s)");
444cc7a88b5Smrj
445cc7a88b5Smrj if (flags & DCMD_ADDRSPEC) {
446cc7a88b5Smrj evtchn_dump((int)addr);
447cc7a88b5Smrj return (DCMD_OK);
448cc7a88b5Smrj }
449cc7a88b5Smrj
450cc7a88b5Smrj for (i = 0; i < NR_EVENT_CHANNELS; i++) {
451cc7a88b5Smrj if (evtchn_tbl[i] == INVALID_IRQ)
452cc7a88b5Smrj continue;
453cc7a88b5Smrj
454cc7a88b5Smrj evtchn_dump(i);
455cc7a88b5Smrj }
456cc7a88b5Smrj
457cc7a88b5Smrj return (DCMD_OK);
458cc7a88b5Smrj }
459cc7a88b5Smrj
460cc7a88b5Smrj static void
evtchns_help(void)461cc7a88b5Smrj evtchns_help(void)
462cc7a88b5Smrj {
463cc7a88b5Smrj mdb_printf("Print valid event channels\n"
464cc7a88b5Smrj "If %<u>addr%</u> is given, interpret it as an evtchn to print "
465cc7a88b5Smrj "details of.\n"
466cc7a88b5Smrj "By default, only interrupt service routine names are printed.\n\n"
467cc7a88b5Smrj "Switches:\n"
468cc7a88b5Smrj " -d instead of ISR, print <driver_name><instance#>\n");
469cc7a88b5Smrj }
470cc7a88b5Smrj
471cc7a88b5Smrj /*
472cc7a88b5Smrj * MDB module linkage information:
473cc7a88b5Smrj */
474cc7a88b5Smrj static const mdb_dcmd_t dcmds[] = {
475cc7a88b5Smrj { "interrupts", "?[-di]", "print interrupts", xen_uppc_interrupt_dump,
476cc7a88b5Smrj interrupt_help},
477cc7a88b5Smrj { "evtchns", "?[-d]", "print event channels", evtchns_dump,
478cc7a88b5Smrj evtchns_help },
479cc7a88b5Smrj { "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump,
480cc7a88b5Smrj soft_interrupt_help},
481cc7a88b5Smrj { NULL }
482cc7a88b5Smrj };
483cc7a88b5Smrj
484cc7a88b5Smrj static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL };
485cc7a88b5Smrj
486cc7a88b5Smrj const mdb_modinfo_t *
_mdb_init(void)487cc7a88b5Smrj _mdb_init(void)
488cc7a88b5Smrj {
489cc7a88b5Smrj GElf_Sym sym;
490cc7a88b5Smrj
491cc7a88b5Smrj if (mdb_lookup_by_name("gld_intr", &sym) != -1)
492cc7a88b5Smrj if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
493cc7a88b5Smrj gld_intr_addr = (uintptr_t)sym.st_value;
494cc7a88b5Smrj
495cc7a88b5Smrj return (&modinfo);
496cc7a88b5Smrj }
497