io_apic.c revision 262192
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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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: stable/10/sys/x86/x86/io_apic.c 262192 2014-02-18 20:27:17Z jhb $"); 29 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> 38#include <sys/module.h> 39#include <sys/mutex.h> 40#include <sys/sysctl.h> 41 42#include <dev/pci/pcireg.h> 43#include <dev/pci/pcivar.h> 44 45#include <vm/vm.h> 46#include <vm/pmap.h> 47 48#include <x86/apicreg.h> 49#include <machine/frame.h> 50#include <machine/intr_machdep.h> 51#include <machine/apicvar.h> 52#include <machine/resource.h> 53#include <machine/segments.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 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 73 * IRQ 0 is actually an ExtINT pin. The apic enumerators override the 74 * configuration of individual pins as indicated by their tables. 75 * 76 * Documentation for the I/O APIC: "82093AA I/O Advanced Programmable 77 * Interrupt Controller (IOAPIC)", May 1996, Intel Corp. 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; 86 u_int io_cpu:8; 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; 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; 100 volatile ioapic_t *io_addr; /* XXX: should use bus_space */ 101 vm_paddr_t io_paddr; 102 STAILQ_ENTRY(ioapic) io_next; 103 struct ioapic_intsrc io_pins[0]; 104}; 105 106static u_int ioapic_read(volatile ioapic_t *apic, int reg); 107static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val); 108static const char *ioapic_bus_string(int bus_type); 109static void ioapic_print_irq(struct ioapic_intsrc *intpin); 110static void ioapic_enable_source(struct intsrc *isrc); 111static void ioapic_disable_source(struct intsrc *isrc, int eoi); 112static void ioapic_eoi_source(struct intsrc *isrc); 113static void ioapic_enable_intr(struct intsrc *isrc); 114static void ioapic_disable_intr(struct intsrc *isrc); 115static int ioapic_vector(struct intsrc *isrc); 116static int ioapic_source_pending(struct intsrc *isrc); 117static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, 118 enum intr_polarity pol); 119static void ioapic_resume(struct pic *pic, bool suspend_cancelled); 120static int ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id); 121static void ioapic_program_intpin(struct ioapic_intsrc *intpin); 122 123static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list); 124struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source, 125 ioapic_eoi_source, ioapic_enable_intr, 126 ioapic_disable_intr, ioapic_vector, 127 ioapic_source_pending, NULL, ioapic_resume, 128 ioapic_config_intr, ioapic_assign_cpu }; 129 130static int next_ioapic_base; 131static u_int next_id; 132 133static SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD, 0, "APIC options"); 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"); 137TUNABLE_INT("hw.apic.enable_extint", &enable_extint); 138 139static __inline void 140_ioapic_eoi_source(struct intsrc *isrc) 141{ 142 lapic_eoi(); 143} 144 145static u_int 146ioapic_read(volatile ioapic_t *apic, int reg) 147{ 148 149 mtx_assert(&icu_lock, MA_OWNED); 150 apic->ioregsel = reg; 151 return (apic->iowin); 152} 153 154static void 155ioapic_write(volatile ioapic_t *apic, int reg, u_int val) 156{ 157 158 mtx_assert(&icu_lock, MA_OWNED); 159 apic->ioregsel = reg; 160 apic->iowin = val; 161} 162 163static const char * 164ioapic_bus_string(int bus_type) 165{ 166 167 switch (bus_type) { 168 case APIC_BUS_ISA: 169 return ("ISA"); 170 case APIC_BUS_EISA: 171 return ("EISA"); 172 case APIC_BUS_PCI: 173 return ("PCI"); 174 default: 175 return ("unknown"); 176 } 177} 178 179static void 180ioapic_print_irq(struct ioapic_intsrc *intpin) 181{ 182 183 switch (intpin->io_irq) { 184 case IRQ_DISABLED: 185 printf("disabled"); 186 break; 187 case IRQ_EXTINT: 188 printf("ExtINT"); 189 break; 190 case IRQ_NMI: 191 printf("NMI"); 192 break; 193 case IRQ_SMI: 194 printf("SMI"); 195 break; 196 default: 197 printf("%s IRQ %u", ioapic_bus_string(intpin->io_bus), 198 intpin->io_irq); 199 } 200} 201 202static void 203ioapic_enable_source(struct intsrc *isrc) 204{ 205 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 206 struct ioapic *io = (struct ioapic *)isrc->is_pic; 207 uint32_t flags; 208 209 mtx_lock_spin(&icu_lock); 210 if (intpin->io_masked) { 211 flags = intpin->io_lowreg & ~IOART_INTMASK; 212 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), 213 flags); 214 intpin->io_masked = 0; 215 } 216 mtx_unlock_spin(&icu_lock); 217} 218 219static void 220ioapic_disable_source(struct intsrc *isrc, int eoi) 221{ 222 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 223 struct ioapic *io = (struct ioapic *)isrc->is_pic; 224 uint32_t flags; 225 226 mtx_lock_spin(&icu_lock); 227 if (!intpin->io_masked && !intpin->io_edgetrigger) { 228 flags = intpin->io_lowreg | IOART_INTMSET; 229 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), 230 flags); 231 intpin->io_masked = 1; 232 } 233 234 if (eoi == PIC_EOI) 235 _ioapic_eoi_source(isrc); 236 237 mtx_unlock_spin(&icu_lock); 238} 239 240static void 241ioapic_eoi_source(struct intsrc *isrc) 242{ 243 244 _ioapic_eoi_source(isrc); 245} 246 247/* 248 * Completely program an intpin based on the data in its interrupt source 249 * structure. 250 */ 251static void 252ioapic_program_intpin(struct ioapic_intsrc *intpin) 253{ 254 struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic; 255 uint32_t low, high, value; 256 257 /* 258 * If a pin is completely invalid or if it is valid but hasn't 259 * been enabled yet, just ensure that the pin is masked. 260 */ 261 mtx_assert(&icu_lock, MA_OWNED); 262 if (intpin->io_irq == IRQ_DISABLED || (intpin->io_irq < NUM_IO_INTS && 263 intpin->io_vector == 0)) { 264 low = ioapic_read(io->io_addr, 265 IOAPIC_REDTBL_LO(intpin->io_intpin)); 266 if ((low & IOART_INTMASK) == IOART_INTMCLR) 267 ioapic_write(io->io_addr, 268 IOAPIC_REDTBL_LO(intpin->io_intpin), 269 low | IOART_INTMSET); 270 return; 271 } 272 273 /* Set the destination. */ 274 low = IOART_DESTPHY; 275 high = intpin->io_cpu << APIC_ID_SHIFT; 276 277 /* Program the rest of the low word. */ 278 if (intpin->io_edgetrigger) 279 low |= IOART_TRGREDG; 280 else 281 low |= IOART_TRGRLVL; 282 if (intpin->io_activehi) 283 low |= IOART_INTAHI; 284 else 285 low |= IOART_INTALO; 286 if (intpin->io_masked) 287 low |= IOART_INTMSET; 288 switch (intpin->io_irq) { 289 case IRQ_EXTINT: 290 KASSERT(intpin->io_edgetrigger, 291 ("ExtINT not edge triggered")); 292 low |= IOART_DELEXINT; 293 break; 294 case IRQ_NMI: 295 KASSERT(intpin->io_edgetrigger, 296 ("NMI not edge triggered")); 297 low |= IOART_DELNMI; 298 break; 299 case IRQ_SMI: 300 KASSERT(intpin->io_edgetrigger, 301 ("SMI not edge triggered")); 302 low |= IOART_DELSMI; 303 break; 304 default: 305 KASSERT(intpin->io_vector != 0, ("No vector for IRQ %u", 306 intpin->io_irq)); 307 low |= IOART_DELFIXED | intpin->io_vector; 308 } 309 310 /* Write the values to the APIC. */ 311 value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin)); 312 value &= ~IOART_DEST; 313 value |= high; 314 ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value); 315 intpin->io_lowreg = low; 316 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low); 317} 318 319static int 320ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id) 321{ 322 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 323 struct ioapic *io = (struct ioapic *)isrc->is_pic; 324 u_int old_vector, new_vector; 325 u_int old_id; 326 327 /* 328 * keep 1st core as the destination for NMI 329 */ 330 if (intpin->io_irq == IRQ_NMI) 331 apic_id = 0; 332 333 /* 334 * Set us up to free the old irq. 335 */ 336 old_vector = intpin->io_vector; 337 old_id = intpin->io_cpu; 338 if (old_vector && apic_id == old_id) 339 return (0); 340 341 /* 342 * Allocate an APIC vector for this interrupt pin. Once 343 * we have a vector we program the interrupt pin. 344 */ 345 new_vector = apic_alloc_vector(apic_id, intpin->io_irq); 346 if (new_vector == 0) 347 return (ENOSPC); 348 349 /* 350 * Mask the old intpin if it is enabled while it is migrated. 351 * 352 * At least some level-triggered interrupts seem to need the 353 * extra DELAY() to avoid being stuck in a non-EOI'd state. 354 */ 355 mtx_lock_spin(&icu_lock); 356 if (!intpin->io_masked && !intpin->io_edgetrigger) { 357 ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), 358 intpin->io_lowreg | IOART_INTMSET); 359 mtx_unlock_spin(&icu_lock); 360 DELAY(100); 361 mtx_lock_spin(&icu_lock); 362 } 363 364 intpin->io_cpu = apic_id; 365 intpin->io_vector = new_vector; 366 if (isrc->is_handlers > 0) 367 apic_enable_vector(intpin->io_cpu, intpin->io_vector); 368 if (bootverbose) { 369 printf("ioapic%u: routing intpin %u (", io->io_id, 370 intpin->io_intpin); 371 ioapic_print_irq(intpin); 372 printf(") to lapic %u vector %u\n", intpin->io_cpu, 373 intpin->io_vector); 374 } 375 ioapic_program_intpin(intpin); 376 mtx_unlock_spin(&icu_lock); 377 378 /* 379 * Free the old vector after the new one is established. This is done 380 * to prevent races where we could miss an interrupt. 381 */ 382 if (old_vector) { 383 if (isrc->is_handlers > 0) 384 apic_disable_vector(old_id, old_vector); 385 apic_free_vector(old_id, old_vector, intpin->io_irq); 386 } 387 return (0); 388} 389 390static void 391ioapic_enable_intr(struct intsrc *isrc) 392{ 393 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 394 395 if (intpin->io_vector == 0) 396 if (ioapic_assign_cpu(isrc, intr_next_cpu()) != 0) 397 panic("Couldn't find an APIC vector for IRQ %d", 398 intpin->io_irq); 399 apic_enable_vector(intpin->io_cpu, intpin->io_vector); 400} 401 402 403static void 404ioapic_disable_intr(struct intsrc *isrc) 405{ 406 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 407 u_int vector; 408 409 if (intpin->io_vector != 0) { 410 /* Mask this interrupt pin and free its APIC vector. */ 411 vector = intpin->io_vector; 412 apic_disable_vector(intpin->io_cpu, vector); 413 mtx_lock_spin(&icu_lock); 414 intpin->io_masked = 1; 415 intpin->io_vector = 0; 416 ioapic_program_intpin(intpin); 417 mtx_unlock_spin(&icu_lock); 418 apic_free_vector(intpin->io_cpu, vector, intpin->io_irq); 419 } 420} 421 422static int 423ioapic_vector(struct intsrc *isrc) 424{ 425 struct ioapic_intsrc *pin; 426 427 pin = (struct ioapic_intsrc *)isrc; 428 return (pin->io_irq); 429} 430 431static int 432ioapic_source_pending(struct intsrc *isrc) 433{ 434 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 435 436 if (intpin->io_vector == 0) 437 return 0; 438 return (lapic_intr_pending(intpin->io_vector)); 439} 440 441static int 442ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, 443 enum intr_polarity pol) 444{ 445 struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; 446 struct ioapic *io = (struct ioapic *)isrc->is_pic; 447 int changed; 448 449 KASSERT(!(trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM), 450 ("%s: Conforming trigger or polarity\n", __func__)); 451 452 /* 453 * EISA interrupts always use active high polarity, so don't allow 454 * them to be set to active low. 455 * 456 * XXX: Should we write to the ELCR if the trigger mode changes for 457 * an EISA IRQ or an ISA IRQ with the ELCR present? 458 */ 459 mtx_lock_spin(&icu_lock); 460 if (intpin->io_bus == APIC_BUS_EISA) 461 pol = INTR_POLARITY_HIGH; 462 changed = 0; 463 if (intpin->io_edgetrigger != (trig == INTR_TRIGGER_EDGE)) { 464 if (bootverbose) 465 printf("ioapic%u: Changing trigger for pin %u to %s\n", 466 io->io_id, intpin->io_intpin, 467 trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 468 intpin->io_edgetrigger = (trig == INTR_TRIGGER_EDGE); 469 changed++; 470 } 471 if (intpin->io_activehi != (pol == INTR_POLARITY_HIGH)) { 472 if (bootverbose) 473 printf("ioapic%u: Changing polarity for pin %u to %s\n", 474 io->io_id, intpin->io_intpin, 475 pol == INTR_POLARITY_HIGH ? "high" : "low"); 476 intpin->io_activehi = (pol == INTR_POLARITY_HIGH); 477 changed++; 478 } 479 if (changed) 480 ioapic_program_intpin(intpin); 481 mtx_unlock_spin(&icu_lock); 482 return (0); 483} 484 485static void 486ioapic_resume(struct pic *pic, bool suspend_cancelled) 487{ 488 struct ioapic *io = (struct ioapic *)pic; 489 int i; 490 491 mtx_lock_spin(&icu_lock); 492 for (i = 0; i < io->io_numintr; i++) 493 ioapic_program_intpin(&io->io_pins[i]); 494 mtx_unlock_spin(&icu_lock); 495} 496 497/* 498 * Create a plain I/O APIC object. 499 */ 500void * 501ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase) 502{ 503 struct ioapic *io; 504 struct ioapic_intsrc *intpin; 505 volatile ioapic_t *apic; 506 u_int numintr, i; 507 uint32_t value; 508 509 /* Map the register window so we can access the device. */ 510 apic = pmap_mapdev(addr, IOAPIC_MEM_REGION); 511 mtx_lock_spin(&icu_lock); 512 value = ioapic_read(apic, IOAPIC_VER); 513 mtx_unlock_spin(&icu_lock); 514 515 /* If it's version register doesn't seem to work, punt. */ 516 if (value == 0xffffffff) { 517 pmap_unmapdev((vm_offset_t)apic, IOAPIC_MEM_REGION); 518 return (NULL); 519 } 520 521 /* Determine the number of vectors and set the APIC ID. */ 522 numintr = ((value & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; 523 io = malloc(sizeof(struct ioapic) + 524 numintr * sizeof(struct ioapic_intsrc), M_IOAPIC, M_WAITOK); 525 io->io_pic = ioapic_template; 526 mtx_lock_spin(&icu_lock); 527 io->io_id = next_id++; 528 io->io_apic_id = ioapic_read(apic, IOAPIC_ID) >> APIC_ID_SHIFT; 529 if (apic_id != -1 && io->io_apic_id != apic_id) { 530 ioapic_write(apic, IOAPIC_ID, apic_id << APIC_ID_SHIFT); 531 mtx_unlock_spin(&icu_lock); 532 io->io_apic_id = apic_id; 533 printf("ioapic%u: Changing APIC ID to %d\n", io->io_id, 534 apic_id); 535 } else 536 mtx_unlock_spin(&icu_lock); 537 if (intbase == -1) { 538 intbase = next_ioapic_base; 539 printf("ioapic%u: Assuming intbase of %d\n", io->io_id, 540 intbase); 541 } else if (intbase != next_ioapic_base && bootverbose) 542 printf("ioapic%u: WARNING: intbase %d != expected base %d\n", 543 io->io_id, intbase, next_ioapic_base); 544 io->io_intbase = intbase; 545 next_ioapic_base = intbase + numintr; 546 io->io_numintr = numintr; 547 io->io_addr = apic; 548 io->io_paddr = addr; 549 550 /* 551 * Initialize pins. Start off with interrupts disabled. Default 552 * to active-hi and edge-triggered for ISA interrupts and active-lo 553 * and level-triggered for all others. 554 */ 555 bzero(io->io_pins, sizeof(struct ioapic_intsrc) * numintr); 556 mtx_lock_spin(&icu_lock); 557 for (i = 0, intpin = io->io_pins; i < numintr; i++, intpin++) { 558 intpin->io_intsrc.is_pic = (struct pic *)io; 559 intpin->io_intpin = i; 560 intpin->io_irq = intbase + i; 561 562 /* 563 * Assume that pin 0 on the first I/O APIC is an ExtINT pin. 564 * Assume that pins 1-15 are ISA interrupts and that all 565 * other pins are PCI interrupts. 566 */ 567 if (intpin->io_irq == 0) 568 ioapic_set_extint(io, i); 569 else if (intpin->io_irq < IOAPIC_ISA_INTS) { 570 intpin->io_bus = APIC_BUS_ISA; 571 intpin->io_activehi = 1; 572 intpin->io_edgetrigger = 1; 573 intpin->io_masked = 1; 574 } else { 575 intpin->io_bus = APIC_BUS_PCI; 576 intpin->io_activehi = 0; 577 intpin->io_edgetrigger = 0; 578 intpin->io_masked = 1; 579 } 580 581 /* 582 * Route interrupts to the BSP by default. Interrupts may 583 * be routed to other CPUs later after they are enabled. 584 */ 585 intpin->io_cpu = PCPU_GET(apic_id); 586 value = ioapic_read(apic, IOAPIC_REDTBL_LO(i)); 587 ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET); 588 } 589 mtx_unlock_spin(&icu_lock); 590 591 return (io); 592} 593 594int 595ioapic_get_vector(void *cookie, u_int pin) 596{ 597 struct ioapic *io; 598 599 io = (struct ioapic *)cookie; 600 if (pin >= io->io_numintr) 601 return (-1); 602 return (io->io_pins[pin].io_irq); 603} 604 605int 606ioapic_disable_pin(void *cookie, u_int pin) 607{ 608 struct ioapic *io; 609 610 io = (struct ioapic *)cookie; 611 if (pin >= io->io_numintr) 612 return (EINVAL); 613 if (io->io_pins[pin].io_irq == IRQ_DISABLED) 614 return (EINVAL); 615 io->io_pins[pin].io_irq = IRQ_DISABLED; 616 if (bootverbose) 617 printf("ioapic%u: intpin %d disabled\n", io->io_id, pin); 618 return (0); 619} 620 621int 622ioapic_remap_vector(void *cookie, u_int pin, int vector) 623{ 624 struct ioapic *io; 625 626 io = (struct ioapic *)cookie; 627 if (pin >= io->io_numintr || vector < 0) 628 return (EINVAL); 629 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 630 return (EINVAL); 631 io->io_pins[pin].io_irq = vector; 632 if (bootverbose) 633 printf("ioapic%u: Routing IRQ %d -> intpin %d\n", io->io_id, 634 vector, pin); 635 return (0); 636} 637 638int 639ioapic_set_bus(void *cookie, u_int pin, int bus_type) 640{ 641 struct ioapic *io; 642 643 if (bus_type < 0 || bus_type > APIC_BUS_MAX) 644 return (EINVAL); 645 io = (struct ioapic *)cookie; 646 if (pin >= io->io_numintr) 647 return (EINVAL); 648 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 649 return (EINVAL); 650 if (io->io_pins[pin].io_bus == bus_type) 651 return (0); 652 io->io_pins[pin].io_bus = bus_type; 653 if (bootverbose) 654 printf("ioapic%u: intpin %d bus %s\n", io->io_id, pin, 655 ioapic_bus_string(bus_type)); 656 return (0); 657} 658 659int 660ioapic_set_nmi(void *cookie, u_int pin) 661{ 662 struct ioapic *io; 663 664 io = (struct ioapic *)cookie; 665 if (pin >= io->io_numintr) 666 return (EINVAL); 667 if (io->io_pins[pin].io_irq == IRQ_NMI) 668 return (0); 669 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 670 return (EINVAL); 671 io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; 672 io->io_pins[pin].io_irq = IRQ_NMI; 673 io->io_pins[pin].io_masked = 0; 674 io->io_pins[pin].io_edgetrigger = 1; 675 io->io_pins[pin].io_activehi = 1; 676 if (bootverbose) 677 printf("ioapic%u: Routing NMI -> intpin %d\n", 678 io->io_id, pin); 679 return (0); 680} 681 682int 683ioapic_set_smi(void *cookie, u_int pin) 684{ 685 struct ioapic *io; 686 687 io = (struct ioapic *)cookie; 688 if (pin >= io->io_numintr) 689 return (EINVAL); 690 if (io->io_pins[pin].io_irq == IRQ_SMI) 691 return (0); 692 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 693 return (EINVAL); 694 io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; 695 io->io_pins[pin].io_irq = IRQ_SMI; 696 io->io_pins[pin].io_masked = 0; 697 io->io_pins[pin].io_edgetrigger = 1; 698 io->io_pins[pin].io_activehi = 1; 699 if (bootverbose) 700 printf("ioapic%u: Routing SMI -> intpin %d\n", 701 io->io_id, pin); 702 return (0); 703} 704 705int 706ioapic_set_extint(void *cookie, u_int pin) 707{ 708 struct ioapic *io; 709 710 io = (struct ioapic *)cookie; 711 if (pin >= io->io_numintr) 712 return (EINVAL); 713 if (io->io_pins[pin].io_irq == IRQ_EXTINT) 714 return (0); 715 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 716 return (EINVAL); 717 io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; 718 io->io_pins[pin].io_irq = IRQ_EXTINT; 719 if (enable_extint) 720 io->io_pins[pin].io_masked = 0; 721 else 722 io->io_pins[pin].io_masked = 1; 723 io->io_pins[pin].io_edgetrigger = 1; 724 io->io_pins[pin].io_activehi = 1; 725 if (bootverbose) 726 printf("ioapic%u: Routing external 8259A's -> intpin %d\n", 727 io->io_id, pin); 728 return (0); 729} 730 731int 732ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol) 733{ 734 struct ioapic *io; 735 int activehi; 736 737 io = (struct ioapic *)cookie; 738 if (pin >= io->io_numintr || pol == INTR_POLARITY_CONFORM) 739 return (EINVAL); 740 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 741 return (EINVAL); 742 activehi = (pol == INTR_POLARITY_HIGH); 743 if (io->io_pins[pin].io_activehi == activehi) 744 return (0); 745 io->io_pins[pin].io_activehi = activehi; 746 if (bootverbose) 747 printf("ioapic%u: intpin %d polarity: %s\n", io->io_id, pin, 748 pol == INTR_POLARITY_HIGH ? "high" : "low"); 749 return (0); 750} 751 752int 753ioapic_set_triggermode(void *cookie, u_int pin, enum intr_trigger trigger) 754{ 755 struct ioapic *io; 756 int edgetrigger; 757 758 io = (struct ioapic *)cookie; 759 if (pin >= io->io_numintr || trigger == INTR_TRIGGER_CONFORM) 760 return (EINVAL); 761 if (io->io_pins[pin].io_irq >= NUM_IO_INTS) 762 return (EINVAL); 763 edgetrigger = (trigger == INTR_TRIGGER_EDGE); 764 if (io->io_pins[pin].io_edgetrigger == edgetrigger) 765 return (0); 766 io->io_pins[pin].io_edgetrigger = edgetrigger; 767 if (bootverbose) 768 printf("ioapic%u: intpin %d trigger: %s\n", io->io_id, pin, 769 trigger == INTR_TRIGGER_EDGE ? "edge" : "level"); 770 return (0); 771} 772 773/* 774 * Register a complete I/O APIC object with the interrupt subsystem. 775 */ 776void 777ioapic_register(void *cookie) 778{ 779 struct ioapic_intsrc *pin; 780 struct ioapic *io; 781 volatile ioapic_t *apic; 782 uint32_t flags; 783 int i; 784 785 io = (struct ioapic *)cookie; 786 apic = io->io_addr; 787 mtx_lock_spin(&icu_lock); 788 flags = ioapic_read(apic, IOAPIC_VER) & IOART_VER_VERSION; 789 STAILQ_INSERT_TAIL(&ioapic_list, io, io_next); 790 mtx_unlock_spin(&icu_lock); 791 printf("ioapic%u <Version %u.%u> irqs %u-%u on motherboard\n", 792 io->io_id, flags >> 4, flags & 0xf, io->io_intbase, 793 io->io_intbase + io->io_numintr - 1); 794 795 /* Register valid pins as interrupt sources. */ 796 intr_register_pic(&io->io_pic); 797 for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++) 798 if (pin->io_irq < NUM_IO_INTS) 799 intr_register_source(&pin->io_intsrc); 800} 801 802/* A simple new-bus driver to consume PCI I/O APIC devices. */ 803static int 804ioapic_pci_probe(device_t dev) 805{ 806 807 if (pci_get_class(dev) == PCIC_BASEPERIPH && 808 pci_get_subclass(dev) == PCIS_BASEPERIPH_PIC) { 809 switch (pci_get_progif(dev)) { 810 case PCIP_BASEPERIPH_PIC_IO_APIC: 811 device_set_desc(dev, "IO APIC"); 812 break; 813 case PCIP_BASEPERIPH_PIC_IOX_APIC: 814 device_set_desc(dev, "IO(x) APIC"); 815 break; 816 default: 817 return (ENXIO); 818 } 819 device_quiet(dev); 820 return (-10000); 821 } 822 return (ENXIO); 823} 824 825static int 826ioapic_pci_attach(device_t dev) 827{ 828 829 return (0); 830} 831 832static device_method_t ioapic_pci_methods[] = { 833 /* Device interface */ 834 DEVMETHOD(device_probe, ioapic_pci_probe), 835 DEVMETHOD(device_attach, ioapic_pci_attach), 836 837 { 0, 0 } 838}; 839 840DEFINE_CLASS_0(ioapic, ioapic_pci_driver, ioapic_pci_methods, 0); 841 842static devclass_t ioapic_devclass; 843DRIVER_MODULE(ioapic, pci, ioapic_pci_driver, ioapic_devclass, 0, 0); 844 845/* 846 * A new-bus driver to consume the memory resources associated with 847 * the APICs in the system. On some systems ACPI or PnPBIOS system 848 * resource devices may already claim these resources. To keep from 849 * breaking those devices, we attach ourself to the nexus device after 850 * legacy0 and acpi0 and ignore any allocation failures. 851 */ 852static void 853apic_identify(driver_t *driver, device_t parent) 854{ 855 856 /* 857 * Add at order 12. acpi0 is probed at order 10 and legacy0 858 * is probed at order 11. 859 */ 860 if (lapic_paddr != 0) 861 BUS_ADD_CHILD(parent, 12, "apic", 0); 862} 863 864static int 865apic_probe(device_t dev) 866{ 867 868 device_set_desc(dev, "APIC resources"); 869 device_quiet(dev); 870 return (0); 871} 872 873static void 874apic_add_resource(device_t dev, int rid, vm_paddr_t base, size_t length) 875{ 876 int error; 877 878#ifdef PAE 879 /* 880 * Resources use long's to track resources, so we can't 881 * include memory regions above 4GB. 882 */ 883 if (base >= ~0ul) 884 return; 885#endif 886 error = bus_set_resource(dev, SYS_RES_MEMORY, rid, base, length); 887 if (error) 888 panic("apic_add_resource: resource %d failed set with %d", rid, 889 error); 890 bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0); 891} 892 893static int 894apic_attach(device_t dev) 895{ 896 struct ioapic *io; 897 int i; 898 899 /* Reserve the local APIC. */ 900 apic_add_resource(dev, 0, lapic_paddr, sizeof(lapic_t)); 901 i = 1; 902 STAILQ_FOREACH(io, &ioapic_list, io_next) { 903 apic_add_resource(dev, i, io->io_paddr, IOAPIC_MEM_REGION); 904 i++; 905 } 906 return (0); 907} 908 909static device_method_t apic_methods[] = { 910 /* Device interface */ 911 DEVMETHOD(device_identify, apic_identify), 912 DEVMETHOD(device_probe, apic_probe), 913 DEVMETHOD(device_attach, apic_attach), 914 915 { 0, 0 } 916}; 917 918DEFINE_CLASS_0(apic, apic_driver, apic_methods, 0); 919 920static devclass_t apic_devclass; 921DRIVER_MODULE(apic, nexus, apic_driver, apic_devclass, 0, 0); 922 923#include "opt_ddb.h" 924 925#ifdef DDB 926#include <ddb/ddb.h> 927 928static const char * 929ioapic_delivery_mode(uint32_t mode) 930{ 931 932 switch (mode) { 933 case IOART_DELFIXED: 934 return ("fixed"); 935 case IOART_DELLOPRI: 936 return ("lowestpri"); 937 case IOART_DELSMI: 938 return ("SMI"); 939 case IOART_DELRSV1: 940 return ("rsrvd1"); 941 case IOART_DELNMI: 942 return ("NMI"); 943 case IOART_DELINIT: 944 return ("INIT"); 945 case IOART_DELRSV2: 946 return ("rsrvd2"); 947 case IOART_DELEXINT: 948 return ("ExtINT"); 949 default: 950 return (""); 951 } 952} 953 954static u_int 955db_ioapic_read(volatile ioapic_t *apic, int reg) 956{ 957 958 apic->ioregsel = reg; 959 return (apic->iowin); 960} 961 962static void 963db_show_ioapic_one(volatile ioapic_t *io_addr) 964{ 965 uint32_t r, lo, hi; 966 int mre, i; 967 968 r = db_ioapic_read(io_addr, IOAPIC_VER); 969 mre = (r & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT; 970 db_printf("Id 0x%08x Ver 0x%02x MRE %d\n", 971 db_ioapic_read(io_addr, IOAPIC_ID), r & IOART_VER_VERSION, mre); 972 for (i = 0; i < mre; i++) { 973 lo = db_ioapic_read(io_addr, IOAPIC_REDTBL_LO(i)); 974 hi = db_ioapic_read(io_addr, IOAPIC_REDTBL_HI(i)); 975 db_printf(" pin %d Dest %s/%x %smasked Trig %s RemoteIRR %d " 976 "Polarity %s Status %s DeliveryMode %s Vec %d\n", i, 977 (lo & IOART_DESTMOD) == IOART_DESTLOG ? "log" : "phy", 978 (hi & IOART_DEST) >> 24, 979 (lo & IOART_INTMASK) == IOART_INTMSET ? "" : "not", 980 (lo & IOART_TRGRMOD) == IOART_TRGRLVL ? "lvl" : "edge", 981 (lo & IOART_REM_IRR) == IOART_REM_IRR ? 1 : 0, 982 (lo & IOART_INTPOL) == IOART_INTALO ? "low" : "high", 983 (lo & IOART_DELIVS) == IOART_DELIVS ? "pend" : "idle", 984 ioapic_delivery_mode(lo & IOART_DELMOD), 985 (lo & IOART_INTVEC)); 986 } 987} 988 989DB_SHOW_COMMAND(ioapic, db_show_ioapic) 990{ 991 struct ioapic *ioapic; 992 int idx, i; 993 994 if (!have_addr) { 995 db_printf("usage: show ioapic index\n"); 996 return; 997 } 998 999 idx = (int)addr; 1000 i = 0; 1001 STAILQ_FOREACH(ioapic, &ioapic_list, io_next) { 1002 if (idx == i) { 1003 db_show_ioapic_one(ioapic->io_addr); 1004 break; 1005 } 1006 i++; 1007 } 1008} 1009 1010DB_SHOW_ALL_COMMAND(ioapics, db_show_all_ioapics) 1011{ 1012 struct ioapic *ioapic; 1013 1014 STAILQ_FOREACH(ioapic, &ioapic_list, io_next) 1015 db_show_ioapic_one(ioapic->io_addr); 1016} 1017#endif 1018