madt.c revision 128329
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 128329 2004-04-16 19:46:30Z 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 force_sci_lo; 73TUNABLE_INT("hw.acpi.force_sci_lo", &force_sci_lo); 74static MULTIPLE_APIC_TABLE *madt; 75static vm_paddr_t madt_physaddr; 76static vm_offset_t madt_length; 77 78MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items"); 79 80static u_char interrupt_polarity(UINT16 Polarity); 81static u_char interrupt_trigger(UINT16 TriggerMode); 82static int madt_find_cpu(u_int acpi_id, u_int *apic_id); 83static int madt_find_interrupt(int intr, void **apic, u_int *pin); 84static void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); 85static void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); 86static void madt_parse_apics(APIC_HEADER *entry, void *arg); 87static void madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr); 88static void madt_parse_ints(APIC_HEADER *entry, void *arg __unused); 89static void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi); 90static void madt_parse_nmi(MADT_NMI_SOURCE *nmi); 91static int madt_probe(void); 92static int madt_probe_cpus(void); 93static void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused); 94static int madt_probe_table(vm_paddr_t address); 95static void madt_register(void *dummy); 96static int madt_setup_local(void); 97static int madt_setup_io(void); 98static void madt_unmap(void *data, vm_offset_t length); 99static void madt_unmap_table(void *table); 100static void madt_walk_table(madt_entry_handler *handler, void *arg); 101 102static struct apic_enumerator madt_enumerator = { 103 "MADT", 104 madt_probe, 105 madt_probe_cpus, 106 madt_setup_local, 107 madt_setup_io 108}; 109 110/* 111 * Code to abuse the crashdump map to map in the tables for the early 112 * probe. We cheat and make the following assumptions about how we 113 * use this KVA: page 0 is used to map in the first page of each table 114 * found via the RSDT or XSDT and pages 1 to n are used to map in the 115 * RSDT or XSDT. The offset is in pages; the length is in bytes. 116 */ 117static void * 118madt_map(vm_paddr_t pa, int offset, vm_offset_t length) 119{ 120 vm_offset_t va, off; 121 void *data; 122 123 off = pa & PAGE_MASK; 124 length = roundup(length + off, PAGE_SIZE); 125 pa = pa & PG_FRAME; 126 va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 127 (offset * PAGE_SIZE); 128 data = (void *)(va + off); 129 length -= PAGE_SIZE; 130 while (length > 0) { 131 va += PAGE_SIZE; 132 pa += PAGE_SIZE; 133 length -= PAGE_SIZE; 134 pmap_kenter(va, pa); 135 invlpg(va); 136 } 137 return (data); 138} 139 140static void 141madt_unmap(void *data, vm_offset_t length) 142{ 143 vm_offset_t va, off; 144 145 va = (vm_offset_t)data; 146 off = va & PAGE_MASK; 147 length = roundup(length + off, PAGE_SIZE); 148 va &= ~PAGE_MASK; 149 while (length > 0) { 150 pmap_kremove(va); 151 invlpg(va); 152 va += PAGE_SIZE; 153 length -= PAGE_SIZE; 154 } 155} 156 157static void * 158madt_map_table(vm_paddr_t pa, int offset, const char *sig) 159{ 160 ACPI_TABLE_HEADER *header; 161 vm_offset_t length; 162 163 header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 164 if (strncmp(header->Signature, sig, 4) != 0) { 165 madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 166 return (NULL); 167 } 168 length = header->Length; 169 madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 170 return (madt_map(pa, offset, length)); 171} 172 173static void 174madt_unmap_table(void *table) 175{ 176 ACPI_TABLE_HEADER *header; 177 178 header = (ACPI_TABLE_HEADER *)table; 179 madt_unmap(table, header->Length); 180} 181 182/* 183 * Look for an ACPI Multiple APIC Description Table ("APIC") 184 */ 185static int 186madt_probe(void) 187{ 188 ACPI_POINTER rsdp_ptr; 189 RSDP_DESCRIPTOR *rsdp; 190 RSDT_DESCRIPTOR *rsdt; 191 XSDT_DESCRIPTOR *xsdt; 192 int i, count; 193 194 if (resource_disabled("acpi", 0)) 195 return (ENXIO); 196 197 /* 198 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 199 * calls pmap_mapdev() to find the RSDP, we assume that we can use 200 * pmap_mapdev() to map the RSDP. 201 */ 202 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 203 return (ENXIO); 204#ifdef __i386__ 205 KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high")); 206#endif 207 rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR)); 208 if (rsdp == NULL) { 209 if (bootverbose) 210 printf("MADT: Failed to map RSDP\n"); 211 return (ENXIO); 212 } 213 214 /* 215 * For ACPI < 2.0, use the RSDT. For ACPI >= 2.0, use the XSDT. 216 * We map the XSDT and RSDT at page 1 in the crashdump area. 217 * Page 0 is used to map in the headers of candidate ACPI tables. 218 */ 219 if (rsdp->Revision >= 2) { 220 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG); 221 if (xsdt == NULL) { 222 if (bootverbose) 223 printf("MADT: Failed to map XSDT\n"); 224 return (ENXIO); 225 } 226 count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 227 sizeof(UINT64); 228 for (i = 0; i < count; i++) 229 if (madt_probe_table(xsdt->TableOffsetEntry[i])) 230 break; 231 madt_unmap_table(xsdt); 232 } else { 233 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG); 234 if (rsdt == NULL) { 235 if (bootverbose) 236 printf("MADT: Failed to map RSDT\n"); 237 return (ENXIO); 238 } 239 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 240 sizeof(UINT32); 241 for (i = 0; i < count; i++) 242 if (madt_probe_table(rsdt->TableOffsetEntry[i])) 243 break; 244 madt_unmap_table(rsdt); 245 } 246 pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR)); 247 if (madt_physaddr == 0) { 248 if (bootverbose) 249 printf("MADT: No MADT table found\n"); 250 return (ENXIO); 251 } 252 if (bootverbose) 253 printf("MADT: Found table at 0x%jx\n", 254 (uintmax_t)madt_physaddr); 255 256 return (0); 257} 258 259/* 260 * See if a given ACPI table is the MADT. 261 */ 262static int 263madt_probe_table(vm_paddr_t address) 264{ 265 ACPI_TABLE_HEADER *table; 266 267 table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 268 if (table == NULL) { 269 if (bootverbose) 270 printf("MADT: Failed to map table at 0x%jx\n", 271 (uintmax_t)address); 272 return (0); 273 } 274 if (bootverbose) 275 printf("Table '%.4s' at 0x%jx\n", table->Signature, 276 (uintmax_t)address); 277 278 /* XXX: Verify checksum? */ 279 if (strncmp(table->Signature, APIC_SIG, 4) != 0) { 280 madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 281 return (0); 282 } 283 madt_physaddr = address; 284 madt_length = table->Length; 285 madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 286 return (1); 287} 288 289/* 290 * Run through the MP table enumerating CPUs. 291 */ 292static int 293madt_probe_cpus(void) 294{ 295 296 madt = madt_map_table(madt_physaddr, 0, APIC_SIG); 297 KASSERT(madt != NULL, ("Unable to re-map MADT")); 298 madt_walk_table(madt_probe_cpus_handler, NULL); 299 madt_unmap_table(madt); 300 madt = NULL; 301 return (0); 302} 303 304/* 305 * Initialize the local APIC on the BSP. 306 */ 307static int 308madt_setup_local(void) 309{ 310 311 madt = pmap_mapdev(madt_physaddr, madt_length); 312 lapic_init((uintptr_t)madt->LocalApicAddress); 313 printf("ACPI APIC Table: <%.*s %.*s>\n", 314 (int)sizeof(madt->OemId), madt->OemId, 315 (int)sizeof(madt->OemTableId), madt->OemTableId); 316 317 /* 318 * We ignore 64-bit local APIC override entries. Should we 319 * perhaps emit a warning here if we find one? 320 */ 321 return (0); 322} 323 324/* 325 * Enumerate I/O APICs and setup interrupt sources. 326 */ 327static int 328madt_setup_io(void) 329{ 330 int i; 331 332 /* Try to initialize ACPI so that we can access the FADT. */ 333 i = acpi_Startup(); 334 if (ACPI_FAILURE(i)) { 335 printf("MADT: ACPI Startup failed with %s\n", 336 AcpiFormatException(i)); 337 printf("Try disabling either ACPI or apic support.\n"); 338 panic("Using MADT but ACPI doesn't work"); 339 } 340 341 /* First, we run through adding I/O APIC's. */ 342 madt_walk_table(madt_parse_apics, NULL); 343 344 /* Second, we run through the table tweaking interrupt sources. */ 345 madt_walk_table(madt_parse_ints, NULL); 346 347 /* Third, we register all the I/O APIC's. */ 348 for (i = 0; i < NIOAPICS; i++) 349 if (ioapics[i].io_apic != NULL) 350 ioapic_register(ioapics[i].io_apic); 351 352 /* Finally, we throw the switch to enable the I/O APIC's. */ 353 acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 354 355 return (0); 356} 357 358static void 359madt_register(void *dummy __unused) 360{ 361 362 apic_register_enumerator(&madt_enumerator); 363} 364SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL) 365 366/* 367 * Call the handler routine for each entry in the MADT table. 368 */ 369static void 370madt_walk_table(madt_entry_handler *handler, void *arg) 371{ 372 APIC_HEADER *entry; 373 u_char *p, *end; 374 375 end = (u_char *)(madt) + madt->Length; 376 for (p = (u_char *)(madt + 1); p < end; ) { 377 entry = (APIC_HEADER *)p; 378 handler(entry, arg); 379 p += entry->Length; 380 } 381} 382 383static void 384madt_probe_cpus_handler(APIC_HEADER *entry, void *arg) 385{ 386 MADT_PROCESSOR_APIC *proc; 387 struct lapic_info *la; 388 389 switch (entry->Type) { 390 case APIC_PROCESSOR: 391 /* 392 * The MADT does not include a BSP flag, so we have to 393 * let the MP code figure out which CPU is the BSP on 394 * its own. 395 */ 396 proc = (MADT_PROCESSOR_APIC *)entry; 397 if (bootverbose) 398 printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", 399 proc->LocalApicId, proc->ProcessorId, 400 proc->ProcessorEnabled ? "enabled" : "disabled"); 401 if (proc->ProcessorId > NLAPICS) 402 panic("%s: CPU ID %d too high", __func__, 403 proc->ProcessorId); 404 la = &lapics[proc->ProcessorId]; 405 KASSERT(la->la_present == 0, 406 ("Duplicate local ACPI ID %d", proc->ProcessorId)); 407 la->la_present = 1; 408 la->la_apic_id = proc->LocalApicId; 409 if (proc->ProcessorEnabled) { 410 la->la_enabled = 1; 411 lapic_create(proc->LocalApicId, 0); 412 } 413 break; 414 } 415} 416 417 418/* 419 * Add an I/O APIC from an entry in the table. 420 */ 421static void 422madt_parse_apics(APIC_HEADER *entry, void *arg __unused) 423{ 424 MADT_IO_APIC *apic; 425 426 switch (entry->Type) { 427 case APIC_IO: 428 apic = (MADT_IO_APIC *)entry; 429 if (bootverbose) 430 printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n", 431 apic->IoApicId, apic->Interrupt, 432 (void *)(uintptr_t)apic->Address); 433 if (apic->IoApicId >= NIOAPICS) 434 panic("%s: I/O APIC ID %d too high", __func__, 435 apic->IoApicId); 436 if (ioapics[apic->IoApicId].io_apic != NULL) 437 panic("%s: Double APIC ID %d", __func__, 438 apic->IoApicId); 439 ioapics[apic->IoApicId].io_apic = ioapic_create( 440 (uintptr_t)apic->Address, apic->IoApicId, 441 apic->Interrupt); 442 ioapics[apic->IoApicId].io_vector = apic->Interrupt; 443 break; 444 default: 445 break; 446 } 447} 448 449/* 450 * Determine properties of an interrupt source. Note that for ACPI, 451 * these are only used for ISA interrupts, so we assume ISA bus values 452 * (Active Hi, Edge Triggered) for conforming values. 453 */ 454static u_char 455interrupt_polarity(UINT16 Polarity) 456{ 457 458 switch (Polarity) { 459 case POLARITY_CONFORMS: 460 case POLARITY_ACTIVE_HIGH: 461 return (1); 462 case POLARITY_ACTIVE_LOW: 463 return (0); 464 default: 465 panic("Bogus Interrupt Polarity"); 466 } 467} 468 469static u_char 470interrupt_trigger(UINT16 TriggerMode) 471{ 472 473 switch (TriggerMode) { 474 case TRIGGER_CONFORMS: 475 case TRIGGER_EDGE: 476 return (1); 477 case TRIGGER_LEVEL: 478 return (0); 479 default: 480 panic("Bogus Interrupt Trigger Mode"); 481 } 482} 483 484/* 485 * Find the local APIC ID associated with a given ACPI Processor ID. 486 */ 487static int 488madt_find_cpu(u_int acpi_id, u_int *apic_id) 489{ 490 491 if (!lapics[acpi_id].la_present) 492 return (ENOENT); 493 *apic_id = lapics[acpi_id].la_apic_id; 494 if (lapics[acpi_id].la_enabled) 495 return (0); 496 else 497 return (ENXIO); 498} 499 500/* 501 * Find the IO APIC and pin on that APIC associated with a given global 502 * interrupt. 503 */ 504static int 505madt_find_interrupt(int intr, void **apic, u_int *pin) 506{ 507 int i, best; 508 509 best = -1; 510 for (i = 0; i < NIOAPICS; i++) { 511 if (ioapics[i].io_apic == NULL || 512 ioapics[i].io_vector > intr) 513 continue; 514 if (best == -1 || 515 ioapics[best].io_vector < ioapics[i].io_vector) 516 best = i; 517 } 518 if (best == -1) 519 return (ENOENT); 520 *apic = ioapics[best].io_apic; 521 *pin = intr - ioapics[best].io_vector; 522 if (*pin > 32) 523 printf("WARNING: Found intpin of %u for vector %d\n", *pin, 524 intr); 525 return (0); 526} 527 528/* 529 * Parse an interrupt source override for an ISA interrupt. 530 */ 531static void 532madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr) 533{ 534 void *new_ioapic, *old_ioapic; 535 u_int new_pin, old_pin; 536 int force_lo; 537 538 if (bootverbose) 539 printf("MADT: intr override: source %u, irq %u\n", 540 intr->Source, intr->Interrupt); 541 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 542 if (madt_find_interrupt(intr->Interrupt, &new_ioapic, 543 &new_pin) != 0) { 544 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n", 545 intr->Interrupt, intr->Source); 546 return; 547 } 548 549 /* 550 * If the SCI is identity mapped but has edge trigger and 551 * active-hi polarity or the force_sci_lo tunable is set, 552 * force it to use level/lo. 553 */ 554 force_lo = 0; 555 if (intr->Source == AcpiGbl_FADT->SciInt) 556 if (force_sci_lo || (intr->Interrupt == intr->Source && 557 intr->TriggerMode == TRIGGER_EDGE && 558 intr->Polarity == POLARITY_ACTIVE_HIGH)) 559 force_lo = 1; 560 561 if (intr->Source != intr->Interrupt) { 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->Interrupt > 15 && 568 intr->Source == AcpiGbl_FADT->SciInt) 569 acpi_OverrideInterruptLevel(intr->Interrupt); 570 else 571 ioapic_remap_vector(new_ioapic, new_pin, intr->Source); 572 if (madt_find_interrupt(intr->Source, &old_ioapic, 573 &old_pin) != 0) 574 printf("MADT: Could not find APIC for source IRQ %d\n", 575 intr->Source); 576 else if (ioapic_get_vector(old_ioapic, old_pin) == 577 intr->Source) 578 ioapic_disable_pin(old_ioapic, old_pin); 579 } 580 if (force_lo) { 581 printf( 582 "MADT: Forcing active-lo polarity and level trigger for IRQ %d\n", 583 intr->Source); 584 ioapic_set_polarity(new_ioapic, new_pin, 0); 585 ioapic_set_triggermode(new_ioapic, new_pin, 0); 586 } else { 587 ioapic_set_polarity(new_ioapic, new_pin, 588 interrupt_polarity(intr->Polarity)); 589 ioapic_set_triggermode(new_ioapic, new_pin, 590 interrupt_trigger(intr->TriggerMode)); 591 } 592} 593 594/* 595 * Parse an entry for an NMI routed to an IO APIC. 596 */ 597static void 598madt_parse_nmi(MADT_NMI_SOURCE *nmi) 599{ 600 void *ioapic; 601 u_int pin; 602 603 if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) { 604 printf("MADT: Could not find APIC for vector %d\n", 605 nmi->Interrupt); 606 return; 607 } 608 609 ioapic_set_nmi(ioapic, pin); 610 if (nmi->TriggerMode != TRIGGER_CONFORMS) 611 ioapic_set_triggermode(ioapic, pin, 612 interrupt_trigger(nmi->TriggerMode)); 613 if (nmi->Polarity != TRIGGER_CONFORMS) 614 ioapic_set_polarity(ioapic, pin, 615 interrupt_polarity(nmi->Polarity)); 616} 617 618/* 619 * Parse an entry for an NMI routed to a local APIC LVT pin. 620 */ 621static void 622madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi) 623{ 624 u_int apic_id, pin; 625 626 if (nmi->ProcessorId == 0xff) 627 apic_id = APIC_ID_ALL; 628 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 629 if (bootverbose) 630 printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", 631 nmi->ProcessorId); 632 return; 633 } 634 if (nmi->Lint == 0) 635 pin = LVT_LINT0; 636 else 637 pin = LVT_LINT1; 638 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 639 if (nmi->TriggerMode != TRIGGER_CONFORMS) 640 lapic_set_lvt_triggermode(apic_id, pin, 641 interrupt_trigger(nmi->TriggerMode)); 642 if (nmi->Polarity != POLARITY_CONFORMS) 643 lapic_set_lvt_polarity(apic_id, pin, 644 interrupt_polarity(nmi->Polarity)); 645} 646 647/* 648 * Parse interrupt entries. 649 */ 650static void 651madt_parse_ints(APIC_HEADER *entry, void *arg __unused) 652{ 653 654 switch (entry->Type) { 655 case APIC_XRUPT_OVERRIDE: 656 madt_parse_interrupt_override( 657 (MADT_INTERRUPT_OVERRIDE *)entry); 658 break; 659 case APIC_NMI: 660 madt_parse_nmi((MADT_NMI_SOURCE *)entry); 661 break; 662 case APIC_LOCAL_NMI: 663 madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry); 664 break; 665 } 666} 667 668/* 669 * Setup per-CPU ACPI IDs. 670 */ 671static void 672madt_set_ids(void *dummy) 673{ 674 struct pcpu *pc; 675 u_int i, j; 676 677 if (madt == NULL) 678 return; 679 for (i = 0; i <= mp_maxid; i++) { 680 if (CPU_ABSENT(i)) 681 continue; 682 pc = pcpu_find(i); 683 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i)); 684 for (j = 0; j < NLAPICS + 1; j++) { 685 if (!lapics[j].la_present || !lapics[j].la_enabled) 686 continue; 687 if (lapics[j].la_apic_id == pc->pc_apic_id) { 688 pc->pc_acpi_id = j; 689 if (bootverbose) 690 printf("APIC: CPU %u has ACPI ID %u\n", 691 i, j); 692 break; 693 } 694 } 695 if (j == NLAPICS + 1) 696 panic("Unable to find ACPI ID for CPU %d", i); 697 } 698} 699SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 700