1 /* NetBSD: intr.c,v 1.15 2004/04/10 14:49:55 kochi Exp */
4 * Copyright 2002 (c) Wasabi Systems, Inc.
7 * Written by Frank van der Linden for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright (c) 1991 The Regents of the University of California.
40 * All rights reserved.
42 * This code is derived from software contributed to Berkeley by
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * @(#)isa.c 7.2 (Berkeley) 5/13/91
72 * Copyright (c) 1993, 1994 Charles Hannum.
74 * Redistribution and use in source and binary forms, with or without
75 * modification, are permitted provided that the following conditions
77 * 1. Redistributions of source code must retain the above copyright
78 * notice, this list of conditions and the following disclaimer.
79 * 2. Redistributions in binary form must reproduce the above copyright
80 * notice, this list of conditions and the following disclaimer in the
81 * documentation and/or other materials provided with the distribution.
82 * 3. All advertising materials mentioning features or use of this software
83 * must display the following acknowledgement:
84 * This product includes software developed by the University of
85 * California, Berkeley and its contributors.
86 * 4. Neither the name of the University nor the names of its contributors
87 * may be used to endorse or promote products derived from this software
88 * without specific prior written permission.
90 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
91 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
93 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
94 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
95 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
96 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
97 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
98 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
99 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
102 * @(#)isa.c 7.2 (Berkeley) 5/13/91
105 #include <sys/cdefs.h>
106 __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.25 2009/07/29 12:02:08 cegger Exp $");
108 #include "opt_multiprocessor.h"
113 #include <sys/param.h>
114 #include <sys/systm.h>
115 #include <sys/kernel.h>
116 #include <sys/syslog.h>
117 #include <sys/device.h>
118 #include <sys/malloc.h>
119 #include <sys/proc.h>
120 #include <sys/errno.h>
123 #include <uvm/uvm_extern.h>
125 #include <machine/i8259.h>
126 #include <machine/pio.h>
127 #include <xen/evtchn.h>
131 #include "opt_mpbios.h"
132 /* for x86/i8259.c */
133 struct intrstub i8259_stubs
[NUM_LEGACY_IRQS
] = {{0,0}};
135 /* for x86/ioapic.c */
136 struct intrstub ioapic_edge_stubs
[MAX_INTR_SOURCES
] = {{0,0}};
137 struct intrstub ioapic_level_stubs
[MAX_INTR_SOURCES
] = {{0,0}};
139 #include <machine/i82093var.h>
140 int irq2vect
[256] = {0};
141 int vect2irq
[256] = {0};
144 #include <machine/mpconfig.h>
145 #include <machine/mpacpi.h>
148 #include <machine/mpbiosvar.h>
152 #include <dev/pci/ppbreg.h>
156 * Recalculate the interrupt from scratch for an event source.
159 intr_calculatemasks(struct evtsource
*evts
)
163 evts
->ev_maxlevel
= IPL_NONE
;
165 for (ih
= evts
->ev_handlers
; ih
!= NULL
; ih
= ih
->ih_evt_next
) {
166 if (ih
->ih_level
> evts
->ev_maxlevel
)
167 evts
->ev_maxlevel
= ih
->ih_level
;
168 evts
->ev_imask
|= (1 << ih
->ih_level
);
174 * Fake interrupt handler structures for the benefit of symmetry with
175 * other interrupt sources.
177 struct intrhand fake_softclock_intrhand
;
178 struct intrhand fake_softnet_intrhand
;
179 struct intrhand fake_softserial_intrhand
;
180 struct intrhand fake_timer_intrhand
;
181 struct intrhand fake_ipi_intrhand
;
184 * Initialize all handlers that aren't dynamically allocated, and exist
185 * for each CPU. Also init ci_iunmask[].
188 cpu_intr_init(struct cpu_info
*ci
)
191 #if defined(INTRSTACKSIZE)
195 ci
->ci_iunmask
[0] = 0xfffffffe;
196 for (i
= 1; i
< NIPL
; i
++)
197 ci
->ci_iunmask
[i
] = ci
->ci_iunmask
[i
- 1] & ~(1 << i
);
199 #if defined(INTRSTACKSIZE)
200 cp
= (char *)uvm_km_alloc(kernel_map
, INTRSTACKSIZE
, 0, UVM_KMF_WIRED
);
201 ci
->ci_intrstack
= cp
+ INTRSTACKSIZE
- sizeof(register_t
);
206 #if NPCI > 0 || NISA > 0
208 intr_establish(int legacy_irq
, struct pic
*pic
, int pin
,
209 int type
, int level
, int (*handler
)(void *) , void *arg
,
212 struct pintrhand
*ih
;
216 if (legacy_irq
!= -1 && (legacy_irq
< 0 || legacy_irq
> 15))
217 panic("intr_establish: bad legacy IRQ value");
218 if (legacy_irq
== -1 && pic
== &i8259_pic
)
219 panic("intr_establish: non-legacy IRQ on i8259");
220 #endif /* DIAGNOSTIC */
221 if (legacy_irq
== -1) {
223 /* will do interrupts via I/O APIC */
224 legacy_irq
= APIC_INT_VIA_APIC
;
225 legacy_irq
|= pic
->pic_apicid
<< APIC_INT_APIC_SHIFT
;
226 legacy_irq
|= pin
<< APIC_INT_PIN_SHIFT
;
227 snprintf(evname
, sizeof(evname
), "%s pin %d",
233 snprintf(evname
, sizeof(evname
), "irq%d", legacy_irq
);
235 evtchn
= xen_intr_map(&legacy_irq
, type
);
236 ih
= pirq_establish(legacy_irq
& 0xff, evtchn
, handler
, arg
, level
,
242 xen_intr_map(int *pirq
, int type
)
246 extern struct cpu_info phycpu_info_primary
; /* XXX */
248 * The hypervisor has already allocated vectors and IRQs for the
249 * devices. Reusing the same IRQ doesn't work because as we bind
250 * them for each devices, we can't then change the route entry
251 * of the next device if this one used this IRQ. The easiest is
252 * to allocate IRQs top-down, starting with a high number.
253 * 250 and 230 have been tried, but got rejected by Xen.
255 * Xen 3.5 also rejects 200. Try out all values until Xen accepts
256 * or none is available.
258 static int xen_next_irq
= 200;
259 struct ioapic_softc
*ioapic
= ioapic_find(APIC_IRQ_APIC(*pirq
));
260 struct pic
*pic
= &ioapic
->sc_pic
;
261 int pin
= APIC_IRQ_PIN(*pirq
);
264 if (*pirq
& APIC_INT_VIA_APIC
) {
265 irq
= vect2irq
[ioapic
->sc_pins
[pin
].ip_vector
];
266 if (ioapic
->sc_pins
[pin
].ip_vector
== 0 || irq
== 0) {
268 irq
= APIC_IRQ_LEGACY_IRQ(*pirq
);
269 if (irq
<= 0 || irq
> 15)
270 irq
= xen_next_irq
--;
272 /* allocate vector and route interrupt */
273 op
.cmd
= PHYSDEVOP_ASSIGN_VECTOR
;
274 op
.u
.irq_op
.irq
= irq
;
275 if (HYPERVISOR_physdev_op(&op
) < 0) {
276 irq
= xen_next_irq
--;
277 if (xen_next_irq
== 15)
278 panic("PHYSDEVOP_ASSIGN_VECTOR irq %d", irq
);
281 irq2vect
[irq
] = op
.u
.irq_op
.vector
;
282 vect2irq
[op
.u
.irq_op
.vector
] = irq
;
283 pic
->pic_addroute(pic
, &phycpu_info_primary
, pin
,
284 op
.u
.irq_op
.vector
, type
);
290 return bind_pirq_to_evtch(irq
);
294 intr_disestablish(struct intrhand
*ih
)
296 printf("intr_disestablish irq\n");
299 #if defined(MPBIOS) || NACPICA > 0
301 intr_findpic(int num
)
304 struct ioapic_softc
*pic
;
306 pic
= ioapic_find_bybase(num
);
310 if (num
< NUM_LEGACY_IRQS
)
317 #if NIOAPIC > 0 || NACPICA > 0
318 struct intr_extra_bus
{
320 pcitag_t
*pci_bridge_tag
;
321 pci_chipset_tag_t pci_chipset_tag
;
322 LIST_ENTRY(intr_extra_bus
) list
;
325 LIST_HEAD(, intr_extra_bus
) intr_extra_buses
=
326 LIST_HEAD_INITIALIZER(intr_extra_buses
);
328 static int intr_scan_bus(int, int, struct xen_intr_handle
*);
331 intr_add_pcibus(struct pcibus_attach_args
*pba
)
333 struct intr_extra_bus
*iebp
;
335 iebp
= malloc(sizeof(struct intr_extra_bus
), M_TEMP
, M_WAITOK
);
336 iebp
->bus
= pba
->pba_bus
;
337 iebp
->pci_chipset_tag
= pba
->pba_pc
;
338 iebp
->pci_bridge_tag
= pba
->pba_bridgetag
;
339 LIST_INSERT_HEAD(&intr_extra_buses
, iebp
, list
);
343 intr_find_pcibridge(int bus
, pcitag_t
*pci_bridge_tag
,
344 pci_chipset_tag_t
*pci_chipset_tag
)
346 struct intr_extra_bus
*iebp
;
353 mpb
= &mp_busses
[bus
];
354 if (mpb
->mb_pci_bridge_tag
== NULL
)
356 *pci_bridge_tag
= *mpb
->mb_pci_bridge_tag
;
357 *pci_chipset_tag
= mpb
->mb_pci_chipset_tag
;
361 LIST_FOREACH(iebp
, &intr_extra_buses
, list
) {
362 if (iebp
->bus
== bus
) {
363 if (iebp
->pci_bridge_tag
== NULL
)
365 *pci_bridge_tag
= *iebp
->pci_bridge_tag
;
366 *pci_chipset_tag
= iebp
->pci_chipset_tag
;
374 intr_find_mpmapping(int bus
, int pin
, struct xen_intr_handle
*handle
)
378 pcitag_t pci_bridge_tag
;
379 pci_chipset_tag_t pci_chipset_tag
;
383 while (intr_scan_bus(bus
, pin
, handle
) != 0) {
384 if (intr_find_pcibridge(bus
, &pci_bridge_tag
,
385 &pci_chipset_tag
) != 0)
389 pin
= PPB_INTERRUPT_SWIZZLE(pin
+ 1, dev
) - 1;
390 pci_decompose_tag(pci_chipset_tag
, pci_bridge_tag
, &bus
,
396 return intr_scan_bus(bus
, pin
, handle
);
401 intr_scan_bus(int bus
, int pin
, struct xen_intr_handle
*handle
)
403 struct mp_intr_map
*mip
, *intrs
;
405 if (bus
< 0 || bus
>= mp_nbus
)
408 intrs
= mp_busses
[bus
].mb_intrs
;
412 for (mip
= intrs
; mip
!= NULL
; mip
= mip
->next
) {
413 if (mip
->bus_pin
== pin
) {
415 if (mip
->linkdev
!= NULL
)
416 if (mpacpi_findintr_linkdev(mip
) != 0)
419 handle
->pirq
= mip
->ioapic_ih
;
425 #endif /* NIOAPIC > 0 || NACPICA > 0 */
426 #endif /* NPCI > 0 || NISA > 0 */
431 intr_printconfig(void)
435 struct intrsource
*isp
;
437 CPU_INFO_ITERATOR cii
;
439 for (CPU_INFO_FOREACH(cii
, ci
)) {
440 printf("%s: interrupt masks:\n", device_xname(ci
->ci_dev
));
441 for (i
= 0; i
< NIPL
; i
++)
442 printf("IPL %d mask %lx unmask %lx\n", i
,
443 (u_long
)ci
->ci_imask
[i
], (u_long
)ci
->ci_iunmask
[i
]);
444 for (i
= 0; i
< MAX_INTR_SOURCES
; i
++) {
445 isp
= ci
->ci_isources
[i
];
448 printf("%s source %d is pin %d from pic %s maxlevel %d\n",
449 device_xname(ci
->ci_dev
), i
, isp
->is_pin
,
450 isp
->is_pic
->pic_name
, isp
->is_maxlevel
);
451 for (ih
= isp
->is_handlers
; ih
!= NULL
;
453 printf("\thandler %p level %d\n",
454 ih
->ih_fun
, ih
->ih_level
);
462 cpu_intr_redistribute(void)
469 cpu_intr_count(struct cpu_info
*ci
)
472 KASSERT(ci
->ci_nintrhand
>= 0);
474 return ci
->ci_nintrhand
;