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$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/limits.h> 35 #include <sys/malloc.h> 36 #include <sys/smp.h> 37 #include <vm/vm.h> 38 #include <vm/pmap.h> 39 40 #include <x86/apicreg.h> 41 #include <machine/intr_machdep.h> 42 #include <x86/apicvar.h> 43 #include <machine/md_var.h> 44 #include <x86/vmware.h> 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/aclocal.h> 48 #include <contrib/dev/acpica/include/actables.h> 49 50 #include <dev/acpica/acpivar.h> 51 #include <dev/pci/pcivar.h> 52 53 /* These two arrays are indexed by APIC IDs. */ 54 static struct { 55 void *io_apic; 56 UINT32 io_vector; 57 } *ioapics; 58 59 static struct lapic_info { 60 u_int la_enabled; 61 u_int la_acpi_id; 62 } lapics[MAX_APIC_ID + 1]; 63 64 int madt_found_sci_override; 65 static ACPI_TABLE_MADT *madt; 66 static vm_paddr_t madt_physaddr; 67 static vm_offset_t madt_length; 68 69 static MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 70 71 static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 72 static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 73 static int madt_find_cpu(u_int acpi_id, u_int *apic_id); 74 static int madt_find_interrupt(int intr, void **apic, u_int *pin); 75 static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 76 static void madt_parse_interrupt_override( 77 ACPI_MADT_INTERRUPT_OVERRIDE *intr); 78 static void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 79 void *arg __unused); 80 static void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 81 static void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 82 static int madt_probe(void); 83 static int madt_probe_cpus(void); 84 static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 85 void *arg __unused); 86 static void madt_register(void *dummy); 87 static int madt_setup_local(void); 88 static int madt_setup_io(void); 89 static void madt_walk_table(acpi_subtable_handler *handler, void *arg); 90 91 static struct apic_enumerator madt_enumerator = { 92 "MADT", 93 madt_probe, 94 madt_probe_cpus, 95 madt_setup_local, 96 madt_setup_io 97 }; 98 99 /* 100 * Look for an ACPI Multiple APIC Description Table ("APIC") 101 */ 102 static int 103 madt_probe(void) 104 { 105 106 madt_physaddr = acpi_find_table(ACPI_SIG_MADT); 107 if (madt_physaddr == 0) 108 return (ENXIO); 109 return (-50); 110 } 111 112 /* 113 * Run through the MP table enumerating CPUs. 114 */ 115 static int 116 madt_probe_cpus(void) 117 { 118 119 madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); 120 madt_length = madt->Header.Length; 121 KASSERT(madt != NULL, ("Unable to re-map MADT")); 122 madt_walk_table(madt_probe_cpus_handler, NULL); 123 acpi_unmap_table(madt); 124 madt = NULL; 125 return (0); 126 } 127 128 /* 129 * Initialize the local APIC on the BSP. 130 */ 131 static int 132 madt_setup_local(void) 133 { 134 ACPI_TABLE_DMAR *dmartbl; 135 vm_paddr_t dmartbl_physaddr; 136 const char *reason; 137 char *hw_vendor; 138 u_int p[4]; 139 int user_x2apic; 140 bool bios_x2apic; 141 142 madt = pmap_mapbios(madt_physaddr, madt_length); 143 if ((cpu_feature2 & CPUID2_X2APIC) != 0) { 144 reason = NULL; 145 146 /* 147 * Automatically detect several configurations where 148 * x2APIC mode is known to cause troubles. User can 149 * override the setting with hw.x2apic_enable tunable. 150 */ 151 dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR); 152 if (dmartbl_physaddr != 0) { 153 dmartbl = acpi_map_table(dmartbl_physaddr, 154 ACPI_SIG_DMAR); 155 if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) 156 reason = "by DMAR table"; 157 acpi_unmap_table(dmartbl); 158 } 159 if (vm_guest == VM_GUEST_VMWARE) { 160 vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p); 161 if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 || 162 (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) 163 reason = 164 "inside VMWare without intr redirection"; 165 } else if (vm_guest == VM_GUEST_XEN) { 166 reason = "due to running under XEN"; 167 } else if (vm_guest == VM_GUEST_NO && 168 CPUID_TO_FAMILY(cpu_id) == 0x6 && 169 CPUID_TO_MODEL(cpu_id) == 0x2a) { 170 hw_vendor = kern_getenv("smbios.planar.maker"); 171 /* 172 * It seems that some Lenovo and ASUS 173 * SandyBridge-based notebook BIOSes have a 174 * bug which prevents booting AP in x2APIC 175 * mode. Since the only way to detect mobile 176 * CPU is to check northbridge pci id, which 177 * cannot be done that early, disable x2APIC 178 * for all Lenovo and ASUS SandyBridge 179 * machines. 180 */ 181 if (hw_vendor != NULL) { 182 if (!strcmp(hw_vendor, "LENOVO") || 183 !strcmp(hw_vendor, 184 "ASUSTeK Computer Inc.")) { 185 reason = 186 "for a suspected SandyBridge BIOS bug"; 187 } 188 freeenv(hw_vendor); 189 } 190 } 191 bios_x2apic = lapic_is_x2apic(); 192 if (reason != NULL && bios_x2apic) { 193 if (bootverbose) 194 printf("x2APIC should be disabled %s but " 195 "already enabled by BIOS; enabling.\n", 196 reason); 197 reason = NULL; 198 } 199 if (reason == NULL) 200 x2apic_mode = 1; 201 else if (bootverbose) 202 printf("x2APIC available but disabled %s\n", reason); 203 user_x2apic = x2apic_mode; 204 TUNABLE_INT_FETCH("hw.x2apic_enable", &user_x2apic); 205 if (user_x2apic != x2apic_mode) { 206 if (bios_x2apic && !user_x2apic) 207 printf("x2APIC disabled by tunable and " 208 "enabled by BIOS; ignoring tunable."); 209 else 210 x2apic_mode = user_x2apic; 211 } 212 } 213 214 lapic_init(madt->Address); 215 printf("ACPI APIC Table: <%.*s %.*s>\n", 216 (int)sizeof(madt->Header.OemId), madt->Header.OemId, 217 (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 218 219 /* 220 * We ignore 64-bit local APIC override entries. Should we 221 * perhaps emit a warning here if we find one? 222 */ 223 return (0); 224 } 225 226 /* 227 * Enumerate I/O APICs and setup interrupt sources. 228 */ 229 static int 230 madt_setup_io(void) 231 { 232 void *ioapic; 233 u_int pin; 234 int i; 235 236 /* Try to initialize ACPI so that we can access the FADT. */ 237 i = acpi_Startup(); 238 if (ACPI_FAILURE(i)) { 239 printf("MADT: ACPI Startup failed with %s\n", 240 AcpiFormatException(i)); 241 printf("Try disabling either ACPI or apic support.\n"); 242 panic("Using MADT but ACPI doesn't work"); 243 } 244 245 ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 246 M_WAITOK | M_ZERO); 247 248 /* First, we run through adding I/O APIC's. */ 249 madt_walk_table(madt_parse_apics, NULL); 250 251 /* Second, we run through the table tweaking interrupt sources. */ 252 madt_walk_table(madt_parse_ints, NULL); 253 254 /* 255 * If there was not an explicit override entry for the SCI, 256 * force it to use level trigger and active-low polarity. 257 */ 258 if (!madt_found_sci_override) { 259 if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 260 &pin) != 0) 261 printf("MADT: Could not find APIC for SCI IRQ %u\n", 262 AcpiGbl_FADT.SciInterrupt); 263 else { 264 printf( 265 "MADT: Forcing active-low polarity and level trigger for SCI\n"); 266 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 267 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 268 } 269 } 270 271 /* Third, we register all the I/O APIC's. */ 272 for (i = 0; i <= MAX_APIC_ID; i++) 273 if (ioapics[i].io_apic != NULL) 274 ioapic_register(ioapics[i].io_apic); 275 276 /* Finally, we throw the switch to enable the I/O APIC's. */ 277 acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 278 279 free(ioapics, M_MADT); 280 ioapics = NULL; 281 282 return (0); 283 } 284 285 static void 286 madt_register(void *dummy __unused) 287 { 288 289 apic_register_enumerator(&madt_enumerator); 290 } 291 SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 292 293 /* 294 * Call the handler routine for each entry in the MADT table. 295 */ 296 static void 297 madt_walk_table(acpi_subtable_handler *handler, void *arg) 298 { 299 300 acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 301 handler, arg); 302 } 303 304 static void 305 madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags) 306 { 307 struct lapic_info *la; 308 309 /* 310 * The MADT does not include a BSP flag, so we have to let the 311 * MP code figure out which CPU is the BSP on its own. 312 */ 313 if (bootverbose) 314 printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 315 apic_id, acpi_id, flags & ACPI_MADT_ENABLED ? 316 "enabled" : "disabled"); 317 if (!(flags & ACPI_MADT_ENABLED)) 318 return; 319 if (apic_id > MAX_APIC_ID) { 320 printf("MADT: Ignoring local APIC ID %u (too high)\n", 321 apic_id); 322 return; 323 } 324 325 la = &lapics[apic_id]; 326 KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id)); 327 la->la_enabled = 1; 328 la->la_acpi_id = acpi_id; 329 lapic_create(apic_id, 0); 330 } 331 332 static void 333 madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 334 { 335 ACPI_MADT_LOCAL_APIC *proc; 336 ACPI_MADT_LOCAL_X2APIC *x2apic; 337 338 switch (entry->Type) { 339 case ACPI_MADT_TYPE_LOCAL_APIC: 340 proc = (ACPI_MADT_LOCAL_APIC *)entry; 341 madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags); 342 break; 343 case ACPI_MADT_TYPE_LOCAL_X2APIC: 344 x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry; 345 madt_add_cpu(x2apic->Uid, x2apic->LocalApicId, 346 x2apic->LapicFlags); 347 break; 348 } 349 } 350 351 352 /* 353 * Add an I/O APIC from an entry in the table. 354 */ 355 static void 356 madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 357 { 358 ACPI_MADT_IO_APIC *apic; 359 360 switch (entry->Type) { 361 case ACPI_MADT_TYPE_IO_APIC: 362 apic = (ACPI_MADT_IO_APIC *)entry; 363 if (bootverbose) 364 printf( 365 "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 366 apic->Id, apic->GlobalIrqBase, 367 (void *)(uintptr_t)apic->Address); 368 if (apic->Id > MAX_APIC_ID) 369 panic("%s: I/O APIC ID %u too high", __func__, 370 apic->Id); 371 if (ioapics[apic->Id].io_apic != NULL) 372 panic("%s: Double APIC ID %u", __func__, apic->Id); 373 if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 374 printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 375 break; 376 } 377 ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 378 apic->Id, apic->GlobalIrqBase); 379 ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 380 break; 381 default: 382 break; 383 } 384 } 385 386 /* 387 * Determine properties of an interrupt source. Note that for ACPI these 388 * functions are only used for ISA interrupts, so we assume ISA bus values 389 * (Active Hi, Edge Triggered) for conforming values except for the ACPI 390 * SCI for which we use Active Lo, Level Triggered. 391 */ 392 static enum intr_polarity 393 interrupt_polarity(UINT16 IntiFlags, UINT8 Source) 394 { 395 396 switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 397 default: 398 printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 399 /* FALLTHROUGH*/ 400 case ACPI_MADT_POLARITY_CONFORMS: 401 if (Source == AcpiGbl_FADT.SciInterrupt) 402 return (INTR_POLARITY_LOW); 403 else 404 return (INTR_POLARITY_HIGH); 405 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 406 return (INTR_POLARITY_HIGH); 407 case ACPI_MADT_POLARITY_ACTIVE_LOW: 408 return (INTR_POLARITY_LOW); 409 } 410 } 411 412 static enum intr_trigger 413 interrupt_trigger(UINT16 IntiFlags, UINT8 Source) 414 { 415 416 switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 417 default: 418 printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 419 /*FALLTHROUGH*/ 420 case ACPI_MADT_TRIGGER_CONFORMS: 421 if (Source == AcpiGbl_FADT.SciInterrupt) 422 return (INTR_TRIGGER_LEVEL); 423 else 424 return (INTR_TRIGGER_EDGE); 425 case ACPI_MADT_TRIGGER_EDGE: 426 return (INTR_TRIGGER_EDGE); 427 case ACPI_MADT_TRIGGER_LEVEL: 428 return (INTR_TRIGGER_LEVEL); 429 } 430 } 431 432 /* 433 * Find the local APIC ID associated with a given ACPI Processor ID. 434 */ 435 static int 436 madt_find_cpu(u_int acpi_id, u_int *apic_id) 437 { 438 int i; 439 440 for (i = 0; i <= MAX_APIC_ID; i++) { 441 if (!lapics[i].la_enabled) 442 continue; 443 if (lapics[i].la_acpi_id != acpi_id) 444 continue; 445 *apic_id = i; 446 return (0); 447 } 448 return (ENOENT); 449 } 450 451 /* 452 * Find the IO APIC and pin on that APIC associated with a given global 453 * interrupt. 454 */ 455 static int 456 madt_find_interrupt(int intr, void **apic, u_int *pin) 457 { 458 int i, best; 459 460 best = -1; 461 for (i = 0; i <= MAX_APIC_ID; i++) { 462 if (ioapics[i].io_apic == NULL || 463 ioapics[i].io_vector > intr) 464 continue; 465 if (best == -1 || 466 ioapics[best].io_vector < ioapics[i].io_vector) 467 best = i; 468 } 469 if (best == -1) 470 return (ENOENT); 471 *apic = ioapics[best].io_apic; 472 *pin = intr - ioapics[best].io_vector; 473 if (*pin > 32) 474 printf("WARNING: Found intpin of %u for vector %d\n", *pin, 475 intr); 476 return (0); 477 } 478 479 void 480 madt_parse_interrupt_values(void *entry, 481 enum intr_trigger *trig, enum intr_polarity *pol) 482 { 483 ACPI_MADT_INTERRUPT_OVERRIDE *intr; 484 char buf[64]; 485 486 intr = entry; 487 488 if (bootverbose) 489 printf("MADT: Interrupt override: source %u, irq %u\n", 490 intr->SourceIrq, intr->GlobalIrq); 491 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 492 493 /* 494 * Lookup the appropriate trigger and polarity modes for this 495 * entry. 496 */ 497 *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 498 *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 499 500 /* 501 * If the SCI is identity mapped but has edge trigger and 502 * active-hi polarity or the force_sci_lo tunable is set, 503 * force it to use level/lo. 504 */ 505 if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 506 madt_found_sci_override = 1; 507 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 508 if (tolower(buf[0]) == 'e') 509 *trig = INTR_TRIGGER_EDGE; 510 else if (tolower(buf[0]) == 'l') 511 *trig = INTR_TRIGGER_LEVEL; 512 else 513 panic( 514 "Invalid trigger %s: must be 'edge' or 'level'", 515 buf); 516 printf("MADT: Forcing SCI to %s trigger\n", 517 *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 518 } 519 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 520 if (tolower(buf[0]) == 'h') 521 *pol = INTR_POLARITY_HIGH; 522 else if (tolower(buf[0]) == 'l') 523 *pol = INTR_POLARITY_LOW; 524 else 525 panic( 526 "Invalid polarity %s: must be 'high' or 'low'", 527 buf); 528 printf("MADT: Forcing SCI to active %s polarity\n", 529 *pol == INTR_POLARITY_HIGH ? "high" : "low"); 530 } 531 } 532 } 533 534 /* 535 * Parse an interrupt source override for an ISA interrupt. 536 */ 537 static void 538 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 539 { 540 void *new_ioapic, *old_ioapic; 541 u_int new_pin, old_pin; 542 enum intr_trigger trig; 543 enum intr_polarity pol; 544 545 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 546 intr->GlobalIrq == 2) { 547 if (bootverbose) 548 printf("MADT: Skipping timer override\n"); 549 return; 550 } 551 552 if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 553 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 554 intr->GlobalIrq, intr->SourceIrq); 555 return; 556 } 557 558 madt_parse_interrupt_values(intr, &trig, &pol); 559 560 /* Remap the IRQ if it is mapped to a different interrupt vector. */ 561 if (intr->SourceIrq != intr->GlobalIrq) { 562 /* 563 * If the SCI is remapped to a non-ISA global interrupt, 564 * then override the vector we use to setup and allocate 565 * the interrupt. 566 */ 567 if (intr->GlobalIrq > 15 && 568 intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 569 acpi_OverrideInterruptLevel(intr->GlobalIrq); 570 else 571 ioapic_remap_vector(new_ioapic, new_pin, 572 intr->SourceIrq); 573 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 574 &old_pin) != 0) 575 printf("MADT: Could not find APIC for source IRQ %u\n", 576 intr->SourceIrq); 577 else if (ioapic_get_vector(old_ioapic, old_pin) == 578 intr->SourceIrq) 579 ioapic_disable_pin(old_ioapic, old_pin); 580 } 581 582 /* Program the polarity and trigger mode. */ 583 ioapic_set_triggermode(new_ioapic, new_pin, trig); 584 ioapic_set_polarity(new_ioapic, new_pin, pol); 585 } 586 587 /* 588 * Parse an entry for an NMI routed to an IO APIC. 589 */ 590 static void 591 madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 592 { 593 void *ioapic; 594 u_int pin; 595 596 if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 597 printf("MADT: Could not find APIC for vector %u\n", 598 nmi->GlobalIrq); 599 return; 600 } 601 602 ioapic_set_nmi(ioapic, pin); 603 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 604 ioapic_set_triggermode(ioapic, pin, 605 interrupt_trigger(nmi->IntiFlags, 0)); 606 if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 607 ioapic_set_polarity(ioapic, pin, 608 interrupt_polarity(nmi->IntiFlags, 0)); 609 } 610 611 /* 612 * Parse an entry for an NMI routed to a local APIC LVT pin. 613 */ 614 static void 615 madt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags) 616 { 617 u_int apic_id, pin; 618 619 if (acpi_id == 0xffffffff) 620 apic_id = APIC_ID_ALL; 621 else if (madt_find_cpu(acpi_id, &apic_id) != 0) { 622 if (bootverbose) 623 printf("MADT: Ignoring local NMI routed to " 624 "ACPI CPU %u\n", acpi_id); 625 return; 626 } 627 if (Lint == 0) 628 pin = APIC_LVT_LINT0; 629 else 630 pin = APIC_LVT_LINT1; 631 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 632 if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 633 lapic_set_lvt_triggermode(apic_id, pin, 634 interrupt_trigger(IntiFlags, 0)); 635 if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 636 lapic_set_lvt_polarity(apic_id, pin, 637 interrupt_polarity(IntiFlags, 0)); 638 } 639 640 static void 641 madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 642 { 643 644 madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff : 645 nmi->ProcessorId, nmi->Lint, nmi->IntiFlags); 646 } 647 648 static void 649 madt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi) 650 { 651 652 madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags); 653 } 654 655 /* 656 * Parse interrupt entries. 657 */ 658 static void 659 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 660 { 661 662 switch (entry->Type) { 663 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 664 madt_parse_interrupt_override( 665 (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 666 break; 667 case ACPI_MADT_TYPE_NMI_SOURCE: 668 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 669 break; 670 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 671 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 672 break; 673 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 674 madt_parse_local_x2apic_nmi( 675 (ACPI_MADT_LOCAL_X2APIC_NMI *)entry); 676 break; 677 } 678 } 679 680 /* 681 * Setup per-CPU ACPI IDs. 682 */ 683 static void 684 madt_set_ids(void *dummy) 685 { 686 struct lapic_info *la; 687 struct pcpu *pc; 688 u_int i; 689 690 if (madt == NULL) 691 return; 692 CPU_FOREACH(i) { 693 pc = pcpu_find(i); 694 KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 695 la = &lapics[pc->pc_apic_id]; 696 if (!la->la_enabled) 697 panic("APIC: CPU with APIC ID %u is not enabled", 698 pc->pc_apic_id); 699 pc->pc_acpi_id = la->la_acpi_id; 700 if (bootverbose) 701 printf("APIC: CPU %u has ACPI ID %u\n", i, 702 la->la_acpi_id); 703 } 704 } 705 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 706