madt.c revision 209059
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 209059 2010-06-11 18:46:34Z 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#include <vm/vm.h> 40#include <vm/pmap.h> 41 42#include <machine/apicreg.h> 43#include <machine/intr_machdep.h> 44#include <machine/apicvar.h> 45 46#include <contrib/dev/acpica/include/acpi.h> 47#include <contrib/dev/acpica/include/actables.h> 48 49#include <dev/acpica/acpivar.h> 50#include <dev/pci/pcivar.h> 51 52/* These two arrays are indexed by APIC IDs. */ 53struct ioapic_info { 54 void *io_apic; 55 UINT32 io_vector; 56} ioapics[MAX_APIC_ID + 1]; 57 58struct lapic_info { 59 u_int la_enabled:1; 60 u_int la_acpi_id:8; 61} lapics[MAX_APIC_ID + 1]; 62 63static int madt_found_sci_override; 64static ACPI_TABLE_MADT *madt; 65static vm_paddr_t madt_physaddr; 66static vm_offset_t madt_length; 67 68MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 69 70static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 71static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 72static int madt_find_cpu(u_int acpi_id, u_int *apic_id); 73static int madt_find_interrupt(int intr, void **apic, u_int *pin); 74static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 75static void madt_parse_interrupt_override( 76 ACPI_MADT_INTERRUPT_OVERRIDE *intr); 77static void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 78 void *arg __unused); 79static void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 80static void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 81static int madt_probe(void); 82static int madt_probe_cpus(void); 83static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 84 void *arg __unused); 85static void madt_register(void *dummy); 86static int madt_setup_local(void); 87static int madt_setup_io(void); 88static void madt_walk_table(acpi_subtable_handler *handler, void *arg); 89 90static struct apic_enumerator madt_enumerator = { 91 "MADT", 92 madt_probe, 93 madt_probe_cpus, 94 madt_setup_local, 95 madt_setup_io 96}; 97 98 99/* 100 * Look for an ACPI Multiple APIC Description Table ("APIC") 101 */ 102static int 103madt_probe(void) 104{ 105 106 madt_physaddr = acpi_find_table(ACPI_SIG_MADT); 107 if (madt_physaddr == 0) 108 return (ENXIO); 109 return (0); 110} 111 112/* 113 * Run through the MP table enumerating CPUs. 114 */ 115static int 116madt_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 */ 131static int 132madt_setup_local(void) 133{ 134 135 madt = pmap_mapbios(madt_physaddr, madt_length); 136 lapic_init(madt->Address); 137 printf("ACPI APIC Table: <%.*s %.*s>\n", 138 (int)sizeof(madt->Header.OemId), madt->Header.OemId, 139 (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 140 141 /* 142 * We ignore 64-bit local APIC override entries. Should we 143 * perhaps emit a warning here if we find one? 144 */ 145 return (0); 146} 147 148/* 149 * Enumerate I/O APICs and setup interrupt sources. 150 */ 151static int 152madt_setup_io(void) 153{ 154 void *ioapic; 155 u_int pin; 156 int i; 157 158 /* Try to initialize ACPI so that we can access the FADT. */ 159 i = acpi_Startup(); 160 if (ACPI_FAILURE(i)) { 161 printf("MADT: ACPI Startup failed with %s\n", 162 AcpiFormatException(i)); 163 printf("Try disabling either ACPI or apic support.\n"); 164 panic("Using MADT but ACPI doesn't work"); 165 } 166 167 /* First, we run through adding I/O APIC's. */ 168 madt_walk_table(madt_parse_apics, NULL); 169 170 /* Second, we run through the table tweaking interrupt sources. */ 171 madt_walk_table(madt_parse_ints, NULL); 172 173 /* 174 * If there was not an explicit override entry for the SCI, 175 * force it to use level trigger and active-low polarity. 176 */ 177 if (!madt_found_sci_override) { 178 if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 179 &pin) != 0) 180 printf("MADT: Could not find APIC for SCI IRQ %u\n", 181 AcpiGbl_FADT.SciInterrupt); 182 else { 183 printf( 184 "MADT: Forcing active-low polarity and level trigger for SCI\n"); 185 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 186 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 187 } 188 } 189 190 /* Third, we register all the I/O APIC's. */ 191 for (i = 0; i <= MAX_APIC_ID; i++) 192 if (ioapics[i].io_apic != NULL) 193 ioapic_register(ioapics[i].io_apic); 194 195 /* Finally, we throw the switch to enable the I/O APIC's. */ 196 acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 197 198 return (0); 199} 200 201static void 202madt_register(void *dummy __unused) 203{ 204 205 apic_register_enumerator(&madt_enumerator); 206} 207SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_SECOND, madt_register, NULL); 208 209/* 210 * Call the handler routine for each entry in the MADT table. 211 */ 212static void 213madt_walk_table(acpi_subtable_handler *handler, void *arg) 214{ 215 216 acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 217 handler, arg); 218} 219 220static void 221madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 222{ 223 ACPI_MADT_LOCAL_APIC *proc; 224 struct lapic_info *la; 225 226 switch (entry->Type) { 227 case ACPI_MADT_TYPE_LOCAL_APIC: 228 /* 229 * The MADT does not include a BSP flag, so we have to 230 * let the MP code figure out which CPU is the BSP on 231 * its own. 232 */ 233 proc = (ACPI_MADT_LOCAL_APIC *)entry; 234 if (bootverbose) 235 printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 236 proc->Id, proc->ProcessorId, 237 (proc->LapicFlags & ACPI_MADT_ENABLED) ? 238 "enabled" : "disabled"); 239 if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 240 break; 241 if (proc->Id > MAX_APIC_ID) 242 panic("%s: CPU ID %u too high", __func__, proc->Id); 243 la = &lapics[proc->Id]; 244 KASSERT(la->la_enabled == 0, 245 ("Duplicate local APIC ID %u", proc->Id)); 246 la->la_enabled = 1; 247 la->la_acpi_id = proc->ProcessorId; 248 lapic_create(proc->Id, 0); 249 break; 250 } 251} 252 253 254/* 255 * Add an I/O APIC from an entry in the table. 256 */ 257static void 258madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 259{ 260 ACPI_MADT_IO_APIC *apic; 261 262 switch (entry->Type) { 263 case ACPI_MADT_TYPE_IO_APIC: 264 apic = (ACPI_MADT_IO_APIC *)entry; 265 if (bootverbose) 266 printf( 267 "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 268 apic->Id, apic->GlobalIrqBase, 269 (void *)(uintptr_t)apic->Address); 270 if (apic->Id > MAX_APIC_ID) 271 panic("%s: I/O APIC ID %u too high", __func__, 272 apic->Id); 273 if (ioapics[apic->Id].io_apic != NULL) 274 panic("%s: Double APIC ID %u", __func__, apic->Id); 275 if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 276 printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 277 break; 278 } 279 ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 280 apic->Id, apic->GlobalIrqBase); 281 ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 282 break; 283 default: 284 break; 285 } 286} 287 288/* 289 * Determine properties of an interrupt source. Note that for ACPI these 290 * functions are only used for ISA interrupts, so we assume ISA bus values 291 * (Active Hi, Edge Triggered) for conforming values except for the ACPI 292 * SCI for which we use Active Lo, Level Triggered. 293 */ 294static enum intr_polarity 295interrupt_polarity(UINT16 IntiFlags, UINT8 Source) 296{ 297 298 switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 299 case ACPI_MADT_POLARITY_CONFORMS: 300 if (Source == AcpiGbl_FADT.SciInterrupt) 301 return (INTR_POLARITY_LOW); 302 else 303 return (INTR_POLARITY_HIGH); 304 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 305 return (INTR_POLARITY_HIGH); 306 case ACPI_MADT_POLARITY_ACTIVE_LOW: 307 return (INTR_POLARITY_LOW); 308 default: 309 panic("Bogus Interrupt Polarity"); 310 } 311} 312 313static enum intr_trigger 314interrupt_trigger(UINT16 IntiFlags, UINT8 Source) 315{ 316 317 switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 318 case ACPI_MADT_TRIGGER_CONFORMS: 319 if (Source == AcpiGbl_FADT.SciInterrupt) 320 return (INTR_TRIGGER_LEVEL); 321 else 322 return (INTR_TRIGGER_EDGE); 323 case ACPI_MADT_TRIGGER_EDGE: 324 return (INTR_TRIGGER_EDGE); 325 case ACPI_MADT_TRIGGER_LEVEL: 326 return (INTR_TRIGGER_LEVEL); 327 default: 328 panic("Bogus Interrupt Trigger Mode"); 329 } 330} 331 332/* 333 * Find the local APIC ID associated with a given ACPI Processor ID. 334 */ 335static int 336madt_find_cpu(u_int acpi_id, u_int *apic_id) 337{ 338 int i; 339 340 for (i = 0; i <= MAX_APIC_ID; i++) { 341 if (!lapics[i].la_enabled) 342 continue; 343 if (lapics[i].la_acpi_id != acpi_id) 344 continue; 345 *apic_id = i; 346 return (0); 347 } 348 return (ENOENT); 349} 350 351/* 352 * Find the IO APIC and pin on that APIC associated with a given global 353 * interrupt. 354 */ 355static int 356madt_find_interrupt(int intr, void **apic, u_int *pin) 357{ 358 int i, best; 359 360 best = -1; 361 for (i = 0; i <= MAX_APIC_ID; i++) { 362 if (ioapics[i].io_apic == NULL || 363 ioapics[i].io_vector > intr) 364 continue; 365 if (best == -1 || 366 ioapics[best].io_vector < ioapics[i].io_vector) 367 best = i; 368 } 369 if (best == -1) 370 return (ENOENT); 371 *apic = ioapics[best].io_apic; 372 *pin = intr - ioapics[best].io_vector; 373 if (*pin > 32) 374 printf("WARNING: Found intpin of %u for vector %d\n", *pin, 375 intr); 376 return (0); 377} 378 379/* 380 * Parse an interrupt source override for an ISA interrupt. 381 */ 382static void 383madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 384{ 385 void *new_ioapic, *old_ioapic; 386 u_int new_pin, old_pin; 387 enum intr_trigger trig; 388 enum intr_polarity pol; 389 char buf[64]; 390 391 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 392 intr->GlobalIrq == 2) { 393 if (bootverbose) 394 printf("MADT: Skipping timer override\n"); 395 return; 396 } 397 if (bootverbose) 398 printf("MADT: Interrupt override: source %u, irq %u\n", 399 intr->SourceIrq, intr->GlobalIrq); 400 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 401 if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 402 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 403 intr->GlobalIrq, intr->SourceIrq); 404 return; 405 } 406 407 /* 408 * Lookup the appropriate trigger and polarity modes for this 409 * entry. 410 */ 411 trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 412 pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 413 414 /* 415 * If the SCI is identity mapped but has edge trigger and 416 * active-hi polarity or the force_sci_lo tunable is set, 417 * force it to use level/lo. 418 */ 419 if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 420 madt_found_sci_override = 1; 421 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 422 if (tolower(buf[0]) == 'e') 423 trig = INTR_TRIGGER_EDGE; 424 else if (tolower(buf[0]) == 'l') 425 trig = INTR_TRIGGER_LEVEL; 426 else 427 panic( 428 "Invalid trigger %s: must be 'edge' or 'level'", 429 buf); 430 printf("MADT: Forcing SCI to %s trigger\n", 431 trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 432 } 433 if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 434 if (tolower(buf[0]) == 'h') 435 pol = INTR_POLARITY_HIGH; 436 else if (tolower(buf[0]) == 'l') 437 pol = INTR_POLARITY_LOW; 438 else 439 panic( 440 "Invalid polarity %s: must be 'high' or 'low'", 441 buf); 442 printf("MADT: Forcing SCI to active %s polarity\n", 443 pol == INTR_POLARITY_HIGH ? "high" : "low"); 444 } 445 } 446 447 /* Remap the IRQ if it is mapped to a different interrupt vector. */ 448 if (intr->SourceIrq != intr->GlobalIrq) { 449 /* 450 * If the SCI is remapped to a non-ISA global interrupt, 451 * then override the vector we use to setup and allocate 452 * the interrupt. 453 */ 454 if (intr->GlobalIrq > 15 && 455 intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 456 acpi_OverrideInterruptLevel(intr->GlobalIrq); 457 else 458 ioapic_remap_vector(new_ioapic, new_pin, 459 intr->SourceIrq); 460 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 461 &old_pin) != 0) 462 printf("MADT: Could not find APIC for source IRQ %u\n", 463 intr->SourceIrq); 464 else if (ioapic_get_vector(old_ioapic, old_pin) == 465 intr->SourceIrq) 466 ioapic_disable_pin(old_ioapic, old_pin); 467 } 468 469 /* Program the polarity and trigger mode. */ 470 ioapic_set_triggermode(new_ioapic, new_pin, trig); 471 ioapic_set_polarity(new_ioapic, new_pin, pol); 472} 473 474/* 475 * Parse an entry for an NMI routed to an IO APIC. 476 */ 477static void 478madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 479{ 480 void *ioapic; 481 u_int pin; 482 483 if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 484 printf("MADT: Could not find APIC for vector %u\n", 485 nmi->GlobalIrq); 486 return; 487 } 488 489 ioapic_set_nmi(ioapic, pin); 490 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 491 ioapic_set_triggermode(ioapic, pin, 492 interrupt_trigger(nmi->IntiFlags, 0)); 493 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 494 ioapic_set_polarity(ioapic, pin, 495 interrupt_polarity(nmi->IntiFlags, 0)); 496} 497 498/* 499 * Parse an entry for an NMI routed to a local APIC LVT pin. 500 */ 501static void 502madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 503{ 504 u_int apic_id, pin; 505 506 if (nmi->ProcessorId == 0xff) 507 apic_id = APIC_ID_ALL; 508 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 509 if (bootverbose) 510 printf("MADT: Ignoring local NMI routed to " 511 "ACPI CPU %u\n", nmi->ProcessorId); 512 return; 513 } 514 if (nmi->Lint == 0) 515 pin = LVT_LINT0; 516 else 517 pin = LVT_LINT1; 518 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 519 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 520 lapic_set_lvt_triggermode(apic_id, pin, 521 interrupt_trigger(nmi->IntiFlags, 0)); 522 if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 523 lapic_set_lvt_polarity(apic_id, pin, 524 interrupt_polarity(nmi->IntiFlags, 0)); 525} 526 527/* 528 * Parse interrupt entries. 529 */ 530static void 531madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 532{ 533 534 switch (entry->Type) { 535 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 536 madt_parse_interrupt_override( 537 (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 538 break; 539 case ACPI_MADT_TYPE_NMI_SOURCE: 540 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 541 break; 542 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 543 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 544 break; 545 } 546} 547 548/* 549 * Setup per-CPU ACPI IDs. 550 */ 551static void 552madt_set_ids(void *dummy) 553{ 554 struct lapic_info *la; 555 struct pcpu *pc; 556 u_int i; 557 558 if (madt == NULL) 559 return; 560 CPU_FOREACH(i) { 561 pc = pcpu_find(i); 562 KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 563 la = &lapics[pc->pc_apic_id]; 564 if (!la->la_enabled) 565 panic("APIC: CPU with APIC ID %u is not enabled", 566 pc->pc_apic_id); 567 pc->pc_acpi_id = la->la_acpi_id; 568 if (bootverbose) 569 printf("APIC: CPU %u has ACPI ID %u\n", i, 570 la->la_acpi_id); 571 } 572} 573SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL); 574