madt.c revision 286994
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 286994 2015-08-21 15:13:25Z 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"; 169286994Skib } else if (vm_guest == VM_GUEST_NO) { 170286994Skib hw_vendor = kern_getenv("smbios.planar.maker"); 171286994Skib /* 172286994Skib * It seems that some Lenovo SandyBridge-based 173286994Skib * notebook BIOSes have a bug which prevents 174286994Skib * booting AP in x2APIC mode. Since the only 175286994Skib * way to detect mobile CPU is to check 176286994Skib * northbridge pci id, which cannot be done 177286994Skib * that early, disable x2APIC for all Lenovo 178286994Skib * SandyBridge machines. 179286994Skib */ 180286994Skib if (hw_vendor != NULL && 181286994Skib !strcmp(hw_vendor, "LENOVO") && 182286994Skib CPUID_TO_FAMILY(cpu_id) == 0x6 && 183286994Skib CPUID_TO_MODEL(cpu_id) == 0x2a) { 184286994Skib x2apic_mode = 0; 185286994Skib reason = "for a suspected Lenovo SandyBridge BIOS bug"; 186286994Skib } 187286994Skib freeenv(hw_vendor); 188278749Skib } 189278473Skib TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode); 190286994Skib if (!x2apic_mode && reason != NULL && bootverbose) 191286994Skib printf("x2APIC available but disabled %s\n", reason); 192278473Skib } 193278473Skib 194167814Sjkim lapic_init(madt->Address); 195121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 196167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 197167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 198121992Sjhb 199121992Sjhb /* 200121992Sjhb * We ignore 64-bit local APIC override entries. Should we 201121992Sjhb * perhaps emit a warning here if we find one? 202121992Sjhb */ 203121992Sjhb return (0); 204121992Sjhb} 205121992Sjhb 206121992Sjhb/* 207125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 208121992Sjhb */ 209121992Sjhbstatic int 210121992Sjhbmadt_setup_io(void) 211121992Sjhb{ 212128930Sjhb void *ioapic; 213128930Sjhb u_int pin; 214121992Sjhb int i; 215121992Sjhb 216125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 217125048Sjhb i = acpi_Startup(); 218125048Sjhb if (ACPI_FAILURE(i)) { 219125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 220125048Sjhb AcpiFormatException(i)); 221125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 222125048Sjhb panic("Using MADT but ACPI doesn't work"); 223125048Sjhb } 224233623Sjhb 225233623Sjhb ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 226233623Sjhb M_WAITOK | M_ZERO); 227233623Sjhb 228121992Sjhb /* First, we run through adding I/O APIC's. */ 229121992Sjhb madt_walk_table(madt_parse_apics, NULL); 230121992Sjhb 231121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 232121992Sjhb madt_walk_table(madt_parse_ints, NULL); 233121992Sjhb 234128930Sjhb /* 235128930Sjhb * If there was not an explicit override entry for the SCI, 236128930Sjhb * force it to use level trigger and active-low polarity. 237128930Sjhb */ 238128930Sjhb if (!madt_found_sci_override) { 239167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 240167814Sjkim &pin) != 0) 241167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 242167814Sjkim AcpiGbl_FADT.SciInterrupt); 243128930Sjhb else { 244128930Sjhb printf( 245128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 246128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 247128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 248128930Sjhb } 249128930Sjhb } 250128930Sjhb 251121992Sjhb /* Third, we register all the I/O APIC's. */ 252169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 253121992Sjhb if (ioapics[i].io_apic != NULL) 254121992Sjhb ioapic_register(ioapics[i].io_apic); 255121992Sjhb 256121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 257121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 258121992Sjhb 259233623Sjhb free(ioapics, M_MADT); 260233623Sjhb ioapics = NULL; 261233623Sjhb 262121992Sjhb return (0); 263121992Sjhb} 264121992Sjhb 265121992Sjhbstatic void 266121992Sjhbmadt_register(void *dummy __unused) 267121992Sjhb{ 268121992Sjhb 269121992Sjhb apic_register_enumerator(&madt_enumerator); 270121992Sjhb} 271215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 272121992Sjhb 273121992Sjhb/* 274121992Sjhb * Call the handler routine for each entry in the MADT table. 275121992Sjhb */ 276121992Sjhbstatic void 277197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg) 278121992Sjhb{ 279121992Sjhb 280197439Sjhb acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 281197439Sjhb handler, arg); 282121992Sjhb} 283121992Sjhb 284121992Sjhbstatic void 285284175Sjhbmadt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags) 286284175Sjhb{ 287284175Sjhb struct lapic_info *la; 288284175Sjhb 289284175Sjhb /* 290284175Sjhb * The MADT does not include a BSP flag, so we have to let the 291284175Sjhb * MP code figure out which CPU is the BSP on its own. 292284175Sjhb */ 293284175Sjhb if (bootverbose) 294284175Sjhb printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 295284175Sjhb apic_id, acpi_id, flags & ACPI_MADT_ENABLED ? 296284175Sjhb "enabled" : "disabled"); 297284175Sjhb if (!(flags & ACPI_MADT_ENABLED)) 298284175Sjhb return; 299284175Sjhb if (apic_id > MAX_APIC_ID) { 300284175Sjhb printf("MADT: Ignoring local APIC ID %u (too high)\n", 301284175Sjhb apic_id); 302284175Sjhb return; 303284175Sjhb } 304284175Sjhb 305284175Sjhb la = &lapics[apic_id]; 306284175Sjhb KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id)); 307284175Sjhb la->la_enabled = 1; 308284175Sjhb la->la_acpi_id = acpi_id; 309284175Sjhb lapic_create(apic_id, 0); 310284175Sjhb} 311284175Sjhb 312284175Sjhbstatic void 313167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 314121992Sjhb{ 315167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 316284175Sjhb ACPI_MADT_LOCAL_X2APIC *x2apic; 317121992Sjhb 318121992Sjhb switch (entry->Type) { 319167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 320167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 321284175Sjhb madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags); 322121992Sjhb break; 323284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC: 324284175Sjhb x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry; 325284175Sjhb madt_add_cpu(x2apic->Uid, x2apic->LocalApicId, 326284175Sjhb x2apic->LapicFlags); 327284175Sjhb break; 328121992Sjhb } 329121992Sjhb} 330121992Sjhb 331121992Sjhb 332121992Sjhb/* 333121992Sjhb * Add an I/O APIC from an entry in the table. 334121992Sjhb */ 335121992Sjhbstatic void 336167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 337121992Sjhb{ 338167814Sjkim ACPI_MADT_IO_APIC *apic; 339121992Sjhb 340121992Sjhb switch (entry->Type) { 341167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 342167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 343121992Sjhb if (bootverbose) 344167814Sjkim printf( 345167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 346167814Sjkim apic->Id, apic->GlobalIrqBase, 347123326Snjl (void *)(uintptr_t)apic->Address); 348169395Sjhb if (apic->Id > MAX_APIC_ID) 349167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 350167814Sjkim apic->Id); 351167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 352167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 353189404Sjhb if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 354189404Sjhb printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 355189404Sjhb break; 356189404Sjhb } 357167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 358167814Sjkim apic->Id, apic->GlobalIrqBase); 359167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 360121992Sjhb break; 361121992Sjhb default: 362121992Sjhb break; 363121992Sjhb } 364121992Sjhb} 365121992Sjhb 366121992Sjhb/* 367129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 368129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 369128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 370129128Sjhb * SCI for which we use Active Lo, Level Triggered. 371121992Sjhb */ 372128930Sjhbstatic enum intr_polarity 373167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 374121992Sjhb{ 375121992Sjhb 376167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 377263859Stakawata default: 378269184Sakiyama printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 379263859Stakawata /* FALLTHROUGH*/ 380167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 381167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 382128930Sjhb return (INTR_POLARITY_LOW); 383128930Sjhb else 384128930Sjhb return (INTR_POLARITY_HIGH); 385167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 386128930Sjhb return (INTR_POLARITY_HIGH); 387167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 388263859Stakawata return (INTR_POLARITY_LOW); 389121992Sjhb } 390121992Sjhb} 391121992Sjhb 392128930Sjhbstatic enum intr_trigger 393167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 394121992Sjhb{ 395121992Sjhb 396167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 397263859Stakawata default: 398269184Sakiyama printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 399263859Stakawata /*FALLTHROUGH*/ 400167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 401167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 402128930Sjhb return (INTR_TRIGGER_LEVEL); 403128930Sjhb else 404128930Sjhb return (INTR_TRIGGER_EDGE); 405167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 406128930Sjhb return (INTR_TRIGGER_EDGE); 407167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 408263859Stakawata return (INTR_TRIGGER_LEVEL); 409121992Sjhb } 410121992Sjhb} 411121992Sjhb 412121992Sjhb/* 413121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 414121992Sjhb */ 415121992Sjhbstatic int 416121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 417121992Sjhb{ 418129960Sjhb int i; 419121992Sjhb 420169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 421130310Sjhb if (!lapics[i].la_enabled) 422129960Sjhb continue; 423129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 424129960Sjhb continue; 425129960Sjhb *apic_id = i; 426130310Sjhb return (0); 427129960Sjhb } 428129960Sjhb return (ENOENT); 429121992Sjhb} 430121992Sjhb 431121992Sjhb/* 432121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 433121992Sjhb * interrupt. 434121992Sjhb */ 435121992Sjhbstatic int 436121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 437121992Sjhb{ 438121992Sjhb int i, best; 439121992Sjhb 440121992Sjhb best = -1; 441169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 442121992Sjhb if (ioapics[i].io_apic == NULL || 443121992Sjhb ioapics[i].io_vector > intr) 444121992Sjhb continue; 445121992Sjhb if (best == -1 || 446121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 447121992Sjhb best = i; 448121992Sjhb } 449121992Sjhb if (best == -1) 450121992Sjhb return (ENOENT); 451121992Sjhb *apic = ioapics[best].io_apic; 452121992Sjhb *pin = intr - ioapics[best].io_vector; 453121992Sjhb if (*pin > 32) 454121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 455121992Sjhb intr); 456121992Sjhb return (0); 457121992Sjhb} 458121992Sjhb 459269512Sroygervoid 460269512Sroygermadt_parse_interrupt_values(void *entry, 461269512Sroyger enum intr_trigger *trig, enum intr_polarity *pol) 462121992Sjhb{ 463269512Sroyger ACPI_MADT_INTERRUPT_OVERRIDE *intr; 464128930Sjhb char buf[64]; 465121992Sjhb 466269512Sroyger intr = entry; 467269512Sroyger 468121992Sjhb if (bootverbose) 469142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 470167814Sjkim intr->SourceIrq, intr->GlobalIrq); 471121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 472121992Sjhb 473125048Sjhb /* 474128930Sjhb * Lookup the appropriate trigger and polarity modes for this 475128930Sjhb * entry. 476128930Sjhb */ 477269512Sroyger *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 478269512Sroyger *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 479269512Sroyger 480128930Sjhb /* 481125048Sjhb * If the SCI is identity mapped but has edge trigger and 482128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 483128329Sjhb * force it to use level/lo. 484125048Sjhb */ 485167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 486128930Sjhb madt_found_sci_override = 1; 487128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 488128930Sjhb if (tolower(buf[0]) == 'e') 489269512Sroyger *trig = INTR_TRIGGER_EDGE; 490128930Sjhb else if (tolower(buf[0]) == 'l') 491269512Sroyger *trig = INTR_TRIGGER_LEVEL; 492128930Sjhb else 493128930Sjhb panic( 494128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 495128930Sjhb buf); 496128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 497269512Sroyger *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 498128930Sjhb } 499128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 500128930Sjhb if (tolower(buf[0]) == 'h') 501269512Sroyger *pol = INTR_POLARITY_HIGH; 502128930Sjhb else if (tolower(buf[0]) == 'l') 503269512Sroyger *pol = INTR_POLARITY_LOW; 504128930Sjhb else 505128930Sjhb panic( 506128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 507128930Sjhb buf); 508128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 509269512Sroyger *pol == INTR_POLARITY_HIGH ? "high" : "low"); 510128930Sjhb } 511128930Sjhb } 512269512Sroyger} 513125048Sjhb 514269512Sroyger/* 515269512Sroyger * Parse an interrupt source override for an ISA interrupt. 516269512Sroyger */ 517269512Sroygerstatic void 518269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 519269512Sroyger{ 520269512Sroyger void *new_ioapic, *old_ioapic; 521269512Sroyger u_int new_pin, old_pin; 522269512Sroyger enum intr_trigger trig; 523269512Sroyger enum intr_polarity pol; 524269512Sroyger 525269512Sroyger if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 526269512Sroyger intr->GlobalIrq == 2) { 527269512Sroyger if (bootverbose) 528269512Sroyger printf("MADT: Skipping timer override\n"); 529269512Sroyger return; 530269512Sroyger } 531269512Sroyger 532269512Sroyger if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 533269512Sroyger printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 534269512Sroyger intr->GlobalIrq, intr->SourceIrq); 535269512Sroyger return; 536269512Sroyger } 537269512Sroyger 538269512Sroyger madt_parse_interrupt_values(intr, &trig, &pol); 539269512Sroyger 540128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 541167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 542125048Sjhb /* 543125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 544125048Sjhb * then override the vector we use to setup and allocate 545125048Sjhb * the interrupt. 546125048Sjhb */ 547167814Sjkim if (intr->GlobalIrq > 15 && 548167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 549167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 550122502Sjhb else 551167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 552167814Sjkim intr->SourceIrq); 553167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 554122149Sjhb &old_pin) != 0) 555167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 556167814Sjkim intr->SourceIrq); 557122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 558167814Sjkim intr->SourceIrq) 559122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 560122149Sjhb } 561128930Sjhb 562128930Sjhb /* Program the polarity and trigger mode. */ 563128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 564128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 565121992Sjhb} 566121992Sjhb 567121992Sjhb/* 568121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 569121992Sjhb */ 570121992Sjhbstatic void 571167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 572121992Sjhb{ 573121992Sjhb void *ioapic; 574121992Sjhb u_int pin; 575121992Sjhb 576167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 577167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 578167814Sjkim nmi->GlobalIrq); 579121992Sjhb return; 580121992Sjhb } 581121992Sjhb 582121992Sjhb ioapic_set_nmi(ioapic, pin); 583167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 584121992Sjhb ioapic_set_triggermode(ioapic, pin, 585167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 586263794Stakawata if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 587121992Sjhb ioapic_set_polarity(ioapic, pin, 588167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 589121992Sjhb} 590121992Sjhb 591121992Sjhb/* 592121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 593121992Sjhb */ 594121992Sjhbstatic void 595284175Sjhbmadt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags) 596121992Sjhb{ 597121992Sjhb u_int apic_id, pin; 598121992Sjhb 599284175Sjhb if (acpi_id == 0xffffffff) 600121992Sjhb apic_id = APIC_ID_ALL; 601284175Sjhb else if (madt_find_cpu(acpi_id, &apic_id) != 0) { 602121992Sjhb if (bootverbose) 603167814Sjkim printf("MADT: Ignoring local NMI routed to " 604284175Sjhb "ACPI CPU %u\n", acpi_id); 605121992Sjhb return; 606121992Sjhb } 607284175Sjhb if (Lint == 0) 608259140Sjhb pin = APIC_LVT_LINT0; 609121992Sjhb else 610259140Sjhb pin = APIC_LVT_LINT1; 611121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 612284175Sjhb if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 613121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 614284175Sjhb interrupt_trigger(IntiFlags, 0)); 615284175Sjhb if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 616121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 617284175Sjhb interrupt_polarity(IntiFlags, 0)); 618121992Sjhb} 619121992Sjhb 620284175Sjhbstatic void 621284175Sjhbmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 622284175Sjhb{ 623284175Sjhb 624284175Sjhb madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff : 625284175Sjhb nmi->ProcessorId, nmi->Lint, nmi->IntiFlags); 626284175Sjhb} 627284175Sjhb 628284175Sjhbstatic void 629284175Sjhbmadt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi) 630284175Sjhb{ 631284175Sjhb 632284175Sjhb madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags); 633284175Sjhb} 634284175Sjhb 635121992Sjhb/* 636121992Sjhb * Parse interrupt entries. 637121992Sjhb */ 638121992Sjhbstatic void 639167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 640121992Sjhb{ 641121992Sjhb 642121992Sjhb switch (entry->Type) { 643167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 644121992Sjhb madt_parse_interrupt_override( 645167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 646121992Sjhb break; 647167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 648167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 649121992Sjhb break; 650167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 651167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 652121992Sjhb break; 653284175Sjhb case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 654284175Sjhb madt_parse_local_x2apic_nmi( 655284175Sjhb (ACPI_MADT_LOCAL_X2APIC_NMI *)entry); 656284175Sjhb break; 657121992Sjhb } 658121992Sjhb} 659121992Sjhb 660121992Sjhb/* 661121992Sjhb * Setup per-CPU ACPI IDs. 662121992Sjhb */ 663121992Sjhbstatic void 664121992Sjhbmadt_set_ids(void *dummy) 665121992Sjhb{ 666129960Sjhb struct lapic_info *la; 667121992Sjhb struct pcpu *pc; 668129960Sjhb u_int i; 669121992Sjhb 670121992Sjhb if (madt == NULL) 671121992Sjhb return; 672209059Sjhb CPU_FOREACH(i) { 673121992Sjhb pc = pcpu_find(i); 674167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 675129960Sjhb la = &lapics[pc->pc_apic_id]; 676130310Sjhb if (!la->la_enabled) 677129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 678129960Sjhb pc->pc_apic_id); 679129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 680129960Sjhb if (bootverbose) 681129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 682129960Sjhb la->la_acpi_id); 683121992Sjhb } 684121992Sjhb} 685256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 686