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 --- |