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