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