Deleted Added
full compact
io_apic.c (279319) io_apic.c (280260)
1/*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/x86/x86/io_apic.c 279319 2015-02-26 11:02:40Z kib $");
28__FBSDID("$FreeBSD: head/sys/x86/x86/io_apic.c 280260 2015-03-19 13:57:47Z kib $");
29
29
30#include "opt_acpi.h"
30#include "opt_isa.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>

--- 8 unchanged lines hidden (view full) ---

46#include <vm/pmap.h>
47
48#include <x86/apicreg.h>
49#include <machine/frame.h>
50#include <machine/intr_machdep.h>
51#include <x86/apicvar.h>
52#include <machine/resource.h>
53#include <machine/segments.h>
31#include "opt_isa.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/bus.h>
36#include <sys/kernel.h>
37#include <sys/lock.h>
38#include <sys/malloc.h>

--- 8 unchanged lines hidden (view full) ---

47#include <vm/pmap.h>
48
49#include <x86/apicreg.h>
50#include <machine/frame.h>
51#include <machine/intr_machdep.h>
52#include <x86/apicvar.h>
53#include <machine/resource.h>
54#include <machine/segments.h>
55#include <x86/iommu/iommu_intrmap.h>
54
55#define IOAPIC_ISA_INTS 16
56#define IOAPIC_MEM_REGION 32
57#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
58#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
59
56
57#define IOAPIC_ISA_INTS 16
58#define IOAPIC_MEM_REGION 32
59#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
60#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
61
60#define IRQ_EXTINT (NUM_IO_INTS + 1)
61#define IRQ_NMI (NUM_IO_INTS + 2)
62#define IRQ_SMI (NUM_IO_INTS + 3)
63#define IRQ_DISABLED (NUM_IO_INTS + 4)
64
65static MALLOC_DEFINE(M_IOAPIC, "io_apic", "I/O APIC structures");
66
67/*
68 * I/O APIC interrupt source driver. Each pin is assigned an IRQ cookie
69 * as laid out in the ACPI System Interrupt number model where each I/O
70 * APIC has a contiguous chunk of the System Interrupt address space.
71 * We assume that IRQs 1 - 15 behave like ISA IRQs and that all other
72 * IRQs behave as PCI IRQs by default. We also assume that the pin for

--- 5 unchanged lines hidden (view full) ---

78 * ftp://download.intel.com/design/chipsets/datashts/29056601.pdf
79 */
80
81struct ioapic_intsrc {
82 struct intsrc io_intsrc;
83 u_int io_irq;
84 u_int io_intpin:8;
85 u_int io_vector:8;
62static MALLOC_DEFINE(M_IOAPIC, "io_apic", "I/O APIC structures");
63
64/*
65 * I/O APIC interrupt source driver. Each pin is assigned an IRQ cookie
66 * as laid out in the ACPI System Interrupt number model where each I/O
67 * APIC has a contiguous chunk of the System Interrupt address space.
68 * We assume that IRQs 1 - 15 behave like ISA IRQs and that all other
69 * IRQs behave as PCI IRQs by default. We also assume that the pin for

--- 5 unchanged lines hidden (view full) ---

75 * ftp://download.intel.com/design/chipsets/datashts/29056601.pdf
76 */
77
78struct ioapic_intsrc {
79 struct intsrc io_intsrc;
80 u_int io_irq;
81 u_int io_intpin:8;
82 u_int io_vector:8;
86 u_int io_cpu:8;
83 u_int io_cpu;
87 u_int io_activehi:1;
88 u_int io_edgetrigger:1;
89 u_int io_masked:1;
90 int io_bus:4;
91 uint32_t io_lowreg;
84 u_int io_activehi:1;
85 u_int io_edgetrigger:1;
86 u_int io_masked:1;
87 int io_bus:4;
88 uint32_t io_lowreg;
89 u_int io_remap_cookie;
92};
93
94struct ioapic {
95 struct pic io_pic;
96 u_int io_id:8; /* logical ID */
97 u_int io_apic_id:4;
98 u_int io_intbase:8; /* System Interrupt base */
99 u_int io_numintr:8;

--- 15 unchanged lines hidden (view full) ---

115static void ioapic_disable_intr(struct intsrc *isrc);
116static int ioapic_vector(struct intsrc *isrc);
117static int ioapic_source_pending(struct intsrc *isrc);
118static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
119 enum intr_polarity pol);
120static void ioapic_resume(struct pic *pic, bool suspend_cancelled);
121static int ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id);
122static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
90};
91
92struct ioapic {
93 struct pic io_pic;
94 u_int io_id:8; /* logical ID */
95 u_int io_apic_id:4;
96 u_int io_intbase:8; /* System Interrupt base */
97 u_int io_numintr:8;

--- 15 unchanged lines hidden (view full) ---

113static void ioapic_disable_intr(struct intsrc *isrc);
114static int ioapic_vector(struct intsrc *isrc);
115static int ioapic_source_pending(struct intsrc *isrc);
116static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
117 enum intr_polarity pol);
118static void ioapic_resume(struct pic *pic, bool suspend_cancelled);
119static int ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id);
120static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
121static void ioapic_reprogram_intpin(struct intsrc *isrc);
123
124static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
122
123static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
125struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
126 ioapic_eoi_source, ioapic_enable_intr,
127 ioapic_disable_intr, ioapic_vector,
128 ioapic_source_pending, NULL, ioapic_resume,
129 ioapic_config_intr, ioapic_assign_cpu };
124struct pic ioapic_template = {
125 .pic_enable_source = ioapic_enable_source,
126 .pic_disable_source = ioapic_disable_source,
127 .pic_eoi_source = ioapic_eoi_source,
128 .pic_enable_intr = ioapic_enable_intr,
129 .pic_disable_intr = ioapic_disable_intr,
130 .pic_vector = ioapic_vector,
131 .pic_source_pending = ioapic_source_pending,
132 .pic_suspend = NULL,
133 .pic_resume = ioapic_resume,
134 .pic_config_intr = ioapic_config_intr,
135 .pic_assign_cpu = ioapic_assign_cpu,
136 .pic_reprogram_pin = ioapic_reprogram_intpin,
137};
130
131static int next_ioapic_base;
132static u_int next_id;
133
134static int enable_extint;
135SYSCTL_INT(_hw_apic, OID_AUTO, enable_extint, CTLFLAG_RDTUN, &enable_extint, 0,
136 "Enable the ExtINT pin in the first I/O APIC");
137

