madt.c revision 279286
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 279286 2015-02-25 16:44:07Z 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 { 59121992Sjhb u_int la_enabled:1; 60129960Sjhb u_int la_acpi_id:8; 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; 135278749Skib u_int p[4]; 136121992Sjhb 137161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 138278473Skib if ((cpu_feature2 & CPUID2_X2APIC) != 0) { 139278473Skib x2apic_mode = 1; 140278473Skib dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR); 141278473Skib if (dmartbl_physaddr != 0) { 142278473Skib dmartbl = acpi_map_table(dmartbl_physaddr, 143278473Skib ACPI_SIG_DMAR); 144278473Skib if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) { 145278473Skib x2apic_mode = 0; 146278473Skib if (bootverbose) 147278473Skib printf( 148278473Skib "x2APIC available but disabled by DMAR table\n"); 149278473Skib } 150278473Skib acpi_unmap_table(dmartbl); 151278473Skib } 152278749Skib if (vm_guest == VM_GUEST_VMWARE) { 153278749Skib vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p); 154278749Skib if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 || 155278749Skib (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) { 156278749Skib x2apic_mode = 0; 157278749Skib if (bootverbose) 158278749Skib printf( 159278749Skib "x2APIC available but disabled inside VMWare without intr redirection\n"); 160278749Skib } 161279286Skib } else if (vm_guest == VM_GUEST_XEN) { 162279286Skib x2apic_mode = 0; 163278749Skib } 164278473Skib TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode); 165278473Skib } 166278473Skib 167167814Sjkim lapic_init(madt->Address); 168121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 169167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 170167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 171121992Sjhb 172121992Sjhb /* 173121992Sjhb * We ignore 64-bit local APIC override entries. Should we 174121992Sjhb * perhaps emit a warning here if we find one? 175121992Sjhb */ 176121992Sjhb return (0); 177121992Sjhb} 178121992Sjhb 179121992Sjhb/* 180125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 181121992Sjhb */ 182121992Sjhbstatic int 183121992Sjhbmadt_setup_io(void) 184121992Sjhb{ 185128930Sjhb void *ioapic; 186128930Sjhb u_int pin; 187121992Sjhb int i; 188121992Sjhb 189125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 190125048Sjhb i = acpi_Startup(); 191125048Sjhb if (ACPI_FAILURE(i)) { 192125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 193125048Sjhb AcpiFormatException(i)); 194125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 195125048Sjhb panic("Using MADT but ACPI doesn't work"); 196125048Sjhb } 197233623Sjhb 198233623Sjhb ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT, 199233623Sjhb M_WAITOK | M_ZERO); 200233623Sjhb 201121992Sjhb /* First, we run through adding I/O APIC's. */ 202121992Sjhb madt_walk_table(madt_parse_apics, NULL); 203121992Sjhb 204121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 205121992Sjhb madt_walk_table(madt_parse_ints, NULL); 206121992Sjhb 207128930Sjhb /* 208128930Sjhb * If there was not an explicit override entry for the SCI, 209128930Sjhb * force it to use level trigger and active-low polarity. 210128930Sjhb */ 211128930Sjhb if (!madt_found_sci_override) { 212167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 213167814Sjkim &pin) != 0) 214167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 215167814Sjkim AcpiGbl_FADT.SciInterrupt); 216128930Sjhb else { 217128930Sjhb printf( 218128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 219128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 220128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 221128930Sjhb } 222128930Sjhb } 223128930Sjhb 224121992Sjhb /* Third, we register all the I/O APIC's. */ 225169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 226121992Sjhb if (ioapics[i].io_apic != NULL) 227121992Sjhb ioapic_register(ioapics[i].io_apic); 228121992Sjhb 229121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 230121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 231121992Sjhb 232233623Sjhb free(ioapics, M_MADT); 233233623Sjhb ioapics = NULL; 234233623Sjhb 235121992Sjhb return (0); 236121992Sjhb} 237121992Sjhb 238121992Sjhbstatic void 239121992Sjhbmadt_register(void *dummy __unused) 240121992Sjhb{ 241121992Sjhb 242121992Sjhb apic_register_enumerator(&madt_enumerator); 243121992Sjhb} 244215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 245121992Sjhb 246121992Sjhb/* 247121992Sjhb * Call the handler routine for each entry in the MADT table. 248121992Sjhb */ 249121992Sjhbstatic void 250197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg) 251121992Sjhb{ 252121992Sjhb 253197439Sjhb acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 254197439Sjhb handler, arg); 255121992Sjhb} 256121992Sjhb 257121992Sjhbstatic void 258167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 259121992Sjhb{ 260167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 261121992Sjhb struct lapic_info *la; 262121992Sjhb 263121992Sjhb switch (entry->Type) { 264167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 265121992Sjhb /* 266121992Sjhb * The MADT does not include a BSP flag, so we have to 267121992Sjhb * let the MP code figure out which CPU is the BSP on 268121992Sjhb * its own. 269121992Sjhb */ 270167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 271121992Sjhb if (bootverbose) 272167814Sjkim printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 273167814Sjkim proc->Id, proc->ProcessorId, 274167814Sjkim (proc->LapicFlags & ACPI_MADT_ENABLED) ? 275167814Sjkim "enabled" : "disabled"); 276167814Sjkim if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 277130310Sjhb break; 278169395Sjhb if (proc->Id > MAX_APIC_ID) 279167814Sjkim panic("%s: CPU ID %u too high", __func__, proc->Id); 280167814Sjkim la = &lapics[proc->Id]; 281130310Sjhb KASSERT(la->la_enabled == 0, 282167814Sjkim ("Duplicate local APIC ID %u", proc->Id)); 283130310Sjhb la->la_enabled = 1; 284129960Sjhb la->la_acpi_id = proc->ProcessorId; 285167814Sjkim lapic_create(proc->Id, 0); 286121992Sjhb break; 287121992Sjhb } 288121992Sjhb} 289121992Sjhb 290121992Sjhb 291121992Sjhb/* 292121992Sjhb * Add an I/O APIC from an entry in the table. 293121992Sjhb */ 294121992Sjhbstatic void 295167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 296121992Sjhb{ 297167814Sjkim ACPI_MADT_IO_APIC *apic; 298121992Sjhb 299121992Sjhb switch (entry->Type) { 300167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 301167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 302121992Sjhb if (bootverbose) 303167814Sjkim printf( 304167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 305167814Sjkim apic->Id, apic->GlobalIrqBase, 306123326Snjl (void *)(uintptr_t)apic->Address); 307169395Sjhb if (apic->Id > MAX_APIC_ID) 308167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 309167814Sjkim apic->Id); 310167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 311167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 312189404Sjhb if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 313189404Sjhb printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 314189404Sjhb break; 315189404Sjhb } 316167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 317167814Sjkim apic->Id, apic->GlobalIrqBase); 318167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 319121992Sjhb break; 320121992Sjhb default: 321121992Sjhb break; 322121992Sjhb } 323121992Sjhb} 324121992Sjhb 325121992Sjhb/* 326129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 327129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 328128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 329129128Sjhb * SCI for which we use Active Lo, Level Triggered. 330121992Sjhb */ 331128930Sjhbstatic enum intr_polarity 332167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 333121992Sjhb{ 334121992Sjhb 335167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 336263859Stakawata default: 337269184Sakiyama printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n"); 338263859Stakawata /* FALLTHROUGH*/ 339167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 340167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 341128930Sjhb return (INTR_POLARITY_LOW); 342128930Sjhb else 343128930Sjhb return (INTR_POLARITY_HIGH); 344167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 345128930Sjhb return (INTR_POLARITY_HIGH); 346167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 347263859Stakawata return (INTR_POLARITY_LOW); 348121992Sjhb } 349121992Sjhb} 350121992Sjhb 351128930Sjhbstatic enum intr_trigger 352167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 353121992Sjhb{ 354121992Sjhb 355167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 356263859Stakawata default: 357269184Sakiyama printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n"); 358263859Stakawata /*FALLTHROUGH*/ 359167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 360167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 361128930Sjhb return (INTR_TRIGGER_LEVEL); 362128930Sjhb else 363128930Sjhb return (INTR_TRIGGER_EDGE); 364167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 365128930Sjhb return (INTR_TRIGGER_EDGE); 366167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 367263859Stakawata return (INTR_TRIGGER_LEVEL); 368121992Sjhb } 369121992Sjhb} 370121992Sjhb 371121992Sjhb/* 372121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 373121992Sjhb */ 374121992Sjhbstatic int 375121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 376121992Sjhb{ 377129960Sjhb int i; 378121992Sjhb 379169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 380130310Sjhb if (!lapics[i].la_enabled) 381129960Sjhb continue; 382129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 383129960Sjhb continue; 384129960Sjhb *apic_id = i; 385130310Sjhb return (0); 386129960Sjhb } 387129960Sjhb return (ENOENT); 388121992Sjhb} 389121992Sjhb 390121992Sjhb/* 391121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 392121992Sjhb * interrupt. 393121992Sjhb */ 394121992Sjhbstatic int 395121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 396121992Sjhb{ 397121992Sjhb int i, best; 398121992Sjhb 399121992Sjhb best = -1; 400169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 401121992Sjhb if (ioapics[i].io_apic == NULL || 402121992Sjhb ioapics[i].io_vector > intr) 403121992Sjhb continue; 404121992Sjhb if (best == -1 || 405121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 406121992Sjhb best = i; 407121992Sjhb } 408121992Sjhb if (best == -1) 409121992Sjhb return (ENOENT); 410121992Sjhb *apic = ioapics[best].io_apic; 411121992Sjhb *pin = intr - ioapics[best].io_vector; 412121992Sjhb if (*pin > 32) 413121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 414121992Sjhb intr); 415121992Sjhb return (0); 416121992Sjhb} 417121992Sjhb 418269512Sroygervoid 419269512Sroygermadt_parse_interrupt_values(void *entry, 420269512Sroyger enum intr_trigger *trig, enum intr_polarity *pol) 421121992Sjhb{ 422269512Sroyger ACPI_MADT_INTERRUPT_OVERRIDE *intr; 423128930Sjhb char buf[64]; 424121992Sjhb 425269512Sroyger intr = entry; 426269512Sroyger 427121992Sjhb if (bootverbose) 428142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 429167814Sjkim intr->SourceIrq, intr->GlobalIrq); 430121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 431121992Sjhb 432125048Sjhb /* 433128930Sjhb * Lookup the appropriate trigger and polarity modes for this 434128930Sjhb * entry. 435128930Sjhb */ 436269512Sroyger *trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 437269512Sroyger *pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 438269512Sroyger 439128930Sjhb /* 440125048Sjhb * If the SCI is identity mapped but has edge trigger and 441128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 442128329Sjhb * force it to use level/lo. 443125048Sjhb */ 444167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 445128930Sjhb madt_found_sci_override = 1; 446128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 447128930Sjhb if (tolower(buf[0]) == 'e') 448269512Sroyger *trig = INTR_TRIGGER_EDGE; 449128930Sjhb else if (tolower(buf[0]) == 'l') 450269512Sroyger *trig = INTR_TRIGGER_LEVEL; 451128930Sjhb else 452128930Sjhb panic( 453128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 454128930Sjhb buf); 455128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 456269512Sroyger *trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 457128930Sjhb } 458128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 459128930Sjhb if (tolower(buf[0]) == 'h') 460269512Sroyger *pol = INTR_POLARITY_HIGH; 461128930Sjhb else if (tolower(buf[0]) == 'l') 462269512Sroyger *pol = INTR_POLARITY_LOW; 463128930Sjhb else 464128930Sjhb panic( 465128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 466128930Sjhb buf); 467128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 468269512Sroyger *pol == INTR_POLARITY_HIGH ? "high" : "low"); 469128930Sjhb } 470128930Sjhb } 471269512Sroyger} 472125048Sjhb 473269512Sroyger/* 474269512Sroyger * Parse an interrupt source override for an ISA interrupt. 475269512Sroyger */ 476269512Sroygerstatic void 477269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 478269512Sroyger{ 479269512Sroyger void *new_ioapic, *old_ioapic; 480269512Sroyger u_int new_pin, old_pin; 481269512Sroyger enum intr_trigger trig; 482269512Sroyger enum intr_polarity pol; 483269512Sroyger 484269512Sroyger if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 485269512Sroyger intr->GlobalIrq == 2) { 486269512Sroyger if (bootverbose) 487269512Sroyger printf("MADT: Skipping timer override\n"); 488269512Sroyger return; 489269512Sroyger } 490269512Sroyger 491269512Sroyger if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 492269512Sroyger printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 493269512Sroyger intr->GlobalIrq, intr->SourceIrq); 494269512Sroyger return; 495269512Sroyger } 496269512Sroyger 497269512Sroyger madt_parse_interrupt_values(intr, &trig, &pol); 498269512Sroyger 499128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 500167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 501125048Sjhb /* 502125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 503125048Sjhb * then override the vector we use to setup and allocate 504125048Sjhb * the interrupt. 505125048Sjhb */ 506167814Sjkim if (intr->GlobalIrq > 15 && 507167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 508167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 509122502Sjhb else 510167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 511167814Sjkim intr->SourceIrq); 512167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 513122149Sjhb &old_pin) != 0) 514167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 515167814Sjkim intr->SourceIrq); 516122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 517167814Sjkim intr->SourceIrq) 518122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 519122149Sjhb } 520128930Sjhb 521128930Sjhb /* Program the polarity and trigger mode. */ 522128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 523128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 524121992Sjhb} 525121992Sjhb 526121992Sjhb/* 527121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 528121992Sjhb */ 529121992Sjhbstatic void 530167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 531121992Sjhb{ 532121992Sjhb void *ioapic; 533121992Sjhb u_int pin; 534121992Sjhb 535167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 536167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 537167814Sjkim nmi->GlobalIrq); 538121992Sjhb return; 539121992Sjhb } 540121992Sjhb 541121992Sjhb ioapic_set_nmi(ioapic, pin); 542167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 543121992Sjhb ioapic_set_triggermode(ioapic, pin, 544167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 545263794Stakawata if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 546121992Sjhb ioapic_set_polarity(ioapic, pin, 547167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 548121992Sjhb} 549121992Sjhb 550121992Sjhb/* 551121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 552121992Sjhb */ 553121992Sjhbstatic void 554167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 555121992Sjhb{ 556121992Sjhb u_int apic_id, pin; 557121992Sjhb 558123326Snjl if (nmi->ProcessorId == 0xff) 559121992Sjhb apic_id = APIC_ID_ALL; 560123326Snjl else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 561121992Sjhb if (bootverbose) 562167814Sjkim printf("MADT: Ignoring local NMI routed to " 563167814Sjkim "ACPI CPU %u\n", nmi->ProcessorId); 564121992Sjhb return; 565121992Sjhb } 566123326Snjl if (nmi->Lint == 0) 567259140Sjhb pin = APIC_LVT_LINT0; 568121992Sjhb else 569259140Sjhb pin = APIC_LVT_LINT1; 570121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 571167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 572121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 573167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 574167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 575121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 576167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 577121992Sjhb} 578121992Sjhb 579121992Sjhb/* 580121992Sjhb * Parse interrupt entries. 581121992Sjhb */ 582121992Sjhbstatic void 583167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 584121992Sjhb{ 585121992Sjhb 586121992Sjhb switch (entry->Type) { 587167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 588121992Sjhb madt_parse_interrupt_override( 589167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 590121992Sjhb break; 591167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 592167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 593121992Sjhb break; 594167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 595167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 596121992Sjhb break; 597121992Sjhb } 598121992Sjhb} 599121992Sjhb 600121992Sjhb/* 601121992Sjhb * Setup per-CPU ACPI IDs. 602121992Sjhb */ 603121992Sjhbstatic void 604121992Sjhbmadt_set_ids(void *dummy) 605121992Sjhb{ 606129960Sjhb struct lapic_info *la; 607121992Sjhb struct pcpu *pc; 608129960Sjhb u_int i; 609121992Sjhb 610121992Sjhb if (madt == NULL) 611121992Sjhb return; 612209059Sjhb CPU_FOREACH(i) { 613121992Sjhb pc = pcpu_find(i); 614167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 615129960Sjhb la = &lapics[pc->pc_apic_id]; 616130310Sjhb if (!la->la_enabled) 617129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 618129960Sjhb pc->pc_apic_id); 619129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 620129960Sjhb if (bootverbose) 621129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 622129960Sjhb la->la_acpi_id); 623121992Sjhb } 624121992Sjhb} 625256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL); 626