madt.c revision 291686
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 291686 2015-12-03 10:59:10Z kib $"); 29121992Sjhb 30121992Sjhb#include <sys/param.h> 31121992Sjhb#include <sys/systm.h> 32121992Sjhb#include <sys/bus.h> 33121992Sjhb#include <sys/kernel.h> 34278749Skib#include <sys/limits.h> 35121992Sjhb#include <sys/malloc.h> 36121992Sjhb#include <sys/smp.h> 37121992Sjhb#include <vm/vm.h> 38121992Sjhb#include <vm/pmap.h> 39121992Sjhb 40214631Sjhb#include <x86/apicreg.h> 41121992Sjhb#include <machine/intr_machdep.h> 42261087Sjhb#include <x86/apicvar.h> 43278473Skib#include <machine/md_var.h> 44278749Skib#include <x86/vmware.h> 45121992Sjhb 46193530Sjkim#include <contrib/dev/acpica/include/acpi.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]; 138121992Sjhb 139161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 140278473Skib if ((cpu_feature2 & CPUID2_X2APIC) != 0) { 141278473Skib x2apic_mode = 1; 142286994Skib reason = NULL; 143286994Skib 144286994Skib /* 145286994Skib * Automatically detect several configurations where 146286994Skib * x2APIC mode is known to cause troubles. User can 147286994Skib * override the setting with hw.x2apic_enable tunable. 148286994Skib */ 149278473Skib dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR); 150278473Skib if (dmartbl_physaddr != 0) { 151278473Skib dmartbl = acpi_map_table(dmartbl_physaddr, 152278473Skib ACPI_SIG_DMAR); 153278473Skib if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) { 154278473Skib x2apic_mode = 0; 155286994Skib reason = "by DMAR table"; 156278473Skib } 157278473Skib acpi_unmap_table(dmartbl); 158278473Skib } 159278749Skib if (vm_guest == VM_GUEST_VMWARE) { 160278749Skib vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p); 161278749Skib if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 || 162278749Skib (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) { 163278749Skib x2apic_mode = 0; 164286994Skib reason = "inside VMWare without intr redirection"; 165278749Skib } 166279286Skib } else if (vm_guest == VM_GUEST_XEN) { 167279286Skib x2apic_mode = 0; 168286994Skib reason = "due to running under XEN"; 169291686Skib } else if (vm_guest == VM_GUEST_NO && 170291686Skib CPUID_TO_FAMILY(cpu_id) == 0x6 && 171291686Skib CPUID_TO_MODEL(cpu_id) == 0x2a) { 172286994Skib hw_vendor = kern_getenv("smbios.planar.maker"); 173286994Skib /* 174291686Skib * It seems that some Lenovo and ASUS 175291686Skib * SandyBridge-based notebook BIOSes have a 176291686Skib * bug which prevents booting AP in x2APIC 177291686Skib * mode. Since the only way to detect mobile 178291686Skib * CPU is to check northbridge pci id, which 179291686Skib * cannot be done that early, disable x2APIC 180291686Skib * for all Lenovo and ASUS SandyBridge 181291686Skib * machines. 182286994Skib */ 183291686Skib if (hw_vendor != NULL) { 184291686Skib if (!strcmp(hw_vendor, "LENOVO") || 185291686Skib !strcmp(hw_vendor, 186291686Skib "ASUSTeK Computer Inc.")) { 187291686Skib x2apic_mode = 0; 188291686Skib reason = 189291686Skib "for a suspected SandyBridge BIOS bug"; 190291686Skib } 191291686Skib freeenv(hw_vendor); 192286994Skib } 193278749Skib } 194278473Skib TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode); 195286994Skib if (!x2apic_mode && reason != NULL && bootverbose) 196286994Skib printf("x2APIC available but disabled %s\n", reason); 197278473Skib } 198278473Skib 199167814Sjkim lapic_init(madt->Address); 200121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 201167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 202167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 203121992Sjhb 204121992Sjhb /* 205121992Sjhb * We ignore 64-bit local APIC override entries. Should we 206121992Sjhb * perhaps emit a warning here if we find one? 207121992Sjhb */ 208121992Sjhb return (0); 209121992Sjhb} 210121992Sjhb 211121992Sjhb/* 212125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 213121992Sjhb */ 214121992Sjhbstatic int 215121992Sjhbmadt_setup_io(void) 216121992Sjhb{ 217128930Sjhb void *ioapic; 218128930Sjhb u_int pin; 219121992Sjhb int i; 220121992Sjhb 221125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 222125048Sjhb i = acpi_Startup(); 223125048Sjhb if (ACPI_FAILURE(i)) { 224125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 225125048Sjhb AcpiFormatException(i)); 226125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 227125048Sjhb panic("Using MADT but ACPI doesn't work"); 228125048Sjhb } 229233623Sjhb 230233623Sjhb ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 231233623Sjhb M_WAITOK | M_ZERO); 232233623Sjhb 233121992Sjhb /* First, we run through adding I/O APIC's. */ 234121992Sjhb madt_walk_table(madt_parse_apics, NULL); 235121992Sjhb 236121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 237121992Sjhb madt_walk_table(madt_parse_ints, NULL); 238121992Sjhb 239128930Sjhb /* 240128930Sjhb * If there was not an explicit override entry for the SCI, 241128930Sjhb * force it to use level trigger and active-low polarity. 242128930Sjhb */ 243128930Sjhb if (!madt_found_sci_override) { 244167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 245167814Sjkim &pin) != 0) 246167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 247167814Sjkim AcpiGbl_FADT.SciInterrupt); 248128930Sjhb else { 249128930Sjhb printf( 250128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 251128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 252128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 253128930Sjhb } 254128930Sjhb } 255128930Sjhb 256121992Sjhb /* Third, we register all the I/O APIC's. */ 257169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 258121992Sjhb if (ioapics[i].io_apic != NULL) 259121992Sjhb ioapic_register(ioapics[i].io_apic); 260121992Sjhb 261121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 262121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 263121992Sjhb 264233623Sjhb free(ioapics, M_MADT); 265233623Sjhb ioapics = NULL; 266233623Sjhb 267121992Sjhb return (0); 268121992Sjhb} 269121992Sjhb 270121992Sjhbstatic void 271121992Sjhbmadt_register(void *dummy __unused) 272121992Sjhb{ 273121992Sjhb 274121992Sjhb apic_register_enumerator(&madt_enumerator); 275121992Sjhb} 276215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 277121992Sjhb 278121992Sjhb/* 279121992Sjhb * Call the handler routine for each entry in the MADT table. 280121992Sjhb */ 281121992Sjhbstatic void 282197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg) 283121992Sjhb{ 284121992Sjhb 285197439Sjhb acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 286197439Sjhb handler, arg); 287121992Sjhb} 288121992Sjhb 289121992Sjhbstatic void 290284175Sjhbmadt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags) 291284175Sjhb{ 292284175Sjhb struct lapic_info *la; 293284175Sjhb 294284175Sjhb /* 295284175Sjhb * The MADT does not include a BSP flag, so we have to let the 296284175Sjhb * MP code figure out which CPU is the BSP on its own. 297284175Sjhb */ 298284175Sjhb if (bootverbose) 299284175Sjhb printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 300284175Sjhb apic_id, acpi_id, flags & ACPI_MADT_ENABLED ? 301284175Sjhb "enabled" : "disabled"); 302284175Sjhb if (!(flags & ACPI_MADT_ENABLED)) 303284175Sjhb return; 304284175Sjhb if (apic_id > MAX_APIC_ID) { 305284175Sjhb printf("MADT: Ignoring local APIC ID %u (too high)\n", 306284175Sjhb apic_id); 307284175Sjhb return; 308284175Sjhb } 309284175Sjhb 310284175Sjhb la = &lapics[apic_id]; 311284175Sjhb KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id)); 312284175Sjhb la->la_enabled = 1; 313284175Sjhb la->la_acpi_id = acpi_id; 314284175Sjhb lapic_create(apic_id, 0); 315284175Sjhb} 316284175Sjhb 317284175Sjhbstatic void 318167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 319121992Sjhb{ 320167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 321284175Sjhb ACPI_MADT_LOCAL_X2APIC *x2apic; 322121992Sjhb 323121992Sjhb switch (entry->Type) { 324167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 325167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 326284175Sjhb madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags); 327121992Sjhb break; 328284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC: 329284175Sjhb x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry; 330284175Sjhb madt_add_cpu(x2apic->Uid, x2apic->LocalApicId, 331284175Sjhb x2apic->LapicFlags); 332284175Sjhb break; 333121992Sjhb } 334121992Sjhb} 335121992Sjhb 336121992Sjhb 337121992Sjhb/* 338121992Sjhb * Add an I/O APIC from an entry in the table. 339121992Sjhb */ 340121992Sjhbstatic void 341167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 342121992Sjhb{ 343167814Sjkim ACPI_MADT_IO_APIC *apic; 344121992Sjhb 345121992Sjhb switch (entry->Type) { 346167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 347167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 348121992Sjhb if (bootverbose) 349167814Sjkim printf( 350167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 351167814Sjkim apic->Id, apic->GlobalIrqBase, 352123326Snjl (void *)(uintptr_t)apic->Address); 353169395Sjhb if (apic->Id > MAX_APIC_ID) 354167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 355167814Sjkim apic->Id); 356167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 357167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 358189404Sjhb if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 359189404Sjhb printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 360189404Sjhb break; 361189404Sjhb } 362167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 363167814Sjkim apic->Id, apic->GlobalIrqBase); 364167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 365121992Sjhb break; 366121992Sjhb default: 367121992Sjhb break; 368121992Sjhb } 369121992Sjhb} 370121992Sjhb 371121992Sjhb/* 372129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 373129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 374128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 375129128Sjhb * SCI for which we use Active Lo, Level Triggered. 376121992Sjhb */ 377128930Sjhbstatic enum intr_polarity 378167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 379121992Sjhb{ 380121992Sjhb 381167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 382263859Stakawata default: 383269184Sakiyama printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 384263859Stakawata /* FALLTHROUGH*/ 385167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 386167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 387128930Sjhb return (INTR_POLARITY_LOW); 388128930Sjhb else 389128930Sjhb return (INTR_POLARITY_HIGH); 390167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 391128930Sjhb return (INTR_POLARITY_HIGH); 392167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 393263859Stakawata return (INTR_POLARITY_LOW); 394121992Sjhb } 395121992Sjhb} 396121992Sjhb 397128930Sjhbstatic enum intr_trigger 398167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 399121992Sjhb{ 400121992Sjhb 401167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 402263859Stakawata default: 403269184Sakiyama printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 404263859Stakawata /*FALLTHROUGH*/ 405167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 406167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 407128930Sjhb return (INTR_TRIGGER_LEVEL); 408128930Sjhb else 409128930Sjhb return (INTR_TRIGGER_EDGE); 410167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 411128930Sjhb return (INTR_TRIGGER_EDGE); 412167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 413263859Stakawata return (INTR_TRIGGER_LEVEL); 414121992Sjhb } 415121992Sjhb} 416121992Sjhb 417121992Sjhb/* 418121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 419121992Sjhb */ 420121992Sjhbstatic int 421121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 422121992Sjhb{ 423129960Sjhb int i; 424121992Sjhb 425169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 426130310Sjhb if (!lapics[i].la_enabled) 427129960Sjhb continue; 428129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 429129960Sjhb continue; 430129960Sjhb *apic_id = i; 431130310Sjhb return (0); 432129960Sjhb } 433129960Sjhb return (ENOENT); 434121992Sjhb} 435121992Sjhb 436121992Sjhb/* 437121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 438121992Sjhb * interrupt. 439121992Sjhb */ 440121992Sjhbstatic int 441121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 442121992Sjhb{ 443121992Sjhb int i, best; 444121992Sjhb 445121992Sjhb best = -1; 446169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 447121992Sjhb if (ioapics[i].io_apic == NULL || 448121992Sjhb ioapics[i].io_vector > intr) 449121992Sjhb continue; 450121992Sjhb if (best == -1 || 451121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 452121992Sjhb best = i; 453121992Sjhb } 454121992Sjhb if (best == -1) 455121992Sjhb return (ENOENT); 456121992Sjhb *apic = ioapics[best].io_apic; 457121992Sjhb *pin = intr - ioapics[best].io_vector; 458121992Sjhb if (*pin > 32) 459121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 460121992Sjhb intr); 461121992Sjhb return (0); 462121992Sjhb} 463121992Sjhb 464269512Sroygervoid 465269512Sroygermadt_parse_interrupt_values(void *entry, 466269512Sroyger enum intr_trigger *trig, enum intr_polarity *pol) 467121992Sjhb{ 468269512Sroyger ACPI_MADT_INTERRUPT_OVERRIDE *intr; 469128930Sjhb char buf[64]; 470121992Sjhb 471269512Sroyger intr = entry; 472269512Sroyger 473121992Sjhb if (bootverbose) 474142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 475167814Sjkim intr->SourceIrq, intr->GlobalIrq); 476121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 477121992Sjhb 478125048Sjhb /* 479128930Sjhb * Lookup the appropriate trigger and polarity modes for this 480128930Sjhb * entry. 481128930Sjhb */ 482269512Sroyger *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 483269512Sroyger *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 484269512Sroyger 485128930Sjhb /* 486125048Sjhb * If the SCI is identity mapped but has edge trigger and 487128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 488128329Sjhb * force it to use level/lo. 489125048Sjhb */ 490167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 491128930Sjhb madt_found_sci_override = 1; 492128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 493128930Sjhb if (tolower(buf[0]) == 'e') 494269512Sroyger *trig = INTR_TRIGGER_EDGE; 495128930Sjhb else if (tolower(buf[0]) == 'l') 496269512Sroyger *trig = INTR_TRIGGER_LEVEL; 497128930Sjhb else 498128930Sjhb panic( 499128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 500128930Sjhb buf); 501128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 502269512Sroyger *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 503128930Sjhb } 504128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 505128930Sjhb if (tolower(buf[0]) == 'h') 506269512Sroyger *pol = INTR_POLARITY_HIGH; 507128930Sjhb else if (tolower(buf[0]) == 'l') 508269512Sroyger *pol = INTR_POLARITY_LOW; 509128930Sjhb else 510128930Sjhb panic( 511128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 512128930Sjhb buf); 513128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 514269512Sroyger *pol == INTR_POLARITY_HIGH ? "high" : "low"); 515128930Sjhb } 516128930Sjhb } 517269512Sroyger} 518125048Sjhb 519269512Sroyger/* 520269512Sroyger * Parse an interrupt source override for an ISA interrupt. 521269512Sroyger */ 522269512Sroygerstatic void 523269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 524269512Sroyger{ 525269512Sroyger void *new_ioapic, *old_ioapic; 526269512Sroyger u_int new_pin, old_pin; 527269512Sroyger enum intr_trigger trig; 528269512Sroyger enum intr_polarity pol; 529269512Sroyger 530269512Sroyger if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 531269512Sroyger intr->GlobalIrq == 2) { 532269512Sroyger if (bootverbose) 533269512Sroyger printf("MADT: Skipping timer override\n"); 534269512Sroyger return; 535269512Sroyger } 536269512Sroyger 537269512Sroyger if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 538269512Sroyger printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 539269512Sroyger intr->GlobalIrq, intr->SourceIrq); 540269512Sroyger return; 541269512Sroyger } 542269512Sroyger 543269512Sroyger madt_parse_interrupt_values(intr, &trig, &pol); 544269512Sroyger 545128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 546167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 547125048Sjhb /* 548125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 549125048Sjhb * then override the vector we use to setup and allocate 550125048Sjhb * the interrupt. 551125048Sjhb */ 552167814Sjkim if (intr->GlobalIrq > 15 && 553167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 554167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 555122502Sjhb else 556167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 557167814Sjkim intr->SourceIrq); 558167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 559122149Sjhb &old_pin) != 0) 560167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 561167814Sjkim intr->SourceIrq); 562122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 563167814Sjkim intr->SourceIrq) 564122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 565122149Sjhb } 566128930Sjhb 567128930Sjhb /* Program the polarity and trigger mode. */ 568128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 569128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 570121992Sjhb} 571121992Sjhb 572121992Sjhb/* 573121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 574121992Sjhb */ 575121992Sjhbstatic void 576167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 577121992Sjhb{ 578121992Sjhb void *ioapic; 579121992Sjhb u_int pin; 580121992Sjhb 581167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 582167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 583167814Sjkim nmi->GlobalIrq); 584121992Sjhb return; 585121992Sjhb } 586121992Sjhb 587121992Sjhb ioapic_set_nmi(ioapic, pin); 588167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 589121992Sjhb ioapic_set_triggermode(ioapic, pin, 590167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 591263794Stakawata if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 592121992Sjhb ioapic_set_polarity(ioapic, pin, 593167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 594121992Sjhb} 595121992Sjhb 596121992Sjhb/* 597121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 598121992Sjhb */ 599121992Sjhbstatic void 600284175Sjhbmadt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags) 601121992Sjhb{ 602121992Sjhb u_int apic_id, pin; 603121992Sjhb 604284175Sjhb if (acpi_id == 0xffffffff) 605121992Sjhb apic_id = APIC_ID_ALL; 606284175Sjhb else if (madt_find_cpu(acpi_id, &apic_id) != 0) { 607121992Sjhb if (bootverbose) 608167814Sjkim printf("MADT: Ignoring local NMI routed to " 609284175Sjhb "ACPI CPU %u\n", acpi_id); 610121992Sjhb return; 611121992Sjhb } 612284175Sjhb if (Lint == 0) 613259140Sjhb pin = APIC_LVT_LINT0; 614121992Sjhb else 615259140Sjhb pin = APIC_LVT_LINT1; 616121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 617284175Sjhb if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 618121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 619284175Sjhb interrupt_trigger(IntiFlags, 0)); 620284175Sjhb if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 621121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 622284175Sjhb interrupt_polarity(IntiFlags, 0)); 623121992Sjhb} 624121992Sjhb 625284175Sjhbstatic void 626284175Sjhbmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 627284175Sjhb{ 628284175Sjhb 629284175Sjhb madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff : 630284175Sjhb nmi->ProcessorId, nmi->Lint, nmi->IntiFlags); 631284175Sjhb} 632284175Sjhb 633284175Sjhbstatic void 634284175Sjhbmadt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi) 635284175Sjhb{ 636284175Sjhb 637284175Sjhb madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags); 638284175Sjhb} 639284175Sjhb 640121992Sjhb/* 641121992Sjhb * Parse interrupt entries. 642121992Sjhb */ 643121992Sjhbstatic void 644167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 645121992Sjhb{ 646121992Sjhb 647121992Sjhb switch (entry->Type) { 648167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 649121992Sjhb madt_parse_interrupt_override( 650167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 651121992Sjhb break; 652167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 653167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 654121992Sjhb break; 655167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 656167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 657121992Sjhb break; 658284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 659284175Sjhb madt_parse_local_x2apic_nmi( 660284175Sjhb (ACPI_MADT_LOCAL_X2APIC_NMI *)entry); 661284175Sjhb break; 662121992Sjhb } 663121992Sjhb} 664121992Sjhb 665121992Sjhb/* 666121992Sjhb * Setup per-CPU ACPI IDs. 667121992Sjhb */ 668121992Sjhbstatic void 669121992Sjhbmadt_set_ids(void *dummy) 670121992Sjhb{ 671129960Sjhb struct lapic_info *la; 672121992Sjhb struct pcpu *pc; 673129960Sjhb u_int i; 674121992Sjhb 675121992Sjhb if (madt == NULL) 676121992Sjhb return; 677209059Sjhb CPU_FOREACH(i) { 678121992Sjhb pc = pcpu_find(i); 679167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 680129960Sjhb la = &lapics[pc->pc_apic_id]; 681130310Sjhb if (!la->la_enabled) 682129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 683129960Sjhb pc->pc_apic_id); 684129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 685129960Sjhb if (bootverbose) 686129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 687129960Sjhb la->la_acpi_id); 688121992Sjhb } 689121992Sjhb} 690256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 691