madt.c revision 278473
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 278473 2015-02-09 21:00:56Z kib $");
29121992Sjhb
30121992Sjhb#include <sys/param.h>
31121992Sjhb#include <sys/systm.h>
32121992Sjhb#include <sys/bus.h>
33121992Sjhb#include <sys/kernel.h>
34121992Sjhb#include <sys/malloc.h>
35121992Sjhb#include <sys/smp.h>
36121992Sjhb#include <vm/vm.h>
37121992Sjhb#include <vm/pmap.h>
38121992Sjhb
39214631Sjhb#include <x86/apicreg.h>
40121992Sjhb#include <machine/intr_machdep.h>
41261087Sjhb#include <x86/apicvar.h>
42278473Skib#include <machine/md_var.h>
43121992Sjhb
44193530Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193530Sjkim#include <contrib/dev/acpica/include/actables.h>
46193530Sjkim
47121992Sjhb#include <dev/acpica/acpivar.h>
48121992Sjhb#include <dev/pci/pcivar.h>
49121992Sjhb
50121992Sjhb/* These two arrays are indexed by APIC IDs. */
51233623Sjhbstatic struct {
52121992Sjhb	void *io_apic;
53121992Sjhb	UINT32 io_vector;
54233623Sjhb} *ioapics;
55121992Sjhb
56233623Sjhbstatic struct lapic_info {
57121992Sjhb	u_int la_enabled:1;
58129960Sjhb	u_int la_acpi_id:8;
59233623Sjhb} lapics[MAX_APIC_ID + 1];
60121992Sjhb
61269512Sroygerint madt_found_sci_override;
62167814Sjkimstatic ACPI_TABLE_MADT *madt;
63121992Sjhbstatic vm_paddr_t madt_physaddr;
64121992Sjhbstatic vm_offset_t madt_length;
65121992Sjhb
66227293Sedstatic MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
67121992Sjhb
68167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
69167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
70121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
71121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
72167814Sjkimstatic void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
73167814Sjkimstatic void	madt_parse_interrupt_override(
74167814Sjkim		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
75167814Sjkimstatic void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
76167814Sjkim		    void *arg __unused);
77167814Sjkimstatic void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
78167814Sjkimstatic void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
79121992Sjhbstatic int	madt_probe(void);
80121992Sjhbstatic int	madt_probe_cpus(void);
81167814Sjkimstatic void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
82167814Sjkim		    void *arg __unused);
83121992Sjhbstatic void	madt_register(void *dummy);
84121992Sjhbstatic int	madt_setup_local(void);
85121992Sjhbstatic int	madt_setup_io(void);
86197439Sjhbstatic void	madt_walk_table(acpi_subtable_handler *handler, void *arg);
87121992Sjhb
88121992Sjhbstatic struct apic_enumerator madt_enumerator = {
89121992Sjhb	"MADT",
90121992Sjhb	madt_probe,
91121992Sjhb	madt_probe_cpus,
92121992Sjhb	madt_setup_local,
93121992Sjhb	madt_setup_io
94121992Sjhb};
95121992Sjhb
96121992Sjhb/*
97121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
98121992Sjhb */
99121992Sjhbstatic int
100121992Sjhbmadt_probe(void)
101121992Sjhb{
102121992Sjhb
103197439Sjhb	madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
104197439Sjhb	if (madt_physaddr == 0)
105121992Sjhb		return (ENXIO);
106269511Sroyger	return (-50);
107121992Sjhb}
108121992Sjhb
109121992Sjhb/*
110121992Sjhb * Run through the MP table enumerating CPUs.
111121992Sjhb */
112121992Sjhbstatic int
113121992Sjhbmadt_probe_cpus(void)
114121992Sjhb{
115121992Sjhb
116197439Sjhb	madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
117197439Sjhb	madt_length = madt->Header.Length;
118121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
119121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
120197439Sjhb	acpi_unmap_table(madt);
121121992Sjhb	madt = NULL;
122121992Sjhb	return (0);
123121992Sjhb}
124121992Sjhb
125121992Sjhb/*
126121992Sjhb * Initialize the local APIC on the BSP.
127121992Sjhb */
128121992Sjhbstatic int
129121992Sjhbmadt_setup_local(void)
130121992Sjhb{
131278473Skib	ACPI_TABLE_DMAR *dmartbl;
132278473Skib	vm_paddr_t dmartbl_physaddr;
133121992Sjhb
134161223Sjhb	madt = pmap_mapbios(madt_physaddr, madt_length);
135278473Skib	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
136278473Skib		x2apic_mode = 1;
137278473Skib		dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
138278473Skib		if (dmartbl_physaddr != 0) {
139278473Skib			dmartbl = acpi_map_table(dmartbl_physaddr,
140278473Skib			    ACPI_SIG_DMAR);
141278473Skib			if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) {
142278473Skib				x2apic_mode = 0;
143278473Skib				if (bootverbose)
144278473Skib					printf(
145278473Skib		"x2APIC available but disabled by DMAR table\n");
146278473Skib			}
147278473Skib			acpi_unmap_table(dmartbl);
148278473Skib		}
149278473Skib		TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode);
150278473Skib	}
151278473Skib
152167814Sjkim	lapic_init(madt->Address);
153121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
154167814Sjkim	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
155167814Sjkim	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
156121992Sjhb
157121992Sjhb	/*
158121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
159121992Sjhb	 * perhaps emit a warning here if we find one?
160121992Sjhb	 */
161121992Sjhb	return (0);
162121992Sjhb}
163121992Sjhb
164121992Sjhb/*
165125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
166121992Sjhb */
167121992Sjhbstatic int
168121992Sjhbmadt_setup_io(void)
169121992Sjhb{
170128930Sjhb	void *ioapic;
171128930Sjhb	u_int pin;
172121992Sjhb	int i;
173121992Sjhb
174125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
175125048Sjhb	i = acpi_Startup();
176125048Sjhb	if (ACPI_FAILURE(i)) {
177125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
178125048Sjhb		    AcpiFormatException(i));
179125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
180125048Sjhb		panic("Using MADT but ACPI doesn't work");
181125048Sjhb	}
182233623Sjhb
183233623Sjhb	ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
184233623Sjhb	    M_WAITOK | M_ZERO);
185233623Sjhb
186121992Sjhb	/* First, we run through adding I/O APIC's. */
187121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
188121992Sjhb
189121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
190121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
191121992Sjhb
192128930Sjhb	/*
193128930Sjhb	 * If there was not an explicit override entry for the SCI,
194128930Sjhb	 * force it to use level trigger and active-low polarity.
195128930Sjhb	 */
196128930Sjhb	if (!madt_found_sci_override) {
197167814Sjkim		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
198167814Sjkim		    &pin) != 0)
199167814Sjkim			printf("MADT: Could not find APIC for SCI IRQ %u\n",
200167814Sjkim			    AcpiGbl_FADT.SciInterrupt);
201128930Sjhb		else {
202128930Sjhb			printf(
203128930Sjhb	"MADT: Forcing active-low polarity and level trigger for SCI\n");
204128930Sjhb			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
205128930Sjhb			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
206128930Sjhb		}
207128930Sjhb	}
208128930Sjhb
209121992Sjhb	/* Third, we register all the I/O APIC's. */
210169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++)
211121992Sjhb		if (ioapics[i].io_apic != NULL)
212121992Sjhb			ioapic_register(ioapics[i].io_apic);
213121992Sjhb
214121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
215121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
216121992Sjhb
217233623Sjhb	free(ioapics, M_MADT);
218233623Sjhb	ioapics = NULL;
219233623Sjhb
220121992Sjhb	return (0);
221121992Sjhb}
222121992Sjhb
223121992Sjhbstatic void
224121992Sjhbmadt_register(void *dummy __unused)
225121992Sjhb{
226121992Sjhb
227121992Sjhb	apic_register_enumerator(&madt_enumerator);
228121992Sjhb}
229215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
230121992Sjhb
231121992Sjhb/*
232121992Sjhb * Call the handler routine for each entry in the MADT table.
233121992Sjhb */
234121992Sjhbstatic void
235197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg)
236121992Sjhb{
237121992Sjhb
238197439Sjhb	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
239197439Sjhb	    handler, arg);
240121992Sjhb}
241121992Sjhb
242121992Sjhbstatic void
243167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
244121992Sjhb{
245167814Sjkim	ACPI_MADT_LOCAL_APIC *proc;
246121992Sjhb	struct lapic_info *la;
247121992Sjhb
248121992Sjhb	switch (entry->Type) {
249167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC:
250121992Sjhb		/*
251121992Sjhb		 * The MADT does not include a BSP flag, so we have to
252121992Sjhb		 * let the MP code figure out which CPU is the BSP on
253121992Sjhb		 * its own.
254121992Sjhb		 */
255167814Sjkim		proc = (ACPI_MADT_LOCAL_APIC *)entry;
256121992Sjhb		if (bootverbose)
257167814Sjkim			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
258167814Sjkim			    proc->Id, proc->ProcessorId,
259167814Sjkim			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
260167814Sjkim			    "enabled" : "disabled");
261167814Sjkim		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
262130310Sjhb			break;
263169395Sjhb		if (proc->Id > MAX_APIC_ID)
264167814Sjkim			panic("%s: CPU ID %u too high", __func__, proc->Id);
265167814Sjkim		la = &lapics[proc->Id];
266130310Sjhb		KASSERT(la->la_enabled == 0,
267167814Sjkim		    ("Duplicate local APIC ID %u", proc->Id));
268130310Sjhb		la->la_enabled = 1;
269129960Sjhb		la->la_acpi_id = proc->ProcessorId;
270167814Sjkim		lapic_create(proc->Id, 0);
271121992Sjhb		break;
272121992Sjhb	}
273121992Sjhb}
274121992Sjhb
275121992Sjhb
276121992Sjhb/*
277121992Sjhb * Add an I/O APIC from an entry in the table.
278121992Sjhb */
279121992Sjhbstatic void
280167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
281121992Sjhb{
282167814Sjkim	ACPI_MADT_IO_APIC *apic;
283121992Sjhb
284121992Sjhb	switch (entry->Type) {
285167814Sjkim	case ACPI_MADT_TYPE_IO_APIC:
286167814Sjkim		apic = (ACPI_MADT_IO_APIC *)entry;
287121992Sjhb		if (bootverbose)
288167814Sjkim			printf(
289167814Sjkim			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
290167814Sjkim			    apic->Id, apic->GlobalIrqBase,
291123326Snjl			    (void *)(uintptr_t)apic->Address);
292169395Sjhb		if (apic->Id > MAX_APIC_ID)
293167814Sjkim			panic("%s: I/O APIC ID %u too high", __func__,
294167814Sjkim			    apic->Id);
295167814Sjkim		if (ioapics[apic->Id].io_apic != NULL)
296167814Sjkim			panic("%s: Double APIC ID %u", __func__, apic->Id);
297189404Sjhb		if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
298189404Sjhb			printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
299189404Sjhb			break;
300189404Sjhb		}
301167814Sjkim		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
302167814Sjkim		    apic->Id, apic->GlobalIrqBase);
303167814Sjkim		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
304121992Sjhb		break;
305121992Sjhb	default:
306121992Sjhb		break;
307121992Sjhb	}
308121992Sjhb}
309121992Sjhb
310121992Sjhb/*
311129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
312129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
313128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
314129128Sjhb * SCI for which we use Active Lo, Level Triggered.
315121992Sjhb */
316128930Sjhbstatic enum intr_polarity
317167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source)
318121992Sjhb{
319121992Sjhb
320167814Sjkim	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
321263859Stakawata	default:
322269184Sakiyama		printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
323263859Stakawata		/* FALLTHROUGH*/
324167814Sjkim	case ACPI_MADT_POLARITY_CONFORMS:
325167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
326128930Sjhb			return (INTR_POLARITY_LOW);
327128930Sjhb		else
328128930Sjhb			return (INTR_POLARITY_HIGH);
329167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
330128930Sjhb		return (INTR_POLARITY_HIGH);
331167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_LOW:
332263859Stakawata		return (INTR_POLARITY_LOW);
333121992Sjhb	}
334121992Sjhb}
335121992Sjhb
336128930Sjhbstatic enum intr_trigger
337167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source)
338121992Sjhb{
339121992Sjhb
340167814Sjkim	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
341263859Stakawata	default:
342269184Sakiyama		printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
343263859Stakawata		/*FALLTHROUGH*/
344167814Sjkim	case ACPI_MADT_TRIGGER_CONFORMS:
345167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
346128930Sjhb			return (INTR_TRIGGER_LEVEL);
347128930Sjhb		else
348128930Sjhb			return (INTR_TRIGGER_EDGE);
349167814Sjkim	case ACPI_MADT_TRIGGER_EDGE:
350128930Sjhb		return (INTR_TRIGGER_EDGE);
351167814Sjkim	case ACPI_MADT_TRIGGER_LEVEL:
352263859Stakawata		return (INTR_TRIGGER_LEVEL);
353121992Sjhb	}
354121992Sjhb}
355121992Sjhb
356121992Sjhb/*
357121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
358121992Sjhb */
359121992Sjhbstatic int
360121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
361121992Sjhb{
362129960Sjhb	int i;
363121992Sjhb
364169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
365130310Sjhb		if (!lapics[i].la_enabled)
366129960Sjhb			continue;
367129960Sjhb		if (lapics[i].la_acpi_id != acpi_id)
368129960Sjhb			continue;
369129960Sjhb		*apic_id = i;
370130310Sjhb		return (0);
371129960Sjhb	}
372129960Sjhb	return (ENOENT);
373121992Sjhb}
374121992Sjhb
375121992Sjhb/*
376121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
377121992Sjhb * interrupt.
378121992Sjhb */
379121992Sjhbstatic int
380121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
381121992Sjhb{
382121992Sjhb	int i, best;
383121992Sjhb
384121992Sjhb	best = -1;
385169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
386121992Sjhb		if (ioapics[i].io_apic == NULL ||
387121992Sjhb		    ioapics[i].io_vector > intr)
388121992Sjhb			continue;
389121992Sjhb		if (best == -1 ||
390121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
391121992Sjhb			best = i;
392121992Sjhb	}
393121992Sjhb	if (best == -1)
394121992Sjhb		return (ENOENT);
395121992Sjhb	*apic = ioapics[best].io_apic;
396121992Sjhb	*pin = intr - ioapics[best].io_vector;
397121992Sjhb	if (*pin > 32)
398121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
399121992Sjhb		    intr);
400121992Sjhb	return (0);
401121992Sjhb}
402121992Sjhb
403269512Sroygervoid
404269512Sroygermadt_parse_interrupt_values(void *entry,
405269512Sroyger    enum intr_trigger *trig, enum intr_polarity *pol)
406121992Sjhb{
407269512Sroyger	ACPI_MADT_INTERRUPT_OVERRIDE *intr;
408128930Sjhb	char buf[64];
409121992Sjhb
410269512Sroyger	intr = entry;
411269512Sroyger
412121992Sjhb	if (bootverbose)
413142257Sjhb		printf("MADT: Interrupt override: source %u, irq %u\n",
414167814Sjkim		    intr->SourceIrq, intr->GlobalIrq);
415121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
416121992Sjhb
417125048Sjhb	/*
418128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
419128930Sjhb	 * entry.
420128930Sjhb	 */
421269512Sroyger	*trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
422269512Sroyger	*pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
423269512Sroyger
424128930Sjhb	/*
425125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
426128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
427128329Sjhb	 * force it to use level/lo.
428125048Sjhb	 */
429167814Sjkim	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
430128930Sjhb		madt_found_sci_override = 1;
431128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
432128930Sjhb			if (tolower(buf[0]) == 'e')
433269512Sroyger				*trig = INTR_TRIGGER_EDGE;
434128930Sjhb			else if (tolower(buf[0]) == 'l')
435269512Sroyger				*trig = INTR_TRIGGER_LEVEL;
436128930Sjhb			else
437128930Sjhb				panic(
438128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
439128930Sjhb				    buf);
440128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
441269512Sroyger			    *trig == INTR_TRIGGER_EDGE ? "edge" : "level");
442128930Sjhb		}
443128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
444128930Sjhb			if (tolower(buf[0]) == 'h')
445269512Sroyger				*pol = INTR_POLARITY_HIGH;
446128930Sjhb			else if (tolower(buf[0]) == 'l')
447269512Sroyger				*pol = INTR_POLARITY_LOW;
448128930Sjhb			else
449128930Sjhb				panic(
450128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
451128930Sjhb				    buf);
452128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
453269512Sroyger			    *pol == INTR_POLARITY_HIGH ? "high" : "low");
454128930Sjhb		}
455128930Sjhb	}
456269512Sroyger}
457125048Sjhb
458269512Sroyger/*
459269512Sroyger * Parse an interrupt source override for an ISA interrupt.
460269512Sroyger */
461269512Sroygerstatic void
462269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
463269512Sroyger{
464269512Sroyger	void *new_ioapic, *old_ioapic;
465269512Sroyger	u_int new_pin, old_pin;
466269512Sroyger	enum intr_trigger trig;
467269512Sroyger	enum intr_polarity pol;
468269512Sroyger
469269512Sroyger	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
470269512Sroyger	    intr->GlobalIrq == 2) {
471269512Sroyger		if (bootverbose)
472269512Sroyger			printf("MADT: Skipping timer override\n");
473269512Sroyger		return;
474269512Sroyger	}
475269512Sroyger
476269512Sroyger	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
477269512Sroyger		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
478269512Sroyger		    intr->GlobalIrq, intr->SourceIrq);
479269512Sroyger		return;
480269512Sroyger	}
481269512Sroyger
482269512Sroyger	madt_parse_interrupt_values(intr, &trig, &pol);
483269512Sroyger
484128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
485167814Sjkim	if (intr->SourceIrq != intr->GlobalIrq) {
486125048Sjhb		/*
487125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
488125048Sjhb		 * then override the vector we use to setup and allocate
489125048Sjhb		 * the interrupt.
490125048Sjhb		 */
491167814Sjkim		if (intr->GlobalIrq > 15 &&
492167814Sjkim		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
493167814Sjkim			acpi_OverrideInterruptLevel(intr->GlobalIrq);
494122502Sjhb		else
495167814Sjkim			ioapic_remap_vector(new_ioapic, new_pin,
496167814Sjkim			    intr->SourceIrq);
497167814Sjkim		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
498122149Sjhb		    &old_pin) != 0)
499167814Sjkim			printf("MADT: Could not find APIC for source IRQ %u\n",
500167814Sjkim			    intr->SourceIrq);
501122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
502167814Sjkim		    intr->SourceIrq)
503122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
504122149Sjhb	}
505128930Sjhb
506128930Sjhb	/* Program the polarity and trigger mode. */
507128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
508128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
509121992Sjhb}
510121992Sjhb
511121992Sjhb/*
512121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
513121992Sjhb */
514121992Sjhbstatic void
515167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
516121992Sjhb{
517121992Sjhb	void *ioapic;
518121992Sjhb	u_int pin;
519121992Sjhb
520167814Sjkim	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
521167814Sjkim		printf("MADT: Could not find APIC for vector %u\n",
522167814Sjkim		    nmi->GlobalIrq);
523121992Sjhb		return;
524121992Sjhb	}
525121992Sjhb
526121992Sjhb	ioapic_set_nmi(ioapic, pin);
527167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
528121992Sjhb		ioapic_set_triggermode(ioapic, pin,
529167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
530263794Stakawata	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
531121992Sjhb		ioapic_set_polarity(ioapic, pin,
532167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
533121992Sjhb}
534121992Sjhb
535121992Sjhb/*
536121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
537121992Sjhb */
538121992Sjhbstatic void
539167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
540121992Sjhb{
541121992Sjhb	u_int apic_id, pin;
542121992Sjhb
543123326Snjl	if (nmi->ProcessorId == 0xff)
544121992Sjhb		apic_id = APIC_ID_ALL;
545123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
546121992Sjhb		if (bootverbose)
547167814Sjkim			printf("MADT: Ignoring local NMI routed to "
548167814Sjkim			    "ACPI CPU %u\n", nmi->ProcessorId);
549121992Sjhb		return;
550121992Sjhb	}
551123326Snjl	if (nmi->Lint == 0)
552259140Sjhb		pin = APIC_LVT_LINT0;
553121992Sjhb	else
554259140Sjhb		pin = APIC_LVT_LINT1;
555121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
556167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
557121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
558167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
559167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
560121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
561167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
562121992Sjhb}
563121992Sjhb
564121992Sjhb/*
565121992Sjhb * Parse interrupt entries.
566121992Sjhb */
567121992Sjhbstatic void
568167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
569121992Sjhb{
570121992Sjhb
571121992Sjhb	switch (entry->Type) {
572167814Sjkim	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
573121992Sjhb		madt_parse_interrupt_override(
574167814Sjkim			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
575121992Sjhb		break;
576167814Sjkim	case ACPI_MADT_TYPE_NMI_SOURCE:
577167814Sjkim		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
578121992Sjhb		break;
579167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
580167814Sjkim		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
581121992Sjhb		break;
582121992Sjhb	}
583121992Sjhb}
584121992Sjhb
585121992Sjhb/*
586121992Sjhb * Setup per-CPU ACPI IDs.
587121992Sjhb */
588121992Sjhbstatic void
589121992Sjhbmadt_set_ids(void *dummy)
590121992Sjhb{
591129960Sjhb	struct lapic_info *la;
592121992Sjhb	struct pcpu *pc;
593129960Sjhb	u_int i;
594121992Sjhb
595121992Sjhb	if (madt == NULL)
596121992Sjhb		return;
597209059Sjhb	CPU_FOREACH(i) {
598121992Sjhb		pc = pcpu_find(i);
599167814Sjkim		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
600129960Sjhb		la = &lapics[pc->pc_apic_id];
601130310Sjhb		if (!la->la_enabled)
602129960Sjhb			panic("APIC: CPU with APIC ID %u is not enabled",
603129960Sjhb			    pc->pc_apic_id);
604129960Sjhb		pc->pc_acpi_id = la->la_acpi_id;
605129960Sjhb		if (bootverbose)
606129960Sjhb			printf("APIC: CPU %u has ACPI ID %u\n", i,
607129960Sjhb			    la->la_acpi_id);
608121992Sjhb	}
609121992Sjhb}
610256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
611