--- 152 unchanged lines hidden (view full) ---

290 * Completely program an intpin based on the data in its interrupt source
291 * structure.
292 */
293static void
294ioapic_program_intpin(struct ioapic_intsrc *intpin)
295{
296 struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
297 uint32_t low, high, value;
138
139static int next_ioapic_base;
140static u_int next_id;
141
142static int enable_extint;
143SYSCTL_INT(_hw_apic, OID_AUTO, enable_extint, CTLFLAG_RDTUN, &enable_extint, 0,
144 "Enable the ExtINT pin in the first I/O APIC");
145

--- 152 unchanged lines hidden (view full) ---

298 * Completely program an intpin based on the data in its interrupt source
299 * structure.
300 */
301static void
302ioapic_program_intpin(struct ioapic_intsrc *intpin)
303{
304 struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
305 uint32_t low, high, value;
306#ifdef ACPI_DMAR
307 int error;
308#endif
298
299 /*
300 * If a pin is completely invalid or if it is valid but hasn't
301 * been enabled yet, just ensure that the pin is masked.
302 */
303 mtx_assert(&icu_lock, MA_OWNED);
304 if (intpin->io_irq == IRQ_DISABLED || (intpin->io_irq < NUM_IO_INTS &&
305 intpin->io_vector == 0)) {
306 low = ioapic_read(io->io_addr,
307 IOAPIC_REDTBL_LO(intpin->io_intpin));
308 if ((low & IOART_INTMASK) == IOART_INTMCLR)
309 ioapic_write(io->io_addr,
310 IOAPIC_REDTBL_LO(intpin->io_intpin),
311 low | IOART_INTMSET);
309
310 /*
311 * If a pin is completely invalid or if it is valid but hasn't
312 * been enabled yet, just ensure that the pin is masked.
313 */
314 mtx_assert(&icu_lock, MA_OWNED);
315 if (intpin->io_irq == IRQ_DISABLED || (intpin->io_irq < NUM_IO_INTS &&
316 intpin->io_vector == 0)) {
317 low = ioapic_read(io->io_addr,
318 IOAPIC_REDTBL_LO(intpin->io_intpin));
319 if ((low & IOART_INTMASK) == IOART_INTMCLR)
320 ioapic_write(io->io_addr,
321 IOAPIC_REDTBL_LO(intpin->io_intpin),
322 low | IOART_INTMSET);
323#ifdef ACPI_DMAR
324 mtx_unlock_spin(&icu_lock);
325 iommu_unmap_ioapic_intr(io->io_apic_id,
326 &intpin->io_remap_cookie);
327 mtx_lock_spin(&icu_lock);
328#endif
312 return;
313 }
314
329 return;
330 }
331
332#ifdef ACPI_DMAR
333 mtx_unlock_spin(&icu_lock);
334 error = iommu_map_ioapic_intr(io->io_apic_id,
335 intpin->io_cpu, intpin->io_vector, intpin->io_edgetrigger,
336 intpin->io_activehi, intpin->io_irq, &intpin->io_remap_cookie,
337 &high, &low);
338 mtx_lock_spin(&icu_lock);
339 if (error == 0) {
340 ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin),
341 high);
342 intpin->io_lowreg = low;
343 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin),
344 low);
345 return;
346 } else if (error != EOPNOTSUPP) {
347 return;
348 }
349#endif
350
315 /* Set the destination. */
316 low = IOART_DESTPHY;
317 high = intpin->io_cpu << APIC_ID_SHIFT;
318
319 /* Program the rest of the low word. */
320 if (intpin->io_edgetrigger)
321 low |= IOART_TRGREDG;
322 else

