madt.c revision 278473
1121992Sjhb/*- 2121992Sjhb * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> 3121992Sjhb * All rights reserved. 4121992Sjhb * 5121992Sjhb * Redistribution and use in source and binary forms, with or without 6121992Sjhb * modification, are permitted provided that the following conditions 7121992Sjhb * are met: 8121992Sjhb * 1. Redistributions of source code must retain the above copyright 9121992Sjhb * notice, this list of conditions and the following disclaimer. 10121992Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11121992Sjhb * notice, this list of conditions and the following disclaimer in the 12121992Sjhb * documentation and/or other materials provided with the distribution. 13121992Sjhb * 14121992Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15121992Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16121992Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17121992Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18121992Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19121992Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20121992Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21121992Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22121992Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23121992Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24121992Sjhb * SUCH DAMAGE. 25121992Sjhb */ 26121992Sjhb 27121992Sjhb#include <sys/cdefs.h> 28121992Sjhb__FBSDID("$FreeBSD: head/sys/x86/acpica/madt.c 278473 2015-02-09 21:00:56Z kib $"); 29121992Sjhb 30121992Sjhb#include <sys/param.h> 31121992Sjhb#include <sys/systm.h> 32121992Sjhb#include <sys/bus.h> 33121992Sjhb#include <sys/kernel.h> 34121992Sjhb#include <sys/malloc.h> 35121992Sjhb#include <sys/smp.h> 36121992Sjhb#include <vm/vm.h> 37121992Sjhb#include <vm/pmap.h> 38121992Sjhb 39214631Sjhb#include <x86/apicreg.h> 40121992Sjhb#include <machine/intr_machdep.h> 41261087Sjhb#include <x86/apicvar.h> 42278473Skib#include <machine/md_var.h> 43121992Sjhb 44193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193530Sjkim#include <contrib/dev/acpica/include/actables.h> 46193530Sjkim 47121992Sjhb#include <dev/acpica/acpivar.h> 48121992Sjhb#include <dev/pci/pcivar.h> 49121992Sjhb 50121992Sjhb/* These two arrays are indexed by APIC IDs. */ 51233623Sjhbstatic struct { 52121992Sjhb void *io_apic; 53121992Sjhb UINT32 io_vector; 54233623Sjhb} *ioapics; 55121992Sjhb 56233623Sjhbstatic struct lapic_info { 57121992Sjhb u_int la_enabled:1; 58129960Sjhb u_int la_acpi_id:8; 59233623Sjhb} lapics[MAX_APIC_ID + 1]; 60121992Sjhb 61269512Sroygerint madt_found_sci_override; 62167814Sjkimstatic ACPI_TABLE_MADT *madt; 63121992Sjhbstatic vm_paddr_t madt_physaddr; 64121992Sjhbstatic vm_offset_t madt_length; 65121992Sjhb 66227293Sedstatic MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 67121992Sjhb 68167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 69167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 70121992Sjhbstatic int madt_find_cpu(u_int acpi_id, u_int *apic_id); 71121992Sjhbstatic int madt_find_interrupt(int intr, void **apic, u_int *pin); 72167814Sjkimstatic void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 73167814Sjkimstatic void madt_parse_interrupt_override( 74167814Sjkim ACPI_MADT_INTERRUPT_OVERRIDE *intr); 75167814Sjkimstatic void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 76167814Sjkim void *arg __unused); 77167814Sjkimstatic void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 78167814Sjkimstatic void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 79121992Sjhbstatic int madt_probe(void); 80121992Sjhbstatic int madt_probe_cpus(void); 81167814Sjkimstatic void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 82167814Sjkim void *arg __unused); 83121992Sjhbstatic void madt_register(void *dummy); 84121992Sjhbstatic int madt_setup_local(void); 85121992Sjhbstatic int madt_setup_io(void); 86197439Sjhbstatic void madt_walk_table(acpi_subtable_handler *handler, void *arg); 87121992Sjhb 88121992Sjhbstatic struct apic_enumerator madt_enumerator = { 89121992Sjhb "MADT", 90121992Sjhb madt_probe, 91121992Sjhb madt_probe_cpus, 92121992Sjhb madt_setup_local, 93121992Sjhb madt_setup_io 94121992Sjhb}; 95121992Sjhb 96121992Sjhb/* 97121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 98121992Sjhb */ 99121992Sjhbstatic int 100121992Sjhbmadt_probe(void) 101121992Sjhb{ 102121992Sjhb 103197439Sjhb madt_physaddr = acpi_find_table(ACPI_SIG_MADT); 104197439Sjhb if (madt_physaddr == 0) 105121992Sjhb return (ENXIO); 106269511Sroyger return (-50); 107121992Sjhb} 108121992Sjhb 109121992Sjhb/* 110121992Sjhb * Run through the MP table enumerating CPUs. 111121992Sjhb */ 112121992Sjhbstatic int 113121992Sjhbmadt_probe_cpus(void) 114121992Sjhb{ 115121992Sjhb 116197439Sjhb madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); 117197439Sjhb madt_length = madt->Header.Length; 118121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 119121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 120197439Sjhb acpi_unmap_table(madt); 121121992Sjhb madt = NULL; 122121992Sjhb return (0); 123121992Sjhb} 124121992Sjhb 125121992Sjhb/* 126121992Sjhb * Initialize the local APIC on the BSP. 127121992Sjhb */ 128121992Sjhbstatic int 129121992Sjhbmadt_setup_local(void) 130121992Sjhb{ 131278473Skib ACPI_TABLE_DMAR *dmartbl; 132278473Skib vm_paddr_t dmartbl_physaddr; 133121992Sjhb 134161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 135278473Skib if ((cpu_feature2 & CPUID2_X2APIC) != 0) { 136278473Skib x2apic_mode = 1; 137278473Skib dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR); 138278473Skib if (dmartbl_physaddr != 0) { 139278473Skib dmartbl = acpi_map_table(dmartbl_physaddr, 140278473Skib ACPI_SIG_DMAR); 141278473Skib if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) { 142278473Skib x2apic_mode = 0; 143278473Skib if (bootverbose) 144278473Skib printf( 145278473Skib "x2APIC available but disabled by DMAR table\n"); 146278473Skib } 147278473Skib acpi_unmap_table(dmartbl); 148278473Skib } 149278473Skib TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode); 150278473Skib } 151278473Skib 152167814Sjkim lapic_init(madt->Address); 153121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 154167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 155167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 156121992Sjhb 157121992Sjhb /* 158121992Sjhb * We ignore 64-bit local APIC override entries. Should we 159121992Sjhb * perhaps emit a warning here if we find one? 160121992Sjhb */ 161121992Sjhb return (0); 162121992Sjhb} 163121992Sjhb 164121992Sjhb/* 165125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 166121992Sjhb */ 167121992Sjhbstatic int 168121992Sjhbmadt_setup_io(void) 169121992Sjhb{ 170128930Sjhb void *ioapic; 171128930Sjhb u_int pin; 172121992Sjhb int i; 173121992Sjhb 174125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 175125048Sjhb i = acpi_Startup(); 176125048Sjhb if (ACPI_FAILURE(i)) { 177125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 178125048Sjhb AcpiFormatException(i)); 179125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 180125048Sjhb panic("Using MADT but ACPI doesn't work"); 181125048Sjhb } 182233623Sjhb 183233623Sjhb ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 184233623Sjhb M_WAITOK | M_ZERO); 185233623Sjhb 186121992Sjhb /* First, we run through adding I/O APIC's. */ 187121992Sjhb madt_walk_table(madt_parse_apics, NULL); 188121992Sjhb 189121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 190121992Sjhb madt_walk_table(madt_parse_ints, NULL); 191121992Sjhb 192128930Sjhb /* 193128930Sjhb * If there was not an explicit override entry for the SCI, 194128930Sjhb * force it to use level trigger and active-low polarity. 195128930Sjhb */ 196128930Sjhb if (!madt_found_sci_override) { 197167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 198167814Sjkim &pin) != 0) 199167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 200167814Sjkim AcpiGbl_FADT.SciInterrupt); 201128930Sjhb else { 202128930Sjhb printf( 203128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 204128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 205128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 206128930Sjhb } 207128930Sjhb } 208128930Sjhb 209121992Sjhb /* Third, we register all the I/O APIC's. */ 210169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 211121992Sjhb if (ioapics[i].io_apic != NULL) 212121992Sjhb ioapic_register(ioapics[i].io_apic); 213121992Sjhb 214121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 215121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 216121992Sjhb 217233623Sjhb free(ioapics, M_MADT); 218233623Sjhb ioapics = NULL; 219233623Sjhb 220121992Sjhb return (0); 221121992Sjhb} 222121992Sjhb 223121992Sjhbstatic void 224121992Sjhbmadt_register(void *dummy __unused) 225121992Sjhb{ 226121992Sjhb 227121992Sjhb apic_register_enumerator(&madt_enumerator); 228121992Sjhb} 229215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 230121992Sjhb 231121992Sjhb/* 232121992Sjhb * Call the handler routine for each entry in the MADT table. 233121992Sjhb */ 234121992Sjhbstatic void 235197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg) 236121992Sjhb{ 237121992Sjhb 238197439Sjhb acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 239197439Sjhb handler, arg); 240121992Sjhb} 241121992Sjhb 242121992Sjhbstatic void 243167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 244121992Sjhb{ 245167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 246121992Sjhb struct lapic_info *la; 247121992Sjhb 248121992Sjhb switch (entry->Type) { 249167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 250121992Sjhb /* 251121992Sjhb * The MADT does not include a BSP flag, so we have to 252121992Sjhb * let the MP code figure out which CPU is the BSP on 253121992Sjhb * its own. 254121992Sjhb */ 255167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 256121992Sjhb if (bootverbose) 257167814Sjkim printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 258167814Sjkim proc->Id, proc->ProcessorId, 259167814Sjkim (proc->LapicFlags & ACPI_MADT_ENABLED) ? 260167814Sjkim "enabled" : "disabled"); 261167814Sjkim if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 262130310Sjhb break; 263169395Sjhb if (proc->Id > MAX_APIC_ID) 264167814Sjkim panic("%s: CPU ID %u too high", __func__, proc->Id); 265167814Sjkim la = &lapics[proc->Id]; 266130310Sjhb KASSERT(la->la_enabled == 0, 267167814Sjkim ("Duplicate local APIC ID %u", proc->Id)); 268130310Sjhb la->la_enabled = 1; 269129960Sjhb la->la_acpi_id = proc->ProcessorId; 270167814Sjkim lapic_create(proc->Id, 0); 271121992Sjhb break; 272121992Sjhb } 273121992Sjhb} 274121992Sjhb 275121992Sjhb 276121992Sjhb/* 277121992Sjhb * Add an I/O APIC from an entry in the table. 278121992Sjhb */ 279121992Sjhbstatic void 280167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 281121992Sjhb{ 282167814Sjkim ACPI_MADT_IO_APIC *apic; 283121992Sjhb 284121992Sjhb switch (entry->Type) { 285167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 286167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 287121992Sjhb if (bootverbose) 288167814Sjkim printf( 289167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 290167814Sjkim apic->Id, apic->GlobalIrqBase, 291123326Snjl (void *)(uintptr_t)apic->Address); 292169395Sjhb if (apic->Id > MAX_APIC_ID) 293167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 294167814Sjkim apic->Id); 295167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 296167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 297189404Sjhb if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 298189404Sjhb printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 299189404Sjhb break; 300189404Sjhb } 301167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 302167814Sjkim apic->Id, apic->GlobalIrqBase); 303167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 304121992Sjhb break; 305121992Sjhb default: 306121992Sjhb break; 307121992Sjhb } 308121992Sjhb} 309121992Sjhb 310121992Sjhb/* 311129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 312129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 313128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 314129128Sjhb * SCI for which we use Active Lo, Level Triggered. 315121992Sjhb */ 316128930Sjhbstatic enum intr_polarity 317167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 318121992Sjhb{ 319121992Sjhb 320167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 321263859Stakawata default: 322269184Sakiyama printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 323263859Stakawata /* FALLTHROUGH*/ 324167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 325167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 326128930Sjhb return (INTR_POLARITY_LOW); 327128930Sjhb else 328128930Sjhb return (INTR_POLARITY_HIGH); 329167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 330128930Sjhb return (INTR_POLARITY_HIGH); 331167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 332263859Stakawata return (INTR_POLARITY_LOW); 333121992Sjhb } 334121992Sjhb} 335121992Sjhb 336128930Sjhbstatic enum intr_trigger 337167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 338121992Sjhb{ 339121992Sjhb 340167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 341263859Stakawata default: 342269184Sakiyama printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 343263859Stakawata /*FALLTHROUGH*/ 344167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 345167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 346128930Sjhb return (INTR_TRIGGER_LEVEL); 347128930Sjhb else 348128930Sjhb return (INTR_TRIGGER_EDGE); 349167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 350128930Sjhb return (INTR_TRIGGER_EDGE); 351167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 352263859Stakawata return (INTR_TRIGGER_LEVEL); 353121992Sjhb } 354121992Sjhb} 355121992Sjhb 356121992Sjhb/* 357121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 358121992Sjhb */ 359121992Sjhbstatic int 360121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 361121992Sjhb{ 362129960Sjhb int i; 363121992Sjhb 364169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 365130310Sjhb if (!lapics[i].la_enabled) 366129960Sjhb continue; 367129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 368129960Sjhb continue; 369129960Sjhb *apic_id = i; 370130310Sjhb return (0); 371129960Sjhb } 372129960Sjhb return (ENOENT); 373121992Sjhb} 374121992Sjhb 375121992Sjhb/* 376121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 377121992Sjhb * interrupt. 378121992Sjhb */ 379121992Sjhbstatic int 380121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 381121992Sjhb{ 382121992Sjhb int i, best; 383121992Sjhb 384121992Sjhb best = -1; 385169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 386121992Sjhb if (ioapics[i].io_apic == NULL || 387121992Sjhb ioapics[i].io_vector > intr) 388121992Sjhb continue; 389121992Sjhb if (best == -1 || 390121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 391121992Sjhb best = i; 392121992Sjhb } 393121992Sjhb if (best == -1) 394121992Sjhb return (ENOENT); 395121992Sjhb *apic = ioapics[best].io_apic; 396121992Sjhb *pin = intr - ioapics[best].io_vector; 397121992Sjhb if (*pin > 32) 398121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 399121992Sjhb intr); 400121992Sjhb return (0); 401121992Sjhb} 402121992Sjhb 403269512Sroygervoid 404269512Sroygermadt_parse_interrupt_values(void *entry, 405269512Sroyger enum intr_trigger *trig, enum intr_polarity *pol) 406121992Sjhb{ 407269512Sroyger ACPI_MADT_INTERRUPT_OVERRIDE *intr; 408128930Sjhb char buf[64]; 409121992Sjhb 410269512Sroyger intr = entry; 411269512Sroyger 412121992Sjhb if (bootverbose) 413142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 414167814Sjkim intr->SourceIrq, intr->GlobalIrq); 415121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 416121992Sjhb 417125048Sjhb /* 418128930Sjhb * Lookup the appropriate trigger and polarity modes for this 419128930Sjhb * entry. 420128930Sjhb */ 421269512Sroyger *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 422269512Sroyger *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 423269512Sroyger 424128930Sjhb /* 425125048Sjhb * If the SCI is identity mapped but has edge trigger and 426128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 427128329Sjhb * force it to use level/lo. 428125048Sjhb */ 429167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 430128930Sjhb madt_found_sci_override = 1; 431128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 432128930Sjhb if (tolower(buf[0]) == 'e') 433269512Sroyger *trig = INTR_TRIGGER_EDGE; 434128930Sjhb else if (tolower(buf[0]) == 'l') 435269512Sroyger *trig = INTR_TRIGGER_LEVEL; 436128930Sjhb else 437128930Sjhb panic( 438128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 439128930Sjhb buf); 440128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 441269512Sroyger *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 442128930Sjhb } 443128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 444128930Sjhb if (tolower(buf[0]) == 'h') 445269512Sroyger *pol = INTR_POLARITY_HIGH; 446128930Sjhb else if (tolower(buf[0]) == 'l') 447269512Sroyger *pol = INTR_POLARITY_LOW; 448128930Sjhb else 449128930Sjhb panic( 450128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 451128930Sjhb buf); 452128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 453269512Sroyger *pol == INTR_POLARITY_HIGH ? "high" : "low"); 454128930Sjhb } 455128930Sjhb } 456269512Sroyger} 457125048Sjhb 458269512Sroyger/* 459269512Sroyger * Parse an interrupt source override for an ISA interrupt. 460269512Sroyger */ 461269512Sroygerstatic void 462269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 463269512Sroyger{ 464269512Sroyger void *new_ioapic, *old_ioapic; 465269512Sroyger u_int new_pin, old_pin; 466269512Sroyger enum intr_trigger trig; 467269512Sroyger enum intr_polarity pol; 468269512Sroyger 469269512Sroyger if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 470269512Sroyger intr->GlobalIrq == 2) { 471269512Sroyger if (bootverbose) 472269512Sroyger printf("MADT: Skipping timer override\n"); 473269512Sroyger return; 474269512Sroyger } 475269512Sroyger 476269512Sroyger if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 477269512Sroyger printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 478269512Sroyger intr->GlobalIrq, intr->SourceIrq); 479269512Sroyger return; 480269512Sroyger } 481269512Sroyger 482269512Sroyger madt_parse_interrupt_values(intr, &trig, &pol); 483269512Sroyger 484128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 485167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 486125048Sjhb /* 487125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 488125048Sjhb * then override the vector we use to setup and allocate 489125048Sjhb * the interrupt. 490125048Sjhb */ 491167814Sjkim if (intr->GlobalIrq > 15 && 492167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 493167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 494122502Sjhb else 495167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 496167814Sjkim intr->SourceIrq); 497167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 498122149Sjhb &old_pin) != 0) 499167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 500167814Sjkim intr->SourceIrq); 501122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 502167814Sjkim intr->SourceIrq) 503122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 504122149Sjhb } 505128930Sjhb 506128930Sjhb /* Program the polarity and trigger mode. */ 507128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 508128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 509121992Sjhb} 510121992Sjhb 511121992Sjhb/* 512121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 513121992Sjhb */ 514121992Sjhbstatic void 515167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 516121992Sjhb{ 517121992Sjhb void *ioapic; 518121992Sjhb u_int pin; 519121992Sjhb 520167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 521167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 522167814Sjkim nmi->GlobalIrq); 523121992Sjhb return; 524121992Sjhb } 525121992Sjhb 526121992Sjhb ioapic_set_nmi(ioapic, pin); 527167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 528121992Sjhb ioapic_set_triggermode(ioapic, pin, 529167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 530263794Stakawata if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 531121992Sjhb ioapic_set_polarity(ioapic, pin, 532167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 533121992Sjhb} 534121992Sjhb 535121992Sjhb/* 536121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 537121992Sjhb */ 538121992Sjhbstatic void 539167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 540121992Sjhb{ 541121992Sjhb u_int apic_id, pin; 542121992Sjhb 543123326Snjl if (nmi->ProcessorId == 0xff) 544121992Sjhb apic_id = APIC_ID_ALL; 545123326Snjl else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 546121992Sjhb if (bootverbose) 547167814Sjkim printf("MADT: Ignoring local NMI routed to " 548167814Sjkim "ACPI CPU %u\n", nmi->ProcessorId); 549121992Sjhb return; 550121992Sjhb } 551123326Snjl if (nmi->Lint == 0) 552259140Sjhb pin = APIC_LVT_LINT0; 553121992Sjhb else 554259140Sjhb pin = APIC_LVT_LINT1; 555121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 556167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 557121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 558167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 559167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 560121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 561167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 562121992Sjhb} 563121992Sjhb 564121992Sjhb/* 565121992Sjhb * Parse interrupt entries. 566121992Sjhb */ 567121992Sjhbstatic void 568167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 569121992Sjhb{ 570121992Sjhb 571121992Sjhb switch (entry->Type) { 572167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 573121992Sjhb madt_parse_interrupt_override( 574167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 575121992Sjhb break; 576167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 577167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 578121992Sjhb break; 579167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 580167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 581121992Sjhb break; 582121992Sjhb } 583121992Sjhb} 584121992Sjhb 585121992Sjhb/* 586121992Sjhb * Setup per-CPU ACPI IDs. 587121992Sjhb */ 588121992Sjhbstatic void 589121992Sjhbmadt_set_ids(void *dummy) 590121992Sjhb{ 591129960Sjhb struct lapic_info *la; 592121992Sjhb struct pcpu *pc; 593129960Sjhb u_int i; 594121992Sjhb 595121992Sjhb if (madt == NULL) 596121992Sjhb return; 597209059Sjhb CPU_FOREACH(i) { 598121992Sjhb pc = pcpu_find(i); 599167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 600129960Sjhb la = &lapics[pc->pc_apic_id]; 601130310Sjhb if (!la->la_enabled) 602129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 603129960Sjhb pc->pc_apic_id); 604129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 605129960Sjhb if (bootverbose) 606129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 607129960Sjhb la->la_acpi_id); 608121992Sjhb } 609121992Sjhb} 610256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 611