madt.c revision 215012
112099Sjoerg/*- 212099Sjoerg * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> 312099Sjoerg * All rights reserved. 412099Sjoerg * 512099Sjoerg * Redistribution and use in source and binary forms, with or without 612099Sjoerg * modification, are permitted provided that the following conditions 712099Sjoerg * are met: 812099Sjoerg * 1. Redistributions of source code must retain the above copyright 912099Sjoerg * notice, this list of conditions and the following disclaimer. 1012099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1112099Sjoerg * notice, this list of conditions and the following disclaimer in the 1212099Sjoerg * documentation and/or other materials provided with the distribution. 1312099Sjoerg * 3. Neither the name of the author nor the names of any co-contributors 1412099Sjoerg * may be used to endorse or promote products derived from this software 1512099Sjoerg * without specific prior written permission. 1612099Sjoerg * 1712099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1812099Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1912099Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2012099Sjoerg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2112099Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2212099Sjoerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2312099Sjoerg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2412099Sjoerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2512099Sjoerg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2612099Sjoerg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2712099Sjoerg * SUCH DAMAGE. 2812099Sjoerg */ 2912099Sjoerg 3012099Sjoerg#include <sys/cdefs.h> 3112099Sjoerg__FBSDID("$FreeBSD: head/sys/x86/acpica/madt.c 215012 2010-11-08 20:57:02Z jhb $"); 3212099Sjoerg 3312099Sjoerg#include <sys/param.h> 3412099Sjoerg#include <sys/systm.h> 3512099Sjoerg#include <sys/bus.h> 3612099Sjoerg#include <sys/kernel.h> 3712099Sjoerg#include <sys/malloc.h> 3812099Sjoerg#include <sys/smp.h> 3912099Sjoerg#include <vm/vm.h> 4012099Sjoerg#include <vm/pmap.h> 4112099Sjoerg 4212099Sjoerg#include <x86/apicreg.h> 4312099Sjoerg#include <machine/intr_machdep.h> 4412099Sjoerg#include <machine/apicvar.h> 4512099Sjoerg 4612099Sjoerg#include <contrib/dev/acpica/include/acpi.h> 4712099Sjoerg#include <contrib/dev/acpica/include/actables.h> 4812099Sjoerg 4912099Sjoerg#include <dev/acpica/acpivar.h> 5012099Sjoerg#include <dev/pci/pcivar.h> 5112099Sjoerg 5212099Sjoerg/* These two arrays are indexed by APIC IDs. */ 5312099Sjoergstruct ioapic_info { 5412099Sjoerg void *io_apic; 5512099Sjoerg UINT32 io_vector; 5612099Sjoerg} ioapics[MAX_APIC_ID + 1]; 5712099Sjoerg 5812099Sjoergstruct lapic_info { 5912099Sjoerg u_int la_enabled:1; 6012099Sjoerg u_int la_acpi_id:8; 6112099Sjoerg} lapics[MAX_APIC_ID + 1]; 6212099Sjoerg 6312099Sjoergstatic int madt_found_sci_override; 6412099Sjoergstatic ACPI_TABLE_MADT *madt; 6512099Sjoergstatic vm_paddr_t madt_physaddr; 6612099Sjoergstatic vm_offset_t madt_length; 6712099Sjoerg 6812099SjoergMALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 6912099Sjoerg 7012099Sjoergstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 7112099Sjoergstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 7212099Sjoergstatic int madt_find_cpu(u_int acpi_id, u_int *apic_id); 7312099Sjoergstatic int madt_find_interrupt(int intr, void **apic, u_int *pin); 7412099Sjoergstatic void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 7512099Sjoergstatic void madt_parse_interrupt_override( 7612099Sjoerg ACPI_MADT_INTERRUPT_OVERRIDE *intr); 7712099Sjoergstatic void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 7812099Sjoerg void *arg __unused); 7912099Sjoergstatic void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 8012099Sjoergstatic void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 8112099Sjoergstatic int madt_probe(void); 8212099Sjoergstatic int madt_probe_cpus(void); 8312099Sjoergstatic void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 8412099Sjoerg void *arg __unused); 8512099Sjoergstatic void madt_register(void *dummy); 8612099Sjoergstatic int madt_setup_local(void); 8712099Sjoergstatic int madt_setup_io(void); 8812099Sjoergstatic void madt_walk_table(acpi_subtable_handler *handler, void *arg); 8912099Sjoerg 9012099Sjoergstatic struct apic_enumerator madt_enumerator = { 9112099Sjoerg "MADT", 9212099Sjoerg madt_probe, 9312099Sjoerg madt_probe_cpus, 9412099Sjoerg madt_setup_local, 9512099Sjoerg madt_setup_io 9612099Sjoerg}; 9712099Sjoerg 9812099Sjoerg/* 9912099Sjoerg * Look for an ACPI Multiple APIC Description Table ("APIC") 10012099Sjoerg */ 10112099Sjoergstatic int 10212099Sjoergmadt_probe(void) 10312099Sjoerg{ 10412099Sjoerg 10512099Sjoerg madt_physaddr = acpi_find_table(ACPI_SIG_MADT); 10612099Sjoerg if (madt_physaddr == 0) 10712099Sjoerg return (ENXIO); 10812099Sjoerg return (0); 10912099Sjoerg} 11012099Sjoerg 11112099Sjoerg/* 11212099Sjoerg * Run through the MP table enumerating CPUs. 11312099Sjoerg */ 11412099Sjoergstatic int 11512099Sjoergmadt_probe_cpus(void) 11612099Sjoerg{ 11712099Sjoerg 11812099Sjoerg madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT); 11912099Sjoerg madt_length = madt->Header.Length; 12012099Sjoerg KASSERT(madt != NULL, ("Unable to re-map MADT")); 12112099Sjoerg madt_walk_table(madt_probe_cpus_handler, NULL); 12212099Sjoerg acpi_unmap_table(madt); 12312099Sjoerg madt = NULL; 12412099Sjoerg return (0); 12512099Sjoerg} 12612099Sjoerg 12712099Sjoerg/* 12812099Sjoerg * Initialize the local APIC on the BSP. 12912099Sjoerg */ 13012099Sjoergstatic int 13112099Sjoergmadt_setup_local(void) 13212099Sjoerg{ 13312099Sjoerg 13412099Sjoerg madt = pmap_mapbios(madt_physaddr, madt_length); 13512099Sjoerg lapic_init(madt->Address); 13612099Sjoerg printf("ACPI APIC Table: <%.*s %.*s>\n", 13712099Sjoerg (int)sizeof(madt->Header.OemId), madt->Header.OemId, 13812099Sjoerg (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 13912099Sjoerg 14012099Sjoerg /* 14112099Sjoerg * We ignore 64-bit local APIC override entries. Should we 14212099Sjoerg * perhaps emit a warning here if we find one? 14312099Sjoerg */ 14412099Sjoerg return (0); 14512099Sjoerg} 14612099Sjoerg 14712099Sjoerg/* 14812099Sjoerg * Enumerate I/O APICs and setup interrupt sources. 14912099Sjoerg */ 15012099Sjoergstatic int 15112099Sjoergmadt_setup_io(void) 15212099Sjoerg{ 15312099Sjoerg void *ioapic; 15412099Sjoerg u_int pin; 15512099Sjoerg int i; 15612099Sjoerg 15712099Sjoerg /* Try to initialize ACPI so that we can access the FADT. */ 15812099Sjoerg i = acpi_Startup(); 15912099Sjoerg if (ACPI_FAILURE(i)) { 16012099Sjoerg printf("MADT: ACPI Startup failed with %s\n", 16112099Sjoerg AcpiFormatException(i)); 16212099Sjoerg printf("Try disabling either ACPI or apic support.\n"); 16312099Sjoerg panic("Using MADT but ACPI doesn't work"); 16412099Sjoerg } 16512099Sjoerg 16612099Sjoerg /* First, we run through adding I/O APIC's. */ 16712099Sjoerg madt_walk_table(madt_parse_apics, NULL); 16812099Sjoerg 16912099Sjoerg /* Second, we run through the table tweaking interrupt sources. */ 17012099Sjoerg madt_walk_table(madt_parse_ints, NULL); 17112099Sjoerg 17212099Sjoerg /* 17312099Sjoerg * If there was not an explicit override entry for the SCI, 17412099Sjoerg * force it to use level trigger and active-low polarity. 17512099Sjoerg */ 17612099Sjoerg if (!madt_found_sci_override) { 17712099Sjoerg if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 17812099Sjoerg &pin) != 0) 17912099Sjoerg printf("MADT: Could not find APIC for SCI IRQ %u\n", 18012099Sjoerg AcpiGbl_FADT.SciInterrupt); 18112099Sjoerg else { 18212099Sjoerg printf( 18312099Sjoerg "MADT: Forcing active-low polarity and level trigger for SCI\n"); 18412099Sjoerg ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 18512099Sjoerg ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 18612099Sjoerg } 18712099Sjoerg } 18812099Sjoerg 18912099Sjoerg /* Third, we register all the I/O APIC's. */ 19012099Sjoerg for (i = 0; i <= MAX_APIC_ID; i++) 19112099Sjoerg if (ioapics[i].io_apic != NULL) 19212099Sjoerg ioapic_register(ioapics[i].io_apic); 19312099Sjoerg 19412099Sjoerg /* Finally, we throw the switch to enable the I/O APIC's. */ 19512099Sjoerg acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 19612099Sjoerg 19712099Sjoerg return (0); 19812099Sjoerg} 19912099Sjoerg 20012099Sjoergstatic void 20112099Sjoergmadt_register(void *dummy __unused) 20212099Sjoerg{ 20312099Sjoerg 20412099Sjoerg apic_register_enumerator(&madt_enumerator); 20512099Sjoerg} 20612099SjoergSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL); 20712099Sjoerg 20812099Sjoerg/* 20912099Sjoerg * Call the handler routine for each entry in the MADT table. 21012099Sjoerg */ 21112099Sjoergstatic void 21212099Sjoergmadt_walk_table(acpi_subtable_handler *handler, void *arg) 21312099Sjoerg{ 21412099Sjoerg 21512099Sjoerg acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, 21612099Sjoerg handler, arg); 21712099Sjoerg} 21812099Sjoerg 21912099Sjoergstatic void 22012099Sjoergmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 22112099Sjoerg{ 22212099Sjoerg ACPI_MADT_LOCAL_APIC *proc; 22312099Sjoerg struct lapic_info *la; 22412099Sjoerg 22512099Sjoerg switch (entry->Type) { 22612099Sjoerg case ACPI_MADT_TYPE_LOCAL_APIC: 22712099Sjoerg /* 22812099Sjoerg * The MADT does not include a BSP flag, so we have to 22912099Sjoerg * let the MP code figure out which CPU is the BSP on 23012099Sjoerg * its own. 23112099Sjoerg */ 23212099Sjoerg proc = (ACPI_MADT_LOCAL_APIC *)entry; 23312099Sjoerg if (bootverbose) 23412099Sjoerg printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 23512099Sjoerg proc->Id, proc->ProcessorId, 23612099Sjoerg (proc->LapicFlags & ACPI_MADT_ENABLED) ? 23712099Sjoerg "enabled" : "disabled"); 23812099Sjoerg if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 23912099Sjoerg break; 24012099Sjoerg if (proc->Id > MAX_APIC_ID) 24112099Sjoerg panic("%s: CPU ID %u too high", __func__, proc->Id); 24212099Sjoerg la = &lapics[proc->Id]; 24312099Sjoerg KASSERT(la->la_enabled == 0, 24412099Sjoerg ("Duplicate local APIC ID %u", proc->Id)); 24512099Sjoerg la->la_enabled = 1; 24612099Sjoerg la->la_acpi_id = proc->ProcessorId; 24712099Sjoerg lapic_create(proc->Id, 0); 24812099Sjoerg break; 24912099Sjoerg } 25012099Sjoerg} 25112099Sjoerg 25212099Sjoerg 25312099Sjoerg/* 25412099Sjoerg * Add an I/O APIC from an entry in the table. 25512099Sjoerg */ 25612099Sjoergstatic void 25712099Sjoergmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 25812099Sjoerg{ 25912099Sjoerg ACPI_MADT_IO_APIC *apic; 26012099Sjoerg 26112099Sjoerg switch (entry->Type) { 26212099Sjoerg case ACPI_MADT_TYPE_IO_APIC: 26312099Sjoerg apic = (ACPI_MADT_IO_APIC *)entry; 26412099Sjoerg if (bootverbose) 26512099Sjoerg printf( 26612099Sjoerg "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 26712099Sjoerg apic->Id, apic->GlobalIrqBase, 26812099Sjoerg (void *)(uintptr_t)apic->Address); 26912099Sjoerg if (apic->Id > MAX_APIC_ID) 27012099Sjoerg panic("%s: I/O APIC ID %u too high", __func__, 27112099Sjoerg apic->Id); 27212099Sjoerg if (ioapics[apic->Id].io_apic != NULL) 27312099Sjoerg panic("%s: Double APIC ID %u", __func__, apic->Id); 27412099Sjoerg if (apic->GlobalIrqBase >= FIRST_MSI_INT) { 27512099Sjoerg printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id); 27612099Sjoerg break; 27712099Sjoerg } 27812099Sjoerg ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 27912099Sjoerg apic->Id, apic->GlobalIrqBase); 28012099Sjoerg ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 28112099Sjoerg break; 28212099Sjoerg default: 28312099Sjoerg break; 28412099Sjoerg } 28512099Sjoerg} 28612099Sjoerg 28712099Sjoerg/* 28812099Sjoerg * Determine properties of an interrupt source. Note that for ACPI these 28912099Sjoerg * functions are only used for ISA interrupts, so we assume ISA bus values 29012099Sjoerg * (Active Hi, Edge Triggered) for conforming values except for the ACPI 29112099Sjoerg * SCI for which we use Active Lo, Level Triggered. 29212099Sjoerg */ 29312099Sjoergstatic enum intr_polarity 29412099Sjoerginterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 29512099Sjoerg{ 29612099Sjoerg 29712099Sjoerg switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 29812099Sjoerg case ACPI_MADT_POLARITY_CONFORMS: 29912099Sjoerg if (Source == AcpiGbl_FADT.SciInterrupt) 30012099Sjoerg return (INTR_POLARITY_LOW); 30112099Sjoerg else 30212099Sjoerg return (INTR_POLARITY_HIGH); 30312099Sjoerg case ACPI_MADT_POLARITY_ACTIVE_HIGH: 30412099Sjoerg return (INTR_POLARITY_HIGH); 30512099Sjoerg case ACPI_MADT_POLARITY_ACTIVE_LOW: 30612099Sjoerg return (INTR_POLARITY_LOW); 30712099Sjoerg default: 30812099Sjoerg panic("Bogus Interrupt Polarity"); 30912099Sjoerg } 31012099Sjoerg} 31112099Sjoerg 31212099Sjoergstatic enum intr_trigger 31312099Sjoerginterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 31412099Sjoerg{ 31512099Sjoerg 31612099Sjoerg switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 31712099Sjoerg case ACPI_MADT_TRIGGER_CONFORMS: 31812099Sjoerg if (Source == AcpiGbl_FADT.SciInterrupt) 31912099Sjoerg return (INTR_TRIGGER_LEVEL); 32012099Sjoerg else 32112099Sjoerg return (INTR_TRIGGER_EDGE); 32212099Sjoerg case ACPI_MADT_TRIGGER_EDGE: 32312099Sjoerg return (INTR_TRIGGER_EDGE); 32412099Sjoerg case ACPI_MADT_TRIGGER_LEVEL: 32512099Sjoerg return (INTR_TRIGGER_LEVEL); 32612099Sjoerg default: 32712099Sjoerg panic("Bogus Interrupt Trigger Mode"); 32812099Sjoerg } 32912099Sjoerg} 33012099Sjoerg 33112099Sjoerg/* 33212099Sjoerg * Find the local APIC ID associated with a given ACPI Processor ID. 33312099Sjoerg */ 33412099Sjoergstatic int 33512099Sjoergmadt_find_cpu(u_int acpi_id, u_int *apic_id) 33612099Sjoerg{ 33712099Sjoerg int i; 33812099Sjoerg 33912099Sjoerg for (i = 0; i <= MAX_APIC_ID; i++) { 34012099Sjoerg if (!lapics[i].la_enabled) 34112099Sjoerg continue; 34212099Sjoerg if (lapics[i].la_acpi_id != acpi_id) 34312099Sjoerg continue; 34412099Sjoerg *apic_id = i; 34512099Sjoerg return (0); 34612099Sjoerg } 34712099Sjoerg return (ENOENT); 34812099Sjoerg} 34912099Sjoerg 35012099Sjoerg/* 35112099Sjoerg * Find the IO APIC and pin on that APIC associated with a given global 35212099Sjoerg * interrupt. 35312099Sjoerg */ 35412099Sjoergstatic int 35512099Sjoergmadt_find_interrupt(int intr, void **apic, u_int *pin) 35612099Sjoerg{ 35712099Sjoerg int i, best; 35812099Sjoerg 35912099Sjoerg best = -1; 36012099Sjoerg for (i = 0; i <= MAX_APIC_ID; i++) { 36112099Sjoerg if (ioapics[i].io_apic == NULL || 36212099Sjoerg ioapics[i].io_vector > intr) 36312099Sjoerg continue; 36412099Sjoerg if (best == -1 || 36512099Sjoerg ioapics[best].io_vector < ioapics[i].io_vector) 36612099Sjoerg best = i; 36712099Sjoerg } 36812099Sjoerg if (best == -1) 36912099Sjoerg return (ENOENT); 37012099Sjoerg *apic = ioapics[best].io_apic; 37112099Sjoerg *pin = intr - ioapics[best].io_vector; 37212099Sjoerg if (*pin > 32) 37312099Sjoerg printf("WARNING: Found intpin of %u for vector %d\n", *pin, 37412099Sjoerg intr); 37512099Sjoerg return (0); 37612099Sjoerg} 37712099Sjoerg 37812099Sjoerg/* 37912099Sjoerg * Parse an interrupt source override for an ISA interrupt. 38012099Sjoerg */ 38112099Sjoergstatic void 38212099Sjoergmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 38312099Sjoerg{ 38412099Sjoerg void *new_ioapic, *old_ioapic; 38512099Sjoerg u_int new_pin, old_pin; 38612099Sjoerg enum intr_trigger trig; 38712099Sjoerg enum intr_polarity pol; 38812099Sjoerg char buf[64]; 38912099Sjoerg 39012099Sjoerg if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 39112099Sjoerg intr->GlobalIrq == 2) { 39212099Sjoerg if (bootverbose) 39312099Sjoerg printf("MADT: Skipping timer override\n"); 39412099Sjoerg return; 39512099Sjoerg } 39612099Sjoerg if (bootverbose) 39712099Sjoerg printf("MADT: Interrupt override: source %u, irq %u\n", 39812099Sjoerg intr->SourceIrq, intr->GlobalIrq); 39912099Sjoerg KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 40012099Sjoerg if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 40112099Sjoerg printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 40212099Sjoerg intr->GlobalIrq, intr->SourceIrq); 40312099Sjoerg return; 40412099Sjoerg } 40512099Sjoerg 40612099Sjoerg /* 40712099Sjoerg * Lookup the appropriate trigger and polarity modes for this 40812099Sjoerg * entry. 40912099Sjoerg */ 41012099Sjoerg trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 41112099Sjoerg pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 41212099Sjoerg 41312099Sjoerg /* 41412099Sjoerg * If the SCI is identity mapped but has edge trigger and 41512099Sjoerg * active-hi polarity or the force_sci_lo tunable is set, 41612099Sjoerg * force it to use level/lo. 41712099Sjoerg */ 41812099Sjoerg if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 41912099Sjoerg madt_found_sci_override = 1; 42012099Sjoerg if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 42112099Sjoerg if (tolower(buf[0]) == 'e') 42212099Sjoerg trig = INTR_TRIGGER_EDGE; 42312099Sjoerg else if (tolower(buf[0]) == 'l') 42412099Sjoerg trig = INTR_TRIGGER_LEVEL; 42512099Sjoerg else 42612099Sjoerg panic( 42712099Sjoerg "Invalid trigger %s: must be 'edge' or 'level'", 42812099Sjoerg buf); 42912099Sjoerg printf("MADT: Forcing SCI to %s trigger\n", 43012099Sjoerg trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 43112099Sjoerg } 43212099Sjoerg if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 43312099Sjoerg if (tolower(buf[0]) == 'h') 43412099Sjoerg pol = INTR_POLARITY_HIGH; 43512099Sjoerg else if (tolower(buf[0]) == 'l') 43612099Sjoerg pol = INTR_POLARITY_LOW; 43712099Sjoerg else 43812099Sjoerg panic( 43912099Sjoerg "Invalid polarity %s: must be 'high' or 'low'", 44012099Sjoerg buf); 44112099Sjoerg printf("MADT: Forcing SCI to active %s polarity\n", 44212099Sjoerg pol == INTR_POLARITY_HIGH ? "high" : "low"); 44312099Sjoerg } 44412099Sjoerg } 44512099Sjoerg 44612099Sjoerg /* Remap the IRQ if it is mapped to a different interrupt vector. */ 44712099Sjoerg if (intr->SourceIrq != intr->GlobalIrq) { 44812099Sjoerg /* 44912099Sjoerg * If the SCI is remapped to a non-ISA global interrupt, 45012099Sjoerg * then override the vector we use to setup and allocate 45112099Sjoerg * the interrupt. 45212099Sjoerg */ 45312099Sjoerg if (intr->GlobalIrq > 15 && 45412099Sjoerg intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 45512099Sjoerg acpi_OverrideInterruptLevel(intr->GlobalIrq); 45612099Sjoerg else 45712099Sjoerg ioapic_remap_vector(new_ioapic, new_pin, 45812099Sjoerg intr->SourceIrq); 45912099Sjoerg if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 46012099Sjoerg &old_pin) != 0) 46112099Sjoerg printf("MADT: Could not find APIC for source IRQ %u\n", 46212099Sjoerg intr->SourceIrq); 46312099Sjoerg else if (ioapic_get_vector(old_ioapic, old_pin) == 46412099Sjoerg intr->SourceIrq) 46512099Sjoerg ioapic_disable_pin(old_ioapic, old_pin); 46612099Sjoerg } 46712099Sjoerg 46812099Sjoerg /* Program the polarity and trigger mode. */ 46912099Sjoerg ioapic_set_triggermode(new_ioapic, new_pin, trig); 47012099Sjoerg ioapic_set_polarity(new_ioapic, new_pin, pol); 47112099Sjoerg} 47212099Sjoerg 47312099Sjoerg/* 47412099Sjoerg * Parse an entry for an NMI routed to an IO APIC. 47512099Sjoerg */ 47612099Sjoergstatic void 47712099Sjoergmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 47812099Sjoerg{ 47912099Sjoerg void *ioapic; 48012099Sjoerg u_int pin; 48112099Sjoerg 48212099Sjoerg if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 48312099Sjoerg printf("MADT: Could not find APIC for vector %u\n", 48412099Sjoerg nmi->GlobalIrq); 48512099Sjoerg return; 48612099Sjoerg } 48712099Sjoerg 48812099Sjoerg ioapic_set_nmi(ioapic, pin); 48912099Sjoerg if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 49012099Sjoerg ioapic_set_triggermode(ioapic, pin, 49112099Sjoerg interrupt_trigger(nmi->IntiFlags, 0)); 49212099Sjoerg if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 49312099Sjoerg ioapic_set_polarity(ioapic, pin, 49412099Sjoerg interrupt_polarity(nmi->IntiFlags, 0)); 49512099Sjoerg} 49612099Sjoerg 49712099Sjoerg/* 49812099Sjoerg * Parse an entry for an NMI routed to a local APIC LVT pin. 49912099Sjoerg */ 50012099Sjoergstatic void 50112099Sjoergmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 50212099Sjoerg{ 50312099Sjoerg u_int apic_id, pin; 50412099Sjoerg 50512099Sjoerg if (nmi->ProcessorId == 0xff) 50612099Sjoerg apic_id = APIC_ID_ALL; 50712099Sjoerg else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 50812099Sjoerg if (bootverbose) 50912099Sjoerg printf("MADT: Ignoring local NMI routed to " 51012099Sjoerg "ACPI CPU %u\n", nmi->ProcessorId); 51112099Sjoerg return; 51212099Sjoerg } 51312099Sjoerg if (nmi->Lint == 0) 51412099Sjoerg pin = LVT_LINT0; 51512099Sjoerg else 51612099Sjoerg pin = LVT_LINT1; 51712099Sjoerg lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 51812099Sjoerg if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 51912099Sjoerg lapic_set_lvt_triggermode(apic_id, pin, 52012099Sjoerg interrupt_trigger(nmi->IntiFlags, 0)); 52112099Sjoerg if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 52212099Sjoerg lapic_set_lvt_polarity(apic_id, pin, 52312099Sjoerg interrupt_polarity(nmi->IntiFlags, 0)); 52412099Sjoerg} 52512099Sjoerg 52612099Sjoerg/* 52712099Sjoerg * Parse interrupt entries. 52812099Sjoerg */ 52912099Sjoergstatic void 53012099Sjoergmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 53112099Sjoerg{ 53212099Sjoerg 53312099Sjoerg switch (entry->Type) { 53412099Sjoerg case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 53512099Sjoerg madt_parse_interrupt_override( 53612099Sjoerg (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 53712099Sjoerg break; 53812099Sjoerg case ACPI_MADT_TYPE_NMI_SOURCE: 53912099Sjoerg madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 54012099Sjoerg break; 54112099Sjoerg case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 54212099Sjoerg madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 54312099Sjoerg break; 54412099Sjoerg } 54512099Sjoerg} 54612099Sjoerg 54712099Sjoerg/* 54812099Sjoerg * Setup per-CPU ACPI IDs. 54912099Sjoerg */ 55012099Sjoergstatic void 55112099Sjoergmadt_set_ids(void *dummy) 55212099Sjoerg{ 55312099Sjoerg struct lapic_info *la; 55412099Sjoerg struct pcpu *pc; 55512099Sjoerg u_int i; 55612099Sjoerg 55712099Sjoerg if (madt == NULL) 55812099Sjoerg return; 55912099Sjoerg CPU_FOREACH(i) { 56012099Sjoerg pc = pcpu_find(i); 56112099Sjoerg KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 56212099Sjoerg la = &lapics[pc->pc_apic_id]; 56312099Sjoerg if (!la->la_enabled) 56412099Sjoerg panic("APIC: CPU with APIC ID %u is not enabled", 56512099Sjoerg pc->pc_apic_id); 56612099Sjoerg pc->pc_acpi_id = la->la_acpi_id; 56712099Sjoerg if (bootverbose) 56812099Sjoerg printf("APIC: CPU %u has ACPI ID %u\n", i, 56912099Sjoerg la->la_acpi_id); 57012099Sjoerg } 57112099Sjoerg} 57212099SjoergSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL); 57312099Sjoerg