madt.c revision 259140
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 * 3. Neither the name of the author nor the names of any co-contributors
14121992Sjhb *    may be used to endorse or promote products derived from this software
15121992Sjhb *    without specific prior written permission.
16121992Sjhb *
17121992Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18121992Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19121992Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20121992Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21121992Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22121992Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23121992Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24121992Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25121992Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26121992Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27121992Sjhb * SUCH DAMAGE.
28121992Sjhb */
29121992Sjhb
30121992Sjhb#include <sys/cdefs.h>
31121992Sjhb__FBSDID("$FreeBSD: head/sys/x86/acpica/madt.c 259140 2013-12-09 21:08:52Z jhb $");
32121992Sjhb
33121992Sjhb#include <sys/param.h>
34121992Sjhb#include <sys/systm.h>
35121992Sjhb#include <sys/bus.h>
36121992Sjhb#include <sys/kernel.h>
37121992Sjhb#include <sys/malloc.h>
38121992Sjhb#include <sys/smp.h>
39121992Sjhb#include <vm/vm.h>
40121992Sjhb#include <vm/pmap.h>
41121992Sjhb
42214631Sjhb#include <x86/apicreg.h>
43121992Sjhb#include <machine/intr_machdep.h>
44121992Sjhb#include <machine/apicvar.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
63128930Sjhbstatic int 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);
108121992Sjhb	return (0);
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{
133121992Sjhb
134161223Sjhb	madt = pmap_mapbios(madt_physaddr, madt_length);
135167814Sjkim	lapic_init(madt->Address);
136121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
137167814Sjkim	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
138167814Sjkim	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
139121992Sjhb
140121992Sjhb	/*
141121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
142121992Sjhb	 * perhaps emit a warning here if we find one?
143121992Sjhb	 */
144121992Sjhb	return (0);
145121992Sjhb}
146121992Sjhb
147121992Sjhb/*
148125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
149121992Sjhb */
150121992Sjhbstatic int
151121992Sjhbmadt_setup_io(void)
152121992Sjhb{
153128930Sjhb	void *ioapic;
154128930Sjhb	u_int pin;
155121992Sjhb	int i;
156121992Sjhb
157125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
158125048Sjhb	i = acpi_Startup();
159125048Sjhb	if (ACPI_FAILURE(i)) {
160125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
161125048Sjhb		    AcpiFormatException(i));
162125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
163125048Sjhb		panic("Using MADT but ACPI doesn't work");
164125048Sjhb	}
165233623Sjhb
166233623Sjhb	ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
167233623Sjhb	    M_WAITOK | M_ZERO);
168233623Sjhb
169121992Sjhb	/* First, we run through adding I/O APIC's. */
170121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
171121992Sjhb
172121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
173121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
174121992Sjhb
175128930Sjhb	/*
176128930Sjhb	 * If there was not an explicit override entry for the SCI,
177128930Sjhb	 * force it to use level trigger and active-low polarity.
178128930Sjhb	 */
179128930Sjhb	if (!madt_found_sci_override) {
180167814Sjkim		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
181167814Sjkim		    &pin) != 0)
182167814Sjkim			printf("MADT: Could not find APIC for SCI IRQ %u\n",
183167814Sjkim			    AcpiGbl_FADT.SciInterrupt);
184128930Sjhb		else {
185128930Sjhb			printf(
186128930Sjhb	"MADT: Forcing active-low polarity and level trigger for SCI\n");
187128930Sjhb			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
188128930Sjhb			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
189128930Sjhb		}
190128930Sjhb	}
191128930Sjhb
192121992Sjhb	/* Third, we register all the I/O APIC's. */
193169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++)
194121992Sjhb		if (ioapics[i].io_apic != NULL)
195121992Sjhb			ioapic_register(ioapics[i].io_apic);
196121992Sjhb
197121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
198121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
199121992Sjhb
200233623Sjhb	free(ioapics, M_MADT);
201233623Sjhb	ioapics = NULL;
202233623Sjhb
203121992Sjhb	return (0);
204121992Sjhb}
205121992Sjhb
206121992Sjhbstatic void
207121992Sjhbmadt_register(void *dummy __unused)
208121992Sjhb{
209121992Sjhb
210121992Sjhb	apic_register_enumerator(&madt_enumerator);
211121992Sjhb}
212215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
213121992Sjhb
214121992Sjhb/*
215121992Sjhb * Call the handler routine for each entry in the MADT table.
216121992Sjhb */
217121992Sjhbstatic void
218197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg)
219121992Sjhb{
220121992Sjhb
221197439Sjhb	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
222197439Sjhb	    handler, arg);
223121992Sjhb}
224121992Sjhb
225121992Sjhbstatic void
226167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
227121992Sjhb{
228167814Sjkim	ACPI_MADT_LOCAL_APIC *proc;
229121992Sjhb	struct lapic_info *la;
230121992Sjhb
231121992Sjhb	switch (entry->Type) {
232167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC:
233121992Sjhb		/*
234121992Sjhb		 * The MADT does not include a BSP flag, so we have to
235121992Sjhb		 * let the MP code figure out which CPU is the BSP on
236121992Sjhb		 * its own.
237121992Sjhb		 */
238167814Sjkim		proc = (ACPI_MADT_LOCAL_APIC *)entry;
239121992Sjhb		if (bootverbose)
240167814Sjkim			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
241167814Sjkim			    proc->Id, proc->ProcessorId,
242167814Sjkim			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
243167814Sjkim			    "enabled" : "disabled");
244167814Sjkim		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
245130310Sjhb			break;
246169395Sjhb		if (proc->Id > MAX_APIC_ID)
247167814Sjkim			panic("%s: CPU ID %u too high", __func__, proc->Id);
248167814Sjkim		la = &lapics[proc->Id];
249130310Sjhb		KASSERT(la->la_enabled == 0,
250167814Sjkim		    ("Duplicate local APIC ID %u", proc->Id));
251130310Sjhb		la->la_enabled = 1;
252129960Sjhb		la->la_acpi_id = proc->ProcessorId;
253167814Sjkim		lapic_create(proc->Id, 0);
254121992Sjhb		break;
255121992Sjhb	}
256121992Sjhb}
257121992Sjhb
258121992Sjhb
259121992Sjhb/*
260121992Sjhb * Add an I/O APIC from an entry in the table.
261121992Sjhb */
262121992Sjhbstatic void
263167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
264121992Sjhb{
265167814Sjkim	ACPI_MADT_IO_APIC *apic;
266121992Sjhb
267121992Sjhb	switch (entry->Type) {
268167814Sjkim	case ACPI_MADT_TYPE_IO_APIC:
269167814Sjkim		apic = (ACPI_MADT_IO_APIC *)entry;
270121992Sjhb		if (bootverbose)
271167814Sjkim			printf(
272167814Sjkim			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
273167814Sjkim			    apic->Id, apic->GlobalIrqBase,
274123326Snjl			    (void *)(uintptr_t)apic->Address);
275169395Sjhb		if (apic->Id > MAX_APIC_ID)
276167814Sjkim			panic("%s: I/O APIC ID %u too high", __func__,
277167814Sjkim			    apic->Id);
278167814Sjkim		if (ioapics[apic->Id].io_apic != NULL)
279167814Sjkim			panic("%s: Double APIC ID %u", __func__, apic->Id);
280189404Sjhb		if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
281189404Sjhb			printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
282189404Sjhb			break;
283189404Sjhb		}
284167814Sjkim		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
285167814Sjkim		    apic->Id, apic->GlobalIrqBase);
286167814Sjkim		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
287121992Sjhb		break;
288121992Sjhb	default:
289121992Sjhb		break;
290121992Sjhb	}
291121992Sjhb}
292121992Sjhb
293121992Sjhb/*
294129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
295129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
296128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
297129128Sjhb * SCI for which we use Active Lo, Level Triggered.
298121992Sjhb */
299128930Sjhbstatic enum intr_polarity
300167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source)
301121992Sjhb{
302121992Sjhb
303167814Sjkim	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
304167814Sjkim	case ACPI_MADT_POLARITY_CONFORMS:
305167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
306128930Sjhb			return (INTR_POLARITY_LOW);
307128930Sjhb		else
308128930Sjhb			return (INTR_POLARITY_HIGH);
309167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
310128930Sjhb		return (INTR_POLARITY_HIGH);
311167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_LOW:
312128930Sjhb		return (INTR_POLARITY_LOW);
313121992Sjhb	default:
314121992Sjhb		panic("Bogus Interrupt Polarity");
315121992Sjhb	}
316121992Sjhb}
317121992Sjhb
318128930Sjhbstatic enum intr_trigger
319167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source)
320121992Sjhb{
321121992Sjhb
322167814Sjkim	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
323167814Sjkim	case ACPI_MADT_TRIGGER_CONFORMS:
324167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
325128930Sjhb			return (INTR_TRIGGER_LEVEL);
326128930Sjhb		else
327128930Sjhb			return (INTR_TRIGGER_EDGE);
328167814Sjkim	case ACPI_MADT_TRIGGER_EDGE:
329128930Sjhb		return (INTR_TRIGGER_EDGE);
330167814Sjkim	case ACPI_MADT_TRIGGER_LEVEL:
331128930Sjhb		return (INTR_TRIGGER_LEVEL);
332121992Sjhb	default:
333121992Sjhb		panic("Bogus Interrupt Trigger Mode");
334121992Sjhb	}
335121992Sjhb}
336121992Sjhb
337121992Sjhb/*
338121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
339121992Sjhb */
340121992Sjhbstatic int
341121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
342121992Sjhb{
343129960Sjhb	int i;
344121992Sjhb
345169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
346130310Sjhb		if (!lapics[i].la_enabled)
347129960Sjhb			continue;
348129960Sjhb		if (lapics[i].la_acpi_id != acpi_id)
349129960Sjhb			continue;
350129960Sjhb		*apic_id = i;
351130310Sjhb		return (0);
352129960Sjhb	}
353129960Sjhb	return (ENOENT);
354121992Sjhb}
355121992Sjhb
356121992Sjhb/*
357121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
358121992Sjhb * interrupt.
359121992Sjhb */
360121992Sjhbstatic int
361121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
362121992Sjhb{
363121992Sjhb	int i, best;
364121992Sjhb
365121992Sjhb	best = -1;
366169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
367121992Sjhb		if (ioapics[i].io_apic == NULL ||
368121992Sjhb		    ioapics[i].io_vector > intr)
369121992Sjhb			continue;
370121992Sjhb		if (best == -1 ||
371121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
372121992Sjhb			best = i;
373121992Sjhb	}
374121992Sjhb	if (best == -1)
375121992Sjhb		return (ENOENT);
376121992Sjhb	*apic = ioapics[best].io_apic;
377121992Sjhb	*pin = intr - ioapics[best].io_vector;
378121992Sjhb	if (*pin > 32)
379121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
380121992Sjhb		    intr);
381121992Sjhb	return (0);
382121992Sjhb}
383121992Sjhb
384121992Sjhb/*
385121992Sjhb * Parse an interrupt source override for an ISA interrupt.
386121992Sjhb */
387121992Sjhbstatic void
388167814Sjkimmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
389121992Sjhb{
390122149Sjhb	void *new_ioapic, *old_ioapic;
391122149Sjhb	u_int new_pin, old_pin;
392128930Sjhb	enum intr_trigger trig;
393128930Sjhb	enum intr_polarity pol;
394128930Sjhb	char buf[64];
395121992Sjhb
396167814Sjkim	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
397167814Sjkim	    intr->GlobalIrq == 2) {
398142257Sjhb		if (bootverbose)
399142257Sjhb			printf("MADT: Skipping timer override\n");
400142257Sjhb		return;
401142257Sjhb	}
402121992Sjhb	if (bootverbose)
403142257Sjhb		printf("MADT: Interrupt override: source %u, irq %u\n",
404167814Sjkim		    intr->SourceIrq, intr->GlobalIrq);
405121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
406167814Sjkim	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
407167814Sjkim		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
408167814Sjkim		    intr->GlobalIrq, intr->SourceIrq);
409121992Sjhb		return;
410121992Sjhb	}
411121992Sjhb
412125048Sjhb	/*
413128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
414128930Sjhb	 * entry.
415128930Sjhb	 */
416167814Sjkim	trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
417167814Sjkim	pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
418128930Sjhb
419128930Sjhb	/*
420125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
421128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
422128329Sjhb	 * force it to use level/lo.
423125048Sjhb	 */
424167814Sjkim	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
425128930Sjhb		madt_found_sci_override = 1;
426128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
427128930Sjhb			if (tolower(buf[0]) == 'e')
428128930Sjhb				trig = INTR_TRIGGER_EDGE;
429128930Sjhb			else if (tolower(buf[0]) == 'l')
430128930Sjhb				trig = INTR_TRIGGER_LEVEL;
431128930Sjhb			else
432128930Sjhb				panic(
433128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
434128930Sjhb				    buf);
435128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
436128930Sjhb			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
437128930Sjhb		}
438128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
439128930Sjhb			if (tolower(buf[0]) == 'h')
440128930Sjhb				pol = INTR_POLARITY_HIGH;
441128930Sjhb			else if (tolower(buf[0]) == 'l')
442128930Sjhb				pol = INTR_POLARITY_LOW;
443128930Sjhb			else
444128930Sjhb				panic(
445128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
446128930Sjhb				    buf);
447128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
448128930Sjhb			    pol == INTR_POLARITY_HIGH ? "high" : "low");
449128930Sjhb		}
450128930Sjhb	}
451125048Sjhb
452128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
453167814Sjkim	if (intr->SourceIrq != intr->GlobalIrq) {
454125048Sjhb		/*
455125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
456125048Sjhb		 * then override the vector we use to setup and allocate
457125048Sjhb		 * the interrupt.
458125048Sjhb		 */
459167814Sjkim		if (intr->GlobalIrq > 15 &&
460167814Sjkim		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
461167814Sjkim			acpi_OverrideInterruptLevel(intr->GlobalIrq);
462122502Sjhb		else
463167814Sjkim			ioapic_remap_vector(new_ioapic, new_pin,
464167814Sjkim			    intr->SourceIrq);
465167814Sjkim		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
466122149Sjhb		    &old_pin) != 0)
467167814Sjkim			printf("MADT: Could not find APIC for source IRQ %u\n",
468167814Sjkim			    intr->SourceIrq);
469122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
470167814Sjkim		    intr->SourceIrq)
471122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
472122149Sjhb	}
473128930Sjhb
474128930Sjhb	/* Program the polarity and trigger mode. */
475128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
476128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
477121992Sjhb}
478121992Sjhb
479121992Sjhb/*
480121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
481121992Sjhb */
482121992Sjhbstatic void
483167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
484121992Sjhb{
485121992Sjhb	void *ioapic;
486121992Sjhb	u_int pin;
487121992Sjhb
488167814Sjkim	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
489167814Sjkim		printf("MADT: Could not find APIC for vector %u\n",
490167814Sjkim		    nmi->GlobalIrq);
491121992Sjhb		return;
492121992Sjhb	}
493121992Sjhb
494121992Sjhb	ioapic_set_nmi(ioapic, pin);
495167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
496121992Sjhb		ioapic_set_triggermode(ioapic, pin,
497167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
498167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
499121992Sjhb		ioapic_set_polarity(ioapic, pin,
500167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
501121992Sjhb}
502121992Sjhb
503121992Sjhb/*
504121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
505121992Sjhb */
506121992Sjhbstatic void
507167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
508121992Sjhb{
509121992Sjhb	u_int apic_id, pin;
510121992Sjhb
511123326Snjl	if (nmi->ProcessorId == 0xff)
512121992Sjhb		apic_id = APIC_ID_ALL;
513123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
514121992Sjhb		if (bootverbose)
515167814Sjkim			printf("MADT: Ignoring local NMI routed to "
516167814Sjkim			    "ACPI CPU %u\n", nmi->ProcessorId);
517121992Sjhb		return;
518121992Sjhb	}
519123326Snjl	if (nmi->Lint == 0)
520259140Sjhb		pin = APIC_LVT_LINT0;
521121992Sjhb	else
522259140Sjhb		pin = APIC_LVT_LINT1;
523121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
524167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
525121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
526167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
527167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
528121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
529167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
530121992Sjhb}
531121992Sjhb
532121992Sjhb/*
533121992Sjhb * Parse interrupt entries.
534121992Sjhb */
535121992Sjhbstatic void
536167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
537121992Sjhb{
538121992Sjhb
539121992Sjhb	switch (entry->Type) {
540167814Sjkim	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
541121992Sjhb		madt_parse_interrupt_override(
542167814Sjkim			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
543121992Sjhb		break;
544167814Sjkim	case ACPI_MADT_TYPE_NMI_SOURCE:
545167814Sjkim		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
546121992Sjhb		break;
547167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
548167814Sjkim		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
549121992Sjhb		break;
550121992Sjhb	}
551121992Sjhb}
552121992Sjhb
553121992Sjhb/*
554121992Sjhb * Setup per-CPU ACPI IDs.
555121992Sjhb */
556121992Sjhbstatic void
557121992Sjhbmadt_set_ids(void *dummy)
558121992Sjhb{
559129960Sjhb	struct lapic_info *la;
560121992Sjhb	struct pcpu *pc;
561129960Sjhb	u_int i;
562121992Sjhb
563121992Sjhb	if (madt == NULL)
564121992Sjhb		return;
565209059Sjhb	CPU_FOREACH(i) {
566121992Sjhb		pc = pcpu_find(i);
567167814Sjkim		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
568129960Sjhb		la = &lapics[pc->pc_apic_id];
569130310Sjhb		if (!la->la_enabled)
570129960Sjhb			panic("APIC: CPU with APIC ID %u is not enabled",
571129960Sjhb			    pc->pc_apic_id);
572129960Sjhb		pc->pc_acpi_id = la->la_acpi_id;
573129960Sjhb		if (bootverbose)
574129960Sjhb			printf("APIC: CPU %u has ACPI ID %u\n", i,
575129960Sjhb			    la->la_acpi_id);
576121992Sjhb	}
577121992Sjhb}
578256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
579