--- 30 unchanged lines hidden (view full) ---

353 value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
354 value &= ~IOART_DEST;
355 value |= high;
356 ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
357 intpin->io_lowreg = low;
358 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);
359}
360
351 /* Set the destination. */
352 low = IOART_DESTPHY;
353 high = intpin->io_cpu << APIC_ID_SHIFT;
354
355 /* Program the rest of the low word. */
356 if (intpin->io_edgetrigger)
357 low |= IOART_TRGREDG;
358 else

--- 30 unchanged lines hidden (view full) ---

389 value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
390 value &= ~IOART_DEST;
391 value |= high;
392 ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
393 intpin->io_lowreg = low;
394 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);
395}
396
397static void
398ioapic_reprogram_intpin(struct intsrc *isrc)
399{
400
401 mtx_lock_spin(&icu_lock);
402 ioapic_program_intpin((struct ioapic_intsrc *)isrc);
403 mtx_unlock_spin(&icu_lock);
404}
405
361static int
362ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id)
363{
364 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
365 struct ioapic *io = (struct ioapic *)isrc->is_pic;
366 u_int old_vector, new_vector;
367 u_int old_id;
368

--- 269 unchanged lines hidden (view full) ---

638
639 /*
640 * Route interrupts to the BSP by default. Interrupts may
641 * be routed to other CPUs later after they are enabled.
642 */
643 intpin->io_cpu = PCPU_GET(apic_id);
644 value = ioapic_read(apic, IOAPIC_REDTBL_LO(i));
645 ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET);
406static int
407ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id)
408{
409 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
410 struct ioapic *io = (struct ioapic *)isrc->is_pic;
411 u_int old_vector, new_vector;
412 u_int old_id;
413

--- 269 unchanged lines hidden (view full) ---

683
684 /*
685 * Route interrupts to the BSP by default. Interrupts may
686 * be routed to other CPUs later after they are enabled.
687 */
688 intpin->io_cpu = PCPU_GET(apic_id);
689 value = ioapic_read(apic, IOAPIC_REDTBL_LO(i));
690 ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET);
691#ifdef ACPI_DMAR
692 /* dummy, but sets cookie */
693 mtx_unlock_spin(&icu_lock);
694 iommu_map_ioapic_intr(io->io_apic_id,
695 intpin->io_cpu, intpin->io_vector, intpin->io_edgetrigger,
696 intpin->io_activehi, intpin->io_irq,
697 &intpin->io_remap_cookie, NULL, NULL);
698 mtx_lock_spin(&icu_lock);
699#endif
646 }
647 mtx_unlock_spin(&icu_lock);
648
649 return (io);
650}
651
652int
653ioapic_get_vector(void *cookie, u_int pin)

--- 422 unchanged lines hidden ---
700 }
701 mtx_unlock_spin(&icu_lock);
702
703 return (io);
704}
705
706int
707ioapic_get_vector(void *cookie, u_int pin)

--- 422 unchanged lines hidden ---