1121992Sjhb/*- 2121992Sjhb * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> 3121992Sjhb * 4121992Sjhb * Redistribution and use in source and binary forms, with or without 5121992Sjhb * modification, are permitted provided that the following conditions 6121992Sjhb * are met: 7121992Sjhb * 1. Redistributions of source code must retain the above copyright 8121992Sjhb * notice, this list of conditions and the following disclaimer. 9121992Sjhb * 2. Redistributions in binary form must reproduce the above copyright 10121992Sjhb * notice, this list of conditions and the following disclaimer in the 11121992Sjhb * documentation and/or other materials provided with the distribution. 12121992Sjhb * 13121992Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14121992Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15121992Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16121992Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17121992Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18121992Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19121992Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20121992Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21121992Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22121992Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23121992Sjhb * SUCH DAMAGE. 24121992Sjhb */ 25121992Sjhb 26121992Sjhb#include <sys/cdefs.h> 27121992Sjhb__FBSDID("$FreeBSD: stable/11/sys/x86/acpica/madt.c 367457 2020-11-07 18:10:59Z dim $"); 28121992Sjhb 29121992Sjhb#include <sys/param.h> 30121992Sjhb#include <sys/systm.h> 31121992Sjhb#include <sys/bus.h> 32121992Sjhb#include <sys/kernel.h> 33278749Skib#include <sys/limits.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> 43278749Skib#include <x86/vmware.h> 44121992Sjhb 45193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 46316303Sjkim#include <contrib/dev/acpica/include/aclocal.h> 47193530Sjkim#include <contrib/dev/acpica/include/actables.h> 48193530Sjkim 49121992Sjhb#include <dev/acpica/acpivar.h> 50121992Sjhb#include <dev/pci/pcivar.h> 51121992Sjhb 52121992Sjhb/* These two arrays are indexed by APIC IDs. */ 53233623Sjhbstatic struct { 54121992Sjhb void *io_apic; 55121992Sjhb UINT32 io_vector; 56233623Sjhb} *ioapics; 57121992Sjhb 58233623Sjhbstatic struct lapic_info { 59284175Sjhb u_int la_enabled; 60284175Sjhb u_int la_acpi_id; 61233623Sjhb} lapics[MAX_APIC_ID + 1]; 62121992Sjhb 63269512Sroygerint madt_found_sci_override; 64167814Sjkimstatic ACPI_TABLE_MADT *madt; 65121992Sjhbstatic vm_paddr_t madt_physaddr; 66121992Sjhbstatic vm_offset_t madt_length; 67121992Sjhb 68227293Sedstatic MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 69121992Sjhb 70167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 71167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 72121992Sjhbstatic int madt_find_cpu(u_int acpi_id, u_int *apic_id); 73121992Sjhbstatic int madt_find_interrupt(int intr, void **apic, u_int *pin); 74167814Sjkimstatic void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 75167814Sjkimstatic void madt_parse_interrupt_override( 76167814Sjkim ACPI_MADT_INTERRUPT_OVERRIDE *intr); 77167814Sjkimstatic void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 78167814Sjkim void *arg __unused); 79167814Sjkimstatic void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 80167814Sjkimstatic void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 81121992Sjhbstatic int madt_probe(void); 82121992Sjhbstatic int madt_probe_cpus(void); 83167814Sjkimstatic void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 84167814Sjkim void *arg __unused); 85121992Sjhbstatic void madt_register(void *dummy); 86121992Sjhbstatic int madt_setup_local(void); 87121992Sjhbstatic int madt_setup_io(void); 88197439Sjhbstatic void madt_walk_table(acpi_subtable_handler *handler, void *arg); 89121992Sjhb 90121992Sjhbstatic struct apic_enumerator madt_enumerator = { 91121992Sjhb "MADT", 92121992Sjhb madt_probe, 93121992Sjhb madt_probe_cpus, 94121992Sjhb madt_setup_local, 95121992Sjhb madt_setup_io 96121992Sjhb}; 97121992Sjhb 98121992Sjhb/* 99121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 100121992Sjhb */ 101121992Sjhbstatic int 102121992Sjhbmadt_probe(void) 103121992Sjhb{ 104121992Sjhb 105197439Sjhb madt_physaddr = acpi_find_table(ACPI_SIG_MADT); 106197439Sjhb if (madt_physaddr == 0) 107121992Sjhb return (ENXIO); 108269511Sroyger return (-50); 109121992Sjhb} 110121992Sjhb 111121992Sjhb/* 112121992Sjhb * Run through the MP table enumerating CPUs. 113121992Sjhb */ 114121992Sjhbstatic int 115121992Sjhbmadt_probe_cpus(void) 116121992Sjhb{ 117121992Sjhb 118197439Sjhb madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); 119197439Sjhb madt_length = madt->Header.Length; 120121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 121121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 122197439Sjhb acpi_unmap_table(madt); 123121992Sjhb madt = NULL; 124121992Sjhb return (0); 125121992Sjhb} 126121992Sjhb 127121992Sjhb/* 128121992Sjhb * Initialize the local APIC on the BSP. 129121992Sjhb */ 130121992Sjhbstatic int 131121992Sjhbmadt_setup_local(void) 132121992Sjhb{ 133278473Skib ACPI_TABLE_DMAR *dmartbl; 134278473Skib vm_paddr_t dmartbl_physaddr; 135286994Skib const char *reason; 136286994Skib char *hw_vendor; 137278749Skib u_int p[4]; 138306628Skib int user_x2apic; 139306628Skib bool bios_x2apic; 140121992Sjhb 141161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 142278473Skib if ((cpu_feature2 & CPUID2_X2APIC) != 0) { 143286994Skib reason = NULL; 144286994Skib 145286994Skib /* 146286994Skib * Automatically detect several configurations where 147286994Skib * x2APIC mode is known to cause troubles. User can 148286994Skib * override the setting with hw.x2apic_enable tunable. 149286994Skib */ 150278473Skib dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR); 151278473Skib if (dmartbl_physaddr != 0) { 152278473Skib dmartbl = acpi_map_table(dmartbl_physaddr, 153278473Skib ACPI_SIG_DMAR); 154306628Skib if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) 155286994Skib reason = "by DMAR table"; 156278473Skib acpi_unmap_table(dmartbl); 157278473Skib } 158278749Skib if (vm_guest == VM_GUEST_VMWARE) { 159278749Skib vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p); 160278749Skib if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 || 161306628Skib (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) 162306628Skib reason = 163306628Skib "inside VMWare without intr redirection"; 164279286Skib } else if (vm_guest == VM_GUEST_XEN) { 165286994Skib reason = "due to running under XEN"; 166291686Skib } else if (vm_guest == VM_GUEST_NO && 167291686Skib CPUID_TO_FAMILY(cpu_id) == 0x6 && 168291686Skib CPUID_TO_MODEL(cpu_id) == 0x2a) { 169286994Skib hw_vendor = kern_getenv("smbios.planar.maker"); 170286994Skib /* 171291686Skib * It seems that some Lenovo and ASUS 172291686Skib * SandyBridge-based notebook BIOSes have a 173291686Skib * bug which prevents booting AP in x2APIC 174291686Skib * mode. Since the only way to detect mobile 175291686Skib * CPU is to check northbridge pci id, which 176291686Skib * cannot be done that early, disable x2APIC 177291686Skib * for all Lenovo and ASUS SandyBridge 178291686Skib * machines. 179286994Skib */ 180291686Skib if (hw_vendor != NULL) { 181291686Skib if (!strcmp(hw_vendor, "LENOVO") || 182291686Skib !strcmp(hw_vendor, 183291686Skib "ASUSTeK Computer Inc.")) { 184291686Skib reason = 185291686Skib "for a suspected SandyBridge BIOS bug"; 186291686Skib } 187291686Skib freeenv(hw_vendor); 188286994Skib } 189278749Skib } 190306628Skib bios_x2apic = lapic_is_x2apic(); 191306628Skib if (reason != NULL && bios_x2apic) { 192306628Skib if (bootverbose) 193306628Skib printf("x2APIC should be disabled %s but " 194306628Skib "already enabled by BIOS; enabling.\n", 195306628Skib reason); 196306628Skib reason = NULL; 197306628Skib } 198306628Skib if (reason == NULL) 199306628Skib x2apic_mode = 1; 200306628Skib else if (bootverbose) 201286994Skib printf("x2APIC available but disabled %s\n", reason); 202306628Skib user_x2apic = x2apic_mode; 203306628Skib TUNABLE_INT_FETCH("hw.x2apic_enable", &user_x2apic); 204306628Skib if (user_x2apic != x2apic_mode) { 205306628Skib if (bios_x2apic && !user_x2apic) 206306628Skib printf("x2APIC disabled by tunable and " 207306628Skib "enabled by BIOS; ignoring tunable."); 208306628Skib else 209306628Skib x2apic_mode = user_x2apic; 210306628Skib } 211278473Skib } 212278473Skib 213167814Sjkim lapic_init(madt->Address); 214121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 215167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 216167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 217121992Sjhb 218121992Sjhb /* 219121992Sjhb * We ignore 64-bit local APIC override entries. Should we 220121992Sjhb * perhaps emit a warning here if we find one? 221121992Sjhb */ 222121992Sjhb return (0); 223121992Sjhb} 224121992Sjhb 225121992Sjhb/* 226125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 227121992Sjhb */ 228121992Sjhbstatic int 229121992Sjhbmadt_setup_io(void) 230121992Sjhb{ 231128930Sjhb void *ioapic; 232128930Sjhb u_int pin; 233121992Sjhb int i; 234121992Sjhb 235125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 236125048Sjhb i = acpi_Startup(); 237125048Sjhb if (ACPI_FAILURE(i)) { 238125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 239125048Sjhb AcpiFormatException(i)); 240125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 241125048Sjhb panic("Using MADT but ACPI doesn't work"); 242125048Sjhb } 243233623Sjhb 244233623Sjhb ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 245233623Sjhb M_WAITOK | M_ZERO); 246233623Sjhb 247121992Sjhb /* First, we run through adding I/O APIC's. */ 248121992Sjhb madt_walk_table(madt_parse_apics, NULL); 249121992Sjhb 250121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 251121992Sjhb madt_walk_table(madt_parse_ints, NULL); 252121992Sjhb 253128930Sjhb /* 254128930Sjhb * If there was not an explicit override entry for the SCI, 255128930Sjhb * force it to use level trigger and active-low polarity. 256128930Sjhb */ 257128930Sjhb if (!madt_found_sci_override) { 258167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 259167814Sjkim &pin) != 0) 260167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 261167814Sjkim AcpiGbl_FADT.SciInterrupt); 262128930Sjhb else { 263128930Sjhb printf( 264128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 265128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 266128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 267128930Sjhb } 268128930Sjhb } 269128930Sjhb 270121992Sjhb /* Third, we register all the I/O APIC's. */ 271169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 272121992Sjhb if (ioapics[i].io_apic != NULL) 273121992Sjhb ioapic_register(ioapics[i].io_apic); 274121992Sjhb 275121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 276121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 277121992Sjhb 278233623Sjhb free(ioapics, M_MADT); 279233623Sjhb ioapics = NULL; 280233623Sjhb 281121992Sjhb return (0); 282121992Sjhb} 283121992Sjhb 284121992Sjhbstatic void 285121992Sjhbmadt_register(void *dummy __unused) 286121992Sjhb{ 287121992Sjhb 288121992Sjhb apic_register_enumerator(&madt_enumerator); 289121992Sjhb} 290215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 291121992Sjhb 292121992Sjhb/* 293121992Sjhb * Call the handler routine for each entry in the MADT table. 294121992Sjhb */ 295121992Sjhbstatic void 296197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg) 297121992Sjhb{ 298121992Sjhb 299197439Sjhb acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 300197439Sjhb handler, arg); 301121992Sjhb} 302121992Sjhb 303121992Sjhbstatic void 304284175Sjhbmadt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags) 305284175Sjhb{ 306284175Sjhb struct lapic_info *la; 307284175Sjhb 308284175Sjhb /* 309284175Sjhb * The MADT does not include a BSP flag, so we have to let the 310284175Sjhb * MP code figure out which CPU is the BSP on its own. 311284175Sjhb */ 312284175Sjhb if (bootverbose) 313284175Sjhb printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 314284175Sjhb apic_id, acpi_id, flags & ACPI_MADT_ENABLED ? 315284175Sjhb "enabled" : "disabled"); 316284175Sjhb if (!(flags & ACPI_MADT_ENABLED)) 317284175Sjhb return; 318284175Sjhb if (apic_id > MAX_APIC_ID) { 319284175Sjhb printf("MADT: Ignoring local APIC ID %u (too high)\n", 320284175Sjhb apic_id); 321284175Sjhb return; 322284175Sjhb } 323284175Sjhb 324284175Sjhb la = &lapics[apic_id]; 325284175Sjhb KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id)); 326284175Sjhb la->la_enabled = 1; 327284175Sjhb la->la_acpi_id = acpi_id; 328284175Sjhb lapic_create(apic_id, 0); 329284175Sjhb} 330284175Sjhb 331284175Sjhbstatic void 332167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 333121992Sjhb{ 334167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 335284175Sjhb ACPI_MADT_LOCAL_X2APIC *x2apic; 336121992Sjhb 337121992Sjhb switch (entry->Type) { 338167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 339167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 340284175Sjhb madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags); 341121992Sjhb break; 342284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC: 343284175Sjhb x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry; 344284175Sjhb madt_add_cpu(x2apic->Uid, x2apic->LocalApicId, 345284175Sjhb x2apic->LapicFlags); 346284175Sjhb break; 347121992Sjhb } 348121992Sjhb} 349121992Sjhb 350121992Sjhb 351121992Sjhb/* 352121992Sjhb * Add an I/O APIC from an entry in the table. 353121992Sjhb */ 354121992Sjhbstatic void 355167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 356121992Sjhb{ 357167814Sjkim ACPI_MADT_IO_APIC *apic; 358121992Sjhb 359121992Sjhb switch (entry->Type) { 360167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 361167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 362121992Sjhb if (bootverbose) 363167814Sjkim printf( 364167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 365167814Sjkim apic->Id, apic->GlobalIrqBase, 366123326Snjl (void *)(uintptr_t)apic->Address); 367169395Sjhb if (apic->Id > MAX_APIC_ID) 368167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 369167814Sjkim apic->Id); 370167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 371167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 372167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 373167814Sjkim apic->Id, apic->GlobalIrqBase); 374167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 375121992Sjhb break; 376121992Sjhb default: 377121992Sjhb break; 378121992Sjhb } 379121992Sjhb} 380121992Sjhb 381121992Sjhb/* 382129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 383129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 384128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 385129128Sjhb * SCI for which we use Active Lo, Level Triggered. 386121992Sjhb */ 387128930Sjhbstatic enum intr_polarity 388167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 389121992Sjhb{ 390121992Sjhb 391167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 392263859Stakawata default: 393269184Sakiyama printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 394263859Stakawata /* FALLTHROUGH*/ 395167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 396167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 397128930Sjhb return (INTR_POLARITY_LOW); 398128930Sjhb else 399128930Sjhb return (INTR_POLARITY_HIGH); 400167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 401128930Sjhb return (INTR_POLARITY_HIGH); 402167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 403263859Stakawata return (INTR_POLARITY_LOW); 404121992Sjhb } 405121992Sjhb} 406121992Sjhb 407128930Sjhbstatic enum intr_trigger 408167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 409121992Sjhb{ 410121992Sjhb 411167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 412263859Stakawata default: 413269184Sakiyama printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 414263859Stakawata /*FALLTHROUGH*/ 415167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 416167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 417128930Sjhb return (INTR_TRIGGER_LEVEL); 418128930Sjhb else 419128930Sjhb return (INTR_TRIGGER_EDGE); 420167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 421128930Sjhb return (INTR_TRIGGER_EDGE); 422167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 423263859Stakawata return (INTR_TRIGGER_LEVEL); 424121992Sjhb } 425121992Sjhb} 426121992Sjhb 427121992Sjhb/* 428121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 429121992Sjhb */ 430121992Sjhbstatic int 431121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 432121992Sjhb{ 433129960Sjhb int i; 434121992Sjhb 435169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 436130310Sjhb if (!lapics[i].la_enabled) 437129960Sjhb continue; 438129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 439129960Sjhb continue; 440129960Sjhb *apic_id = i; 441130310Sjhb return (0); 442129960Sjhb } 443129960Sjhb return (ENOENT); 444121992Sjhb} 445121992Sjhb 446121992Sjhb/* 447121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 448121992Sjhb * interrupt. 449121992Sjhb */ 450121992Sjhbstatic int 451121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 452121992Sjhb{ 453121992Sjhb int i, best; 454121992Sjhb 455121992Sjhb best = -1; 456169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 457121992Sjhb if (ioapics[i].io_apic == NULL || 458121992Sjhb ioapics[i].io_vector > intr) 459121992Sjhb continue; 460121992Sjhb if (best == -1 || 461121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 462121992Sjhb best = i; 463121992Sjhb } 464121992Sjhb if (best == -1) 465121992Sjhb return (ENOENT); 466121992Sjhb *apic = ioapics[best].io_apic; 467121992Sjhb *pin = intr - ioapics[best].io_vector; 468121992Sjhb if (*pin > 32) 469121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 470121992Sjhb intr); 471121992Sjhb return (0); 472121992Sjhb} 473121992Sjhb 474269512Sroygervoid 475269512Sroygermadt_parse_interrupt_values(void *entry, 476269512Sroyger enum intr_trigger *trig, enum intr_polarity *pol) 477121992Sjhb{ 478269512Sroyger ACPI_MADT_INTERRUPT_OVERRIDE *intr; 479128930Sjhb char buf[64]; 480121992Sjhb 481269512Sroyger intr = entry; 482269512Sroyger 483121992Sjhb if (bootverbose) 484142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 485167814Sjkim intr->SourceIrq, intr->GlobalIrq); 486121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 487121992Sjhb 488125048Sjhb /* 489128930Sjhb * Lookup the appropriate trigger and polarity modes for this 490128930Sjhb * entry. 491128930Sjhb */ 492269512Sroyger *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 493269512Sroyger *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 494269512Sroyger 495128930Sjhb /* 496125048Sjhb * If the SCI is identity mapped but has edge trigger and 497128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 498128329Sjhb * force it to use level/lo. 499125048Sjhb */ 500167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 501128930Sjhb madt_found_sci_override = 1; 502128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 503128930Sjhb if (tolower(buf[0]) == 'e') 504269512Sroyger *trig = INTR_TRIGGER_EDGE; 505128930Sjhb else if (tolower(buf[0]) == 'l') 506269512Sroyger *trig = INTR_TRIGGER_LEVEL; 507128930Sjhb else 508128930Sjhb panic( 509128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 510128930Sjhb buf); 511128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 512269512Sroyger *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 513128930Sjhb } 514128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 515128930Sjhb if (tolower(buf[0]) == 'h') 516269512Sroyger *pol = INTR_POLARITY_HIGH; 517128930Sjhb else if (tolower(buf[0]) == 'l') 518269512Sroyger *pol = INTR_POLARITY_LOW; 519128930Sjhb else 520128930Sjhb panic( 521128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 522128930Sjhb buf); 523128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 524269512Sroyger *pol == INTR_POLARITY_HIGH ? "high" : "low"); 525128930Sjhb } 526128930Sjhb } 527269512Sroyger} 528125048Sjhb 529269512Sroyger/* 530269512Sroyger * Parse an interrupt source override for an ISA interrupt. 531269512Sroyger */ 532269512Sroygerstatic void 533269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 534269512Sroyger{ 535269512Sroyger void *new_ioapic, *old_ioapic; 536269512Sroyger u_int new_pin, old_pin; 537269512Sroyger enum intr_trigger trig; 538269512Sroyger enum intr_polarity pol; 539269512Sroyger 540269512Sroyger if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 541269512Sroyger intr->GlobalIrq == 2) { 542269512Sroyger if (bootverbose) 543269512Sroyger printf("MADT: Skipping timer override\n"); 544269512Sroyger return; 545269512Sroyger } 546269512Sroyger 547269512Sroyger if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 548269512Sroyger printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 549269512Sroyger intr->GlobalIrq, intr->SourceIrq); 550269512Sroyger return; 551269512Sroyger } 552269512Sroyger 553269512Sroyger madt_parse_interrupt_values(intr, &trig, &pol); 554269512Sroyger 555128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 556167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 557125048Sjhb /* 558125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 559125048Sjhb * then override the vector we use to setup and allocate 560125048Sjhb * the interrupt. 561125048Sjhb */ 562167814Sjkim if (intr->GlobalIrq > 15 && 563167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 564167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 565122502Sjhb else 566167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 567167814Sjkim intr->SourceIrq); 568167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 569122149Sjhb &old_pin) != 0) 570167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 571167814Sjkim intr->SourceIrq); 572122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 573167814Sjkim intr->SourceIrq) 574122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 575122149Sjhb } 576128930Sjhb 577128930Sjhb /* Program the polarity and trigger mode. */ 578128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 579128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 580121992Sjhb} 581121992Sjhb 582121992Sjhb/* 583121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 584121992Sjhb */ 585121992Sjhbstatic void 586167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 587121992Sjhb{ 588121992Sjhb void *ioapic; 589121992Sjhb u_int pin; 590121992Sjhb 591167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 592167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 593167814Sjkim nmi->GlobalIrq); 594121992Sjhb return; 595121992Sjhb } 596121992Sjhb 597121992Sjhb ioapic_set_nmi(ioapic, pin); 598167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 599121992Sjhb ioapic_set_triggermode(ioapic, pin, 600167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 601263794Stakawata if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 602121992Sjhb ioapic_set_polarity(ioapic, pin, 603167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 604121992Sjhb} 605121992Sjhb 606121992Sjhb/* 607121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 608121992Sjhb */ 609121992Sjhbstatic void 610284175Sjhbmadt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags) 611121992Sjhb{ 612121992Sjhb u_int apic_id, pin; 613121992Sjhb 614284175Sjhb if (acpi_id == 0xffffffff) 615121992Sjhb apic_id = APIC_ID_ALL; 616284175Sjhb else if (madt_find_cpu(acpi_id, &apic_id) != 0) { 617121992Sjhb if (bootverbose) 618167814Sjkim printf("MADT: Ignoring local NMI routed to " 619284175Sjhb "ACPI CPU %u\n", acpi_id); 620121992Sjhb return; 621121992Sjhb } 622284175Sjhb if (Lint == 0) 623259140Sjhb pin = APIC_LVT_LINT0; 624121992Sjhb else 625259140Sjhb pin = APIC_LVT_LINT1; 626121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 627284175Sjhb if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 628121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 629284175Sjhb interrupt_trigger(IntiFlags, 0)); 630284175Sjhb if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 631121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 632284175Sjhb interrupt_polarity(IntiFlags, 0)); 633121992Sjhb} 634121992Sjhb 635284175Sjhbstatic void 636284175Sjhbmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 637284175Sjhb{ 638284175Sjhb 639284175Sjhb madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff : 640284175Sjhb nmi->ProcessorId, nmi->Lint, nmi->IntiFlags); 641284175Sjhb} 642284175Sjhb 643284175Sjhbstatic void 644284175Sjhbmadt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi) 645284175Sjhb{ 646284175Sjhb 647284175Sjhb madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags); 648284175Sjhb} 649284175Sjhb 650121992Sjhb/* 651121992Sjhb * Parse interrupt entries. 652121992Sjhb */ 653121992Sjhbstatic void 654167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 655121992Sjhb{ 656121992Sjhb 657121992Sjhb switch (entry->Type) { 658167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 659121992Sjhb madt_parse_interrupt_override( 660167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 661121992Sjhb break; 662167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 663167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 664121992Sjhb break; 665167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 666167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 667121992Sjhb break; 668284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 669284175Sjhb madt_parse_local_x2apic_nmi( 670284175Sjhb (ACPI_MADT_LOCAL_X2APIC_NMI *)entry); 671284175Sjhb break; 672121992Sjhb } 673121992Sjhb} 674121992Sjhb 675121992Sjhb/* 676121992Sjhb * Setup per-CPU ACPI IDs. 677121992Sjhb */ 678121992Sjhbstatic void 679121992Sjhbmadt_set_ids(void *dummy) 680121992Sjhb{ 681129960Sjhb struct lapic_info *la; 682121992Sjhb struct pcpu *pc; 683129960Sjhb u_int i; 684121992Sjhb 685121992Sjhb if (madt == NULL) 686121992Sjhb return; 687209059Sjhb CPU_FOREACH(i) { 688121992Sjhb pc = pcpu_find(i); 689167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 690129960Sjhb la = &lapics[pc->pc_apic_id]; 691130310Sjhb if (!la->la_enabled) 692129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 693129960Sjhb pc->pc_apic_id); 694129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 695129960Sjhb if (bootverbose) 696129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 697129960Sjhb la->la_acpi_id); 698121992Sjhb } 699121992Sjhb} 700256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 701