madt.c revision 128930
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 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/i386/acpica/madt.c 128930 2004-05-04 20:39:24Z jhb $"); 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/bus.h> 36#include <sys/kernel.h> 37#include <sys/malloc.h> 38#include <sys/smp.h> 39 40#include <vm/vm.h> 41#include <vm/vm_param.h> 42#include <vm/pmap.h> 43 44#include <machine/apicreg.h> 45#include <machine/frame.h> 46#include <machine/intr_machdep.h> 47#include <machine/apicvar.h> 48#include <machine/md_var.h> 49#include <machine/specialreg.h> 50 51#include "acpi.h" 52#include <dev/acpica/acpivar.h> 53#include <dev/pci/pcivar.h> 54 55#define NIOAPICS 32 /* Max number of I/O APICs */ 56#define NLAPICS 32 /* Max number of local APICs */ 57 58typedef void madt_entry_handler(APIC_HEADER *entry, void *arg); 59 60/* These two arrays are indexed by APIC IDs. */ 61struct ioapic_info { 62 void *io_apic; 63 UINT32 io_vector; 64} ioapics[NIOAPICS]; 65 66struct lapic_info { 67 u_int la_present:1; 68 u_int la_enabled:1; 69 u_int la_apic_id:8; 70} lapics[NLAPICS + 1]; 71 72static int madt_found_sci_override; 73static MULTIPLE_APIC_TABLE *madt; 74static vm_paddr_t madt_physaddr; 75static vm_offset_t madt_length; 76 77MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items"); 78 79static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source); 80static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source); 81static int madt_find_cpu(u_int acpi_id, u_int *apic_id); 82static int madt_find_interrupt(int intr, void **apic, u_int *pin); 83static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); 84static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); 85static void madt_parse_apics(APIC_HEADER *entry, void *arg); 86static void madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr); 87static void madt_parse_ints(APIC_HEADER *entry, void *arg __unused); 88static void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi); 89static void madt_parse_nmi(MADT_NMI_SOURCE *nmi); 90static int madt_probe(void); 91static int madt_probe_cpus(void); 92static void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused); 93static int madt_probe_table(vm_paddr_t address); 94static void madt_register(void *dummy); 95static int madt_setup_local(void); 96static int madt_setup_io(void); 97static void madt_unmap(void *data, vm_offset_t length); 98static void madt_unmap_table(void *table); 99static void madt_walk_table(madt_entry_handler *handler, void *arg); 100 101static struct apic_enumerator madt_enumerator = { 102 "MADT", 103 madt_probe, 104 madt_probe_cpus, 105 madt_setup_local, 106 madt_setup_io 107}; 108 109/* 110 * Code to abuse the crashdump map to map in the tables for the early 111 * probe. We cheat and make the following assumptions about how we 112 * use this KVA: page 0 is used to map in the first page of each table 113 * found via the RSDT or XSDT and pages 1 to n are used to map in the 114 * RSDT or XSDT. The offset is in pages; the length is in bytes. 115 */ 116static void * 117madt_map(vm_paddr_t pa, int offset, vm_offset_t length) 118{ 119 vm_offset_t va, off; 120 void *data; 121 122 off = pa & PAGE_MASK; 123 length = roundup(length + off, PAGE_SIZE); 124 pa = pa & PG_FRAME; 125 va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 126 (offset * PAGE_SIZE); 127 data = (void *)(va + off); 128 length -= PAGE_SIZE; 129 while (length > 0) { 130 va += PAGE_SIZE; 131 pa += PAGE_SIZE; 132 length -= PAGE_SIZE; 133 pmap_kenter(va, pa); 134 invlpg(va); 135 } 136 return (data); 137} 138 139static void 140madt_unmap(void *data, vm_offset_t length) 141{ 142 vm_offset_t va, off; 143 144 va = (vm_offset_t)data; 145 off = va & PAGE_MASK; 146 length = roundup(length + off, PAGE_SIZE); 147 va &= ~PAGE_MASK; 148 while (length > 0) { 149 pmap_kremove(va); 150 invlpg(va); 151 va += PAGE_SIZE; 152 length -= PAGE_SIZE; 153 } 154} 155 156static void * 157madt_map_table(vm_paddr_t pa, int offset, const char *sig) 158{ 159 ACPI_TABLE_HEADER *header; 160 vm_offset_t length; 161 162 header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 163 if (strncmp(header->Signature, sig, 4) != 0) { 164 madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 165 return (NULL); 166 } 167 length = header->Length; 168 madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 169 return (madt_map(pa, offset, length)); 170} 171 172static void 173madt_unmap_table(void *table) 174{ 175 ACPI_TABLE_HEADER *header; 176 177 header = (ACPI_TABLE_HEADER *)table; 178 madt_unmap(table, header->Length); 179} 180 181/* 182 * Look for an ACPI Multiple APIC Description Table ("APIC") 183 */ 184static int 185madt_probe(void) 186{ 187 ACPI_POINTER rsdp_ptr; 188 RSDP_DESCRIPTOR *rsdp; 189 RSDT_DESCRIPTOR *rsdt; 190 XSDT_DESCRIPTOR *xsdt; 191 int i, count; 192 193 if (resource_disabled("acpi", 0)) 194 return (ENXIO); 195 196 /* 197 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 198 * calls pmap_mapdev() to find the RSDP, we assume that we can use 199 * pmap_mapdev() to map the RSDP. 200 */ 201 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 202 return (ENXIO); 203#ifdef __i386__ 204 KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high")); 205#endif 206 rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR)); 207 if (rsdp == NULL) { 208 if (bootverbose) 209 printf("MADT: Failed to map RSDP\n"); 210 return (ENXIO); 211 } 212 213 /* 214 * For ACPI < 2.0, use the RSDT. For ACPI >= 2.0, use the XSDT. 215 * We map the XSDT and RSDT at page 1 in the crashdump area. 216 * Page 0 is used to map in the headers of candidate ACPI tables. 217 */ 218 if (rsdp->Revision >= 2) { 219 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG); 220 if (xsdt == NULL) { 221 if (bootverbose) 222 printf("MADT: Failed to map XSDT\n"); 223 return (ENXIO); 224 } 225 count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 226 sizeof(UINT64); 227 for (i = 0; i < count; i++) 228 if (madt_probe_table(xsdt->TableOffsetEntry[i])) 229 break; 230 madt_unmap_table(xsdt); 231 } else { 232 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG); 233 if (rsdt == NULL) { 234 if (bootverbose) 235 printf("MADT: Failed to map RSDT\n"); 236 return (ENXIO); 237 } 238 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 239 sizeof(UINT32); 240 for (i = 0; i < count; i++) 241 if (madt_probe_table(rsdt->TableOffsetEntry[i])) 242 break; 243 madt_unmap_table(rsdt); 244 } 245 pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR)); 246 if (madt_physaddr == 0) { 247 if (bootverbose) 248 printf("MADT: No MADT table found\n"); 249 return (ENXIO); 250 } 251 if (bootverbose) 252 printf("MADT: Found table at 0x%jx\n", 253 (uintmax_t)madt_physaddr); 254 255 return (0); 256} 257 258/* 259 * See if a given ACPI table is the MADT. 260 */ 261static int 262madt_probe_table(vm_paddr_t address) 263{ 264 ACPI_TABLE_HEADER *table; 265 266 table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 267 if (table == NULL) { 268 if (bootverbose) 269 printf("MADT: Failed to map table at 0x%jx\n", 270 (uintmax_t)address); 271 return (0); 272 } 273 if (bootverbose) 274 printf("Table '%.4s' at 0x%jx\n", table->Signature, 275 (uintmax_t)address); 276 277 /* XXX: Verify checksum? */ 278 if (strncmp(table->Signature, APIC_SIG, 4) != 0) { 279 madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 280 return (0); 281 } 282 madt_physaddr = address; 283 madt_length = table->Length; 284 madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 285 return (1); 286} 287 288/* 289 * Run through the MP table enumerating CPUs. 290 */ 291static int 292madt_probe_cpus(void) 293{ 294 295 madt = madt_map_table(madt_physaddr, 0, APIC_SIG); 296 KASSERT(madt != NULL, ("Unable to re-map MADT")); 297 madt_walk_table(madt_probe_cpus_handler, NULL); 298 madt_unmap_table(madt); 299 madt = NULL; 300 return (0); 301} 302 303/* 304 * Initialize the local APIC on the BSP. 305 */ 306static int 307madt_setup_local(void) 308{ 309 310 madt = pmap_mapdev(madt_physaddr, madt_length); 311 lapic_init((uintptr_t)madt->LocalApicAddress); 312 printf("ACPI APIC Table: <%.*s %.*s>\n", 313 (int)sizeof(madt->OemId), madt->OemId, 314 (int)sizeof(madt->OemTableId), madt->OemTableId); 315 316 /* 317 * We ignore 64-bit local APIC override entries. Should we 318 * perhaps emit a warning here if we find one? 319 */ 320 return (0); 321} 322 323/* 324 * Enumerate I/O APICs and setup interrupt sources. 325 */ 326static int 327madt_setup_io(void) 328{ 329 void *ioapic; 330 u_int pin; 331 int i; 332 333 /* Try to initialize ACPI so that we can access the FADT. */ 334 i = acpi_Startup(); 335 if (ACPI_FAILURE(i)) { 336 printf("MADT: ACPI Startup failed with %s\n", 337 AcpiFormatException(i)); 338 printf("Try disabling either ACPI or apic support.\n"); 339 panic("Using MADT but ACPI doesn't work"); 340 } 341 342 /* First, we run through adding I/O APIC's. */ 343 madt_walk_table(madt_parse_apics, NULL); 344 345 /* Second, we run through the table tweaking interrupt sources. */ 346 madt_walk_table(madt_parse_ints, NULL); 347 348 /* 349 * If there was not an explicit override entry for the SCI, 350 * force it to use level trigger and active-low polarity. 351 */ 352 if (!madt_found_sci_override) { 353 if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin) 354 != 0) 355 printf("MADT: Could not find APIC for SCI IRQ %d\n", 356 AcpiGbl_FADT->SciInt); 357 else { 358 printf( 359 "MADT: Forcing active-low polarity and level trigger for SCI\n"); 360 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 361 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 362 } 363 } 364 365 /* Third, we register all the I/O APIC's. */ 366 for (i = 0; i < NIOAPICS; i++) 367 if (ioapics[i].io_apic != NULL) 368 ioapic_register(ioapics[i].io_apic); 369 370 /* Finally, we throw the switch to enable the I/O APIC's. */ 371 acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 372 373 return (0); 374} 375 376static void 377madt_register(void *dummy __unused) 378{ 379 380 apic_register_enumerator(&madt_enumerator); 381} 382SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL) 383 384/* 385 * Call the handler routine for each entry in the MADT table. 386 */ 387static void 388madt_walk_table(madt_entry_handler *handler, void *arg) 389{ 390 APIC_HEADER *entry; 391 u_char *p, *end; 392 393 end = (u_char *)(madt) + madt->Length; 394 for (p = (u_char *)(madt + 1); p < end; ) { 395 entry = (APIC_HEADER *)p; 396 handler(entry, arg); 397 p += entry->Length; 398 } 399} 400 401static void 402madt_probe_cpus_handler(APIC_HEADER *entry, void *arg) 403{ 404 MADT_PROCESSOR_APIC *proc; 405 struct lapic_info *la; 406 407 switch (entry->Type) { 408 case APIC_PROCESSOR: 409 /* 410 * The MADT does not include a BSP flag, so we have to 411 * let the MP code figure out which CPU is the BSP on 412 * its own. 413 */ 414 proc = (MADT_PROCESSOR_APIC *)entry; 415 if (bootverbose) 416 printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", 417 proc->LocalApicId, proc->ProcessorId, 418 proc->ProcessorEnabled ? "enabled" : "disabled"); 419 if (proc->ProcessorId > NLAPICS) 420 panic("%s: CPU ID %d too high", __func__, 421 proc->ProcessorId); 422 la = &lapics[proc->ProcessorId]; 423 KASSERT(la->la_present == 0, 424 ("Duplicate local ACPI ID %d", proc->ProcessorId)); 425 la->la_present = 1; 426 la->la_apic_id = proc->LocalApicId; 427 if (proc->ProcessorEnabled) { 428 la->la_enabled = 1; 429 lapic_create(proc->LocalApicId, 0); 430 } 431 break; 432 } 433} 434 435 436/* 437 * Add an I/O APIC from an entry in the table. 438 */ 439static void 440madt_parse_apics(APIC_HEADER *entry, void *arg __unused) 441{ 442 MADT_IO_APIC *apic; 443 444 switch (entry->Type) { 445 case APIC_IO: 446 apic = (MADT_IO_APIC *)entry; 447 if (bootverbose) 448 printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n", 449 apic->IoApicId, apic->Interrupt, 450 (void *)(uintptr_t)apic->Address); 451 if (apic->IoApicId >= NIOAPICS) 452 panic("%s: I/O APIC ID %d too high", __func__, 453 apic->IoApicId); 454 if (ioapics[apic->IoApicId].io_apic != NULL) 455 panic("%s: Double APIC ID %d", __func__, 456 apic->IoApicId); 457 ioapics[apic->IoApicId].io_apic = ioapic_create( 458 (uintptr_t)apic->Address, apic->IoApicId, 459 apic->Interrupt); 460 ioapics[apic->IoApicId].io_vector = apic->Interrupt; 461 break; 462 default: 463 break; 464 } 465} 466 467/* 468 * Determine properties of an interrupt source. Note that for ACPI, 469 * these are only used for ISA interrupts, so we assume ISA bus values 470 * (Active Hi, Edge Triggered) for conforming values except for the ACPI 471 * SCI for which we use Active Lo, Level Triggered.. 472 */ 473static enum intr_polarity 474interrupt_polarity(UINT16 Polarity, UINT8 Source) 475{ 476 477 switch (Polarity) { 478 case POLARITY_CONFORMS: 479 if (Source == AcpiGbl_FADT->SciInt) 480 return (INTR_POLARITY_LOW); 481 else 482 return (INTR_POLARITY_HIGH); 483 case POLARITY_ACTIVE_HIGH: 484 return (INTR_POLARITY_HIGH); 485 case POLARITY_ACTIVE_LOW: 486 return (INTR_POLARITY_LOW); 487 default: 488 panic("Bogus Interrupt Polarity"); 489 } 490} 491 492static enum intr_trigger 493interrupt_trigger(UINT16 TriggerMode, UINT8 Source) 494{ 495 496 switch (TriggerMode) { 497 case TRIGGER_CONFORMS: 498 if (Source == AcpiGbl_FADT->SciInt) 499 return (INTR_TRIGGER_LEVEL); 500 else 501 return (INTR_TRIGGER_EDGE); 502 case TRIGGER_EDGE: 503 return (INTR_TRIGGER_EDGE); 504 case TRIGGER_LEVEL: 505 return (INTR_TRIGGER_LEVEL); 506 default: 507 panic("Bogus Interrupt Trigger Mode"); 508 } 509} 510 511/* 512 * Find the local APIC ID associated with a given ACPI Processor ID. 513 */ 514static int 515madt_find_cpu(u_int acpi_id, u_int *apic_id) 516{ 517 518 if (!lapics[acpi_id].la_present) 519 return (ENOENT); 520 *apic_id = lapics[acpi_id].la_apic_id; 521 if (lapics[acpi_id].la_enabled) 522 return (0); 523 else 524 return (ENXIO); 525} 526 527/* 528 * Find the IO APIC and pin on that APIC associated with a given global 529 * interrupt. 530 */ 531static int 532madt_find_interrupt(int intr, void **apic, u_int *pin) 533{ 534 int i, best; 535 536 best = -1; 537 for (i = 0; i < NIOAPICS; i++) { 538 if (ioapics[i].io_apic == NULL || 539 ioapics[i].io_vector > intr) 540 continue; 541 if (best == -1 || 542 ioapics[best].io_vector < ioapics[i].io_vector) 543 best = i; 544 } 545 if (best == -1) 546 return (ENOENT); 547 *apic = ioapics[best].io_apic; 548 *pin = intr - ioapics[best].io_vector; 549 if (*pin > 32) 550 printf("WARNING: Found intpin of %u for vector %d\n", *pin, 551 intr); 552 return (0); 553} 554 555/* 556 * Parse an interrupt source override for an ISA interrupt. 557 */ 558static void 559madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr) 560{ 561 void *new_ioapic, *old_ioapic; 562 u_int new_pin, old_pin; 563 enum intr_trigger trig; 564 enum intr_polarity pol; 565 char buf[64]; 566 567 if (bootverbose) 568 printf("MADT: intr override: source %u, irq %u\n", 569 intr->Source, intr->Interrupt); 570 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 571 if (madt_find_interrupt(intr->Interrupt, &new_ioapic, 572 &new_pin) != 0) { 573 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n", 574 intr->Interrupt, intr->Source); 575 return; 576 } 577 578 /* 579 * Lookup the appropriate trigger and polarity modes for this 580 * entry. 581 */ 582 trig = interrupt_trigger(intr->TriggerMode, intr->Source); 583 pol = interrupt_polarity(intr->Polarity, intr->Source); 584 585 /* 586 * If the SCI is identity mapped but has edge trigger and 587 * active-hi polarity or the force_sci_lo tunable is set, 588 * force it to use level/lo. 589 */ 590 if (intr->Source == AcpiGbl_FADT->SciInt) { 591 madt_found_sci_override = 1; 592 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 593 if (tolower(buf[0]) == 'e') 594 trig = INTR_TRIGGER_EDGE; 595 else if (tolower(buf[0]) == 'l') 596 trig = INTR_TRIGGER_LEVEL; 597 else 598 panic( 599 "Invalid trigger %s: must be 'edge' or 'level'", 600 buf); 601 printf("MADT: Forcing SCI to %s trigger\n", 602 trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 603 } 604 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 605 if (tolower(buf[0]) == 'h') 606 pol = INTR_POLARITY_HIGH; 607 else if (tolower(buf[0]) == 'l') 608 pol = INTR_POLARITY_LOW; 609 else 610 panic( 611 "Invalid polarity %s: must be 'high' or 'low'", 612 buf); 613 printf("MADT: Forcing SCI to active %s polarity\n", 614 pol == INTR_POLARITY_HIGH ? "high" : "low"); 615 } 616 } 617 618 /* Remap the IRQ if it is mapped to a different interrupt vector. */ 619 if (intr->Source != intr->Interrupt) { 620 /* 621 * If the SCI is remapped to a non-ISA global interrupt, 622 * then override the vector we use to setup and allocate 623 * the interrupt. 624 */ 625 if (intr->Interrupt > 15 && 626 intr->Source == AcpiGbl_FADT->SciInt) 627 acpi_OverrideInterruptLevel(intr->Interrupt); 628 else 629 ioapic_remap_vector(new_ioapic, new_pin, intr->Source); 630 if (madt_find_interrupt(intr->Source, &old_ioapic, 631 &old_pin) != 0) 632 printf("MADT: Could not find APIC for source IRQ %d\n", 633 intr->Source); 634 else if (ioapic_get_vector(old_ioapic, old_pin) == 635 intr->Source) 636 ioapic_disable_pin(old_ioapic, old_pin); 637 } 638 639 /* Program the polarity and trigger mode. */ 640 ioapic_set_triggermode(new_ioapic, new_pin, trig); 641 ioapic_set_polarity(new_ioapic, new_pin, pol); 642} 643 644/* 645 * Parse an entry for an NMI routed to an IO APIC. 646 */ 647static void 648madt_parse_nmi(MADT_NMI_SOURCE *nmi) 649{ 650 void *ioapic; 651 u_int pin; 652 653 if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) { 654 printf("MADT: Could not find APIC for vector %d\n", 655 nmi->Interrupt); 656 return; 657 } 658 659 ioapic_set_nmi(ioapic, pin); 660 if (nmi->TriggerMode != TRIGGER_CONFORMS) 661 ioapic_set_triggermode(ioapic, pin, 662 interrupt_trigger(nmi->TriggerMode, 0)); 663 if (nmi->Polarity != TRIGGER_CONFORMS) 664 ioapic_set_polarity(ioapic, pin, 665 interrupt_polarity(nmi->Polarity, 0)); 666} 667 668/* 669 * Parse an entry for an NMI routed to a local APIC LVT pin. 670 */ 671static void 672madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi) 673{ 674 u_int apic_id, pin; 675 676 if (nmi->ProcessorId == 0xff) 677 apic_id = APIC_ID_ALL; 678 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 679 if (bootverbose) 680 printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", 681 nmi->ProcessorId); 682 return; 683 } 684 if (nmi->Lint == 0) 685 pin = LVT_LINT0; 686 else 687 pin = LVT_LINT1; 688 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 689 if (nmi->TriggerMode != TRIGGER_CONFORMS) 690 lapic_set_lvt_triggermode(apic_id, pin, 691 interrupt_trigger(nmi->TriggerMode, 0)); 692 if (nmi->Polarity != POLARITY_CONFORMS) 693 lapic_set_lvt_polarity(apic_id, pin, 694 interrupt_polarity(nmi->Polarity, 0)); 695} 696 697/* 698 * Parse interrupt entries. 699 */ 700static void 701madt_parse_ints(APIC_HEADER *entry, void *arg __unused) 702{ 703 704 switch (entry->Type) { 705 case APIC_XRUPT_OVERRIDE: 706 madt_parse_interrupt_override( 707 (MADT_INTERRUPT_OVERRIDE *)entry); 708 break; 709 case APIC_NMI: 710 madt_parse_nmi((MADT_NMI_SOURCE *)entry); 711 break; 712 case APIC_LOCAL_NMI: 713 madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry); 714 break; 715 } 716} 717 718/* 719 * Setup per-CPU ACPI IDs. 720 */ 721static void 722madt_set_ids(void *dummy) 723{ 724 struct pcpu *pc; 725 u_int i, j; 726 727 if (madt == NULL) 728 return; 729 for (i = 0; i <= mp_maxid; i++) { 730 if (CPU_ABSENT(i)) 731 continue; 732 pc = pcpu_find(i); 733 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i)); 734 for (j = 0; j < NLAPICS + 1; j++) { 735 if (!lapics[j].la_present || !lapics[j].la_enabled) 736 continue; 737 if (lapics[j].la_apic_id == pc->pc_apic_id) { 738 pc->pc_acpi_id = j; 739 if (bootverbose) 740 printf("APIC: CPU %u has ACPI ID %u\n", 741 i, j); 742 break; 743 } 744 } 745 if (j == NLAPICS + 1) 746 panic("Unable to find ACPI ID for CPU %d", i); 747 } 748} 749SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 750