madt.c revision 269512
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 269512 2014-08-04 08:58:50Z royger $");
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>
42121992Sjhb
43193530Sjkim#include <contrib/dev/acpica/include/acpi.h>
44193530Sjkim#include <contrib/dev/acpica/include/actables.h>
45193530Sjkim
46121992Sjhb#include <dev/acpica/acpivar.h>
47121992Sjhb#include <dev/pci/pcivar.h>
48121992Sjhb
49121992Sjhb/* These two arrays are indexed by APIC IDs. */
50233623Sjhbstatic struct {
51121992Sjhb	void *io_apic;
52121992Sjhb	UINT32 io_vector;
53233623Sjhb} *ioapics;
54121992Sjhb
55233623Sjhbstatic struct lapic_info {
56121992Sjhb	u_int la_enabled:1;
57129960Sjhb	u_int la_acpi_id:8;
58233623Sjhb} lapics[MAX_APIC_ID + 1];
59121992Sjhb
60269512Sroygerint madt_found_sci_override;
61167814Sjkimstatic ACPI_TABLE_MADT *madt;
62121992Sjhbstatic vm_paddr_t madt_physaddr;
63121992Sjhbstatic vm_offset_t madt_length;
64121992Sjhb
65227293Sedstatic MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
66121992Sjhb
67167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
68167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
69121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
70121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
71167814Sjkimstatic void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
72167814Sjkimstatic void	madt_parse_interrupt_override(
73167814Sjkim		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
74167814Sjkimstatic void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
75167814Sjkim		    void *arg __unused);
76167814Sjkimstatic void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
77167814Sjkimstatic void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
78121992Sjhbstatic int	madt_probe(void);
79121992Sjhbstatic int	madt_probe_cpus(void);
80167814Sjkimstatic void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
81167814Sjkim		    void *arg __unused);
82121992Sjhbstatic void	madt_register(void *dummy);
83121992Sjhbstatic int	madt_setup_local(void);
84121992Sjhbstatic int	madt_setup_io(void);
85197439Sjhbstatic void	madt_walk_table(acpi_subtable_handler *handler, void *arg);
86121992Sjhb
87121992Sjhbstatic struct apic_enumerator madt_enumerator = {
88121992Sjhb	"MADT",
89121992Sjhb	madt_probe,
90121992Sjhb	madt_probe_cpus,
91121992Sjhb	madt_setup_local,
92121992Sjhb	madt_setup_io
93121992Sjhb};
94121992Sjhb
95121992Sjhb/*
96121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
97121992Sjhb */
98121992Sjhbstatic int
99121992Sjhbmadt_probe(void)
100121992Sjhb{
101121992Sjhb
102197439Sjhb	madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
103197439Sjhb	if (madt_physaddr == 0)
104121992Sjhb		return (ENXIO);
105269511Sroyger	return (-50);
106121992Sjhb}
107121992Sjhb
108121992Sjhb/*
109121992Sjhb * Run through the MP table enumerating CPUs.
110121992Sjhb */
111121992Sjhbstatic int
112121992Sjhbmadt_probe_cpus(void)
113121992Sjhb{
114121992Sjhb
115197439Sjhb	madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
116197439Sjhb	madt_length = madt->Header.Length;
117121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
118121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
119197439Sjhb	acpi_unmap_table(madt);
120121992Sjhb	madt = NULL;
121121992Sjhb	return (0);
122121992Sjhb}
123121992Sjhb
124121992Sjhb/*
125121992Sjhb * Initialize the local APIC on the BSP.
126121992Sjhb */
127121992Sjhbstatic int
128121992Sjhbmadt_setup_local(void)
129121992Sjhb{
130121992Sjhb
131161223Sjhb	madt = pmap_mapbios(madt_physaddr, madt_length);
132167814Sjkim	lapic_init(madt->Address);
133121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
134167814Sjkim	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
135167814Sjkim	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
136121992Sjhb
137121992Sjhb	/*
138121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
139121992Sjhb	 * perhaps emit a warning here if we find one?
140121992Sjhb	 */
141121992Sjhb	return (0);
142121992Sjhb}
143121992Sjhb
144121992Sjhb/*
145125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
146121992Sjhb */
147121992Sjhbstatic int
148121992Sjhbmadt_setup_io(void)
149121992Sjhb{
150128930Sjhb	void *ioapic;
151128930Sjhb	u_int pin;
152121992Sjhb	int i;
153121992Sjhb
154125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
155125048Sjhb	i = acpi_Startup();
156125048Sjhb	if (ACPI_FAILURE(i)) {
157125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
158125048Sjhb		    AcpiFormatException(i));
159125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
160125048Sjhb		panic("Using MADT but ACPI doesn't work");
161125048Sjhb	}
162233623Sjhb
163233623Sjhb	ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
164233623Sjhb	    M_WAITOK | M_ZERO);
165233623Sjhb
166121992Sjhb	/* First, we run through adding I/O APIC's. */
167121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
168121992Sjhb
169121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
170121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
171121992Sjhb
172128930Sjhb	/*
173128930Sjhb	 * If there was not an explicit override entry for the SCI,
174128930Sjhb	 * force it to use level trigger and active-low polarity.
175128930Sjhb	 */
176128930Sjhb	if (!madt_found_sci_override) {
177167814Sjkim		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
178167814Sjkim		    &pin) != 0)
179167814Sjkim			printf("MADT: Could not find APIC for SCI IRQ %u\n",
180167814Sjkim			    AcpiGbl_FADT.SciInterrupt);
181128930Sjhb		else {
182128930Sjhb			printf(
183128930Sjhb	"MADT: Forcing active-low polarity and level trigger for SCI\n");
184128930Sjhb			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
185128930Sjhb			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
186128930Sjhb		}
187128930Sjhb	}
188128930Sjhb
189121992Sjhb	/* Third, we register all the I/O APIC's. */
190169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++)
191121992Sjhb		if (ioapics[i].io_apic != NULL)
192121992Sjhb			ioapic_register(ioapics[i].io_apic);
193121992Sjhb
194121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
195121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
196121992Sjhb
197233623Sjhb	free(ioapics, M_MADT);
198233623Sjhb	ioapics = NULL;
199233623Sjhb
200121992Sjhb	return (0);
201121992Sjhb}
202121992Sjhb
203121992Sjhbstatic void
204121992Sjhbmadt_register(void *dummy __unused)
205121992Sjhb{
206121992Sjhb
207121992Sjhb	apic_register_enumerator(&madt_enumerator);
208121992Sjhb}
209215009SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
210121992Sjhb
211121992Sjhb/*
212121992Sjhb * Call the handler routine for each entry in the MADT table.
213121992Sjhb */
214121992Sjhbstatic void
215197439Sjhbmadt_walk_table(acpi_subtable_handler *handler, void *arg)
216121992Sjhb{
217121992Sjhb
218197439Sjhb	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
219197439Sjhb	    handler, arg);
220121992Sjhb}
221121992Sjhb
222121992Sjhbstatic void
223167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
224121992Sjhb{
225167814Sjkim	ACPI_MADT_LOCAL_APIC *proc;
226121992Sjhb	struct lapic_info *la;
227121992Sjhb
228121992Sjhb	switch (entry->Type) {
229167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC:
230121992Sjhb		/*
231121992Sjhb		 * The MADT does not include a BSP flag, so we have to
232121992Sjhb		 * let the MP code figure out which CPU is the BSP on
233121992Sjhb		 * its own.
234121992Sjhb		 */
235167814Sjkim		proc = (ACPI_MADT_LOCAL_APIC *)entry;
236121992Sjhb		if (bootverbose)
237167814Sjkim			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
238167814Sjkim			    proc->Id, proc->ProcessorId,
239167814Sjkim			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
240167814Sjkim			    "enabled" : "disabled");
241167814Sjkim		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
242130310Sjhb			break;
243169395Sjhb		if (proc->Id > MAX_APIC_ID)
244167814Sjkim			panic("%s: CPU ID %u too high", __func__, proc->Id);
245167814Sjkim		la = &lapics[proc->Id];
246130310Sjhb		KASSERT(la->la_enabled == 0,
247167814Sjkim		    ("Duplicate local APIC ID %u", proc->Id));
248130310Sjhb		la->la_enabled = 1;
249129960Sjhb		la->la_acpi_id = proc->ProcessorId;
250167814Sjkim		lapic_create(proc->Id, 0);
251121992Sjhb		break;
252121992Sjhb	}
253121992Sjhb}
254121992Sjhb
255121992Sjhb
256121992Sjhb/*
257121992Sjhb * Add an I/O APIC from an entry in the table.
258121992Sjhb */
259121992Sjhbstatic void
260167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
261121992Sjhb{
262167814Sjkim	ACPI_MADT_IO_APIC *apic;
263121992Sjhb
264121992Sjhb	switch (entry->Type) {
265167814Sjkim	case ACPI_MADT_TYPE_IO_APIC:
266167814Sjkim		apic = (ACPI_MADT_IO_APIC *)entry;
267121992Sjhb		if (bootverbose)
268167814Sjkim			printf(
269167814Sjkim			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
270167814Sjkim			    apic->Id, apic->GlobalIrqBase,
271123326Snjl			    (void *)(uintptr_t)apic->Address);
272169395Sjhb		if (apic->Id > MAX_APIC_ID)
273167814Sjkim			panic("%s: I/O APIC ID %u too high", __func__,
274167814Sjkim			    apic->Id);
275167814Sjkim		if (ioapics[apic->Id].io_apic != NULL)
276167814Sjkim			panic("%s: Double APIC ID %u", __func__, apic->Id);
277189404Sjhb		if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
278189404Sjhb			printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
279189404Sjhb			break;
280189404Sjhb		}
281167814Sjkim		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
282167814Sjkim		    apic->Id, apic->GlobalIrqBase);
283167814Sjkim		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
284121992Sjhb		break;
285121992Sjhb	default:
286121992Sjhb		break;
287121992Sjhb	}
288121992Sjhb}
289121992Sjhb
290121992Sjhb/*
291129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
292129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
293128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
294129128Sjhb * SCI for which we use Active Lo, Level Triggered.
295121992Sjhb */
296128930Sjhbstatic enum intr_polarity
297167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source)
298121992Sjhb{
299121992Sjhb
300167814Sjkim	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
301263859Stakawata	default:
302269184Sakiyama		printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
303263859Stakawata		/* FALLTHROUGH*/
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:
312263859Stakawata		return (INTR_POLARITY_LOW);
313121992Sjhb	}
314121992Sjhb}
315121992Sjhb
316128930Sjhbstatic enum intr_trigger
317167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source)
318121992Sjhb{
319121992Sjhb
320167814Sjkim	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
321263859Stakawata	default:
322269184Sakiyama		printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
323263859Stakawata		/*FALLTHROUGH*/
324167814Sjkim	case ACPI_MADT_TRIGGER_CONFORMS:
325167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
326128930Sjhb			return (INTR_TRIGGER_LEVEL);
327128930Sjhb		else
328128930Sjhb			return (INTR_TRIGGER_EDGE);
329167814Sjkim	case ACPI_MADT_TRIGGER_EDGE:
330128930Sjhb		return (INTR_TRIGGER_EDGE);
331167814Sjkim	case ACPI_MADT_TRIGGER_LEVEL:
332263859Stakawata		return (INTR_TRIGGER_LEVEL);
333121992Sjhb	}
334121992Sjhb}
335121992Sjhb
336121992Sjhb/*
337121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
338121992Sjhb */
339121992Sjhbstatic int
340121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
341121992Sjhb{
342129960Sjhb	int i;
343121992Sjhb
344169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
345130310Sjhb		if (!lapics[i].la_enabled)
346129960Sjhb			continue;
347129960Sjhb		if (lapics[i].la_acpi_id != acpi_id)
348129960Sjhb			continue;
349129960Sjhb		*apic_id = i;
350130310Sjhb		return (0);
351129960Sjhb	}
352129960Sjhb	return (ENOENT);
353121992Sjhb}
354121992Sjhb
355121992Sjhb/*
356121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
357121992Sjhb * interrupt.
358121992Sjhb */
359121992Sjhbstatic int
360121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
361121992Sjhb{
362121992Sjhb	int i, best;
363121992Sjhb
364121992Sjhb	best = -1;
365169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
366121992Sjhb		if (ioapics[i].io_apic == NULL ||
367121992Sjhb		    ioapics[i].io_vector > intr)
368121992Sjhb			continue;
369121992Sjhb		if (best == -1 ||
370121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
371121992Sjhb			best = i;
372121992Sjhb	}
373121992Sjhb	if (best == -1)
374121992Sjhb		return (ENOENT);
375121992Sjhb	*apic = ioapics[best].io_apic;
376121992Sjhb	*pin = intr - ioapics[best].io_vector;
377121992Sjhb	if (*pin > 32)
378121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
379121992Sjhb		    intr);
380121992Sjhb	return (0);
381121992Sjhb}
382121992Sjhb
383269512Sroygervoid
384269512Sroygermadt_parse_interrupt_values(void *entry,
385269512Sroyger    enum intr_trigger *trig, enum intr_polarity *pol)
386121992Sjhb{
387269512Sroyger	ACPI_MADT_INTERRUPT_OVERRIDE *intr;
388128930Sjhb	char buf[64];
389121992Sjhb
390269512Sroyger	intr = entry;
391269512Sroyger
392121992Sjhb	if (bootverbose)
393142257Sjhb		printf("MADT: Interrupt override: source %u, irq %u\n",
394167814Sjkim		    intr->SourceIrq, intr->GlobalIrq);
395121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
396121992Sjhb
397125048Sjhb	/*
398128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
399128930Sjhb	 * entry.
400128930Sjhb	 */
401269512Sroyger	*trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
402269512Sroyger	*pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
403269512Sroyger
404128930Sjhb	/*
405125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
406128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
407128329Sjhb	 * force it to use level/lo.
408125048Sjhb	 */
409167814Sjkim	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
410128930Sjhb		madt_found_sci_override = 1;
411128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
412128930Sjhb			if (tolower(buf[0]) == 'e')
413269512Sroyger				*trig = INTR_TRIGGER_EDGE;
414128930Sjhb			else if (tolower(buf[0]) == 'l')
415269512Sroyger				*trig = INTR_TRIGGER_LEVEL;
416128930Sjhb			else
417128930Sjhb				panic(
418128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
419128930Sjhb				    buf);
420128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
421269512Sroyger			    *trig == INTR_TRIGGER_EDGE ? "edge" : "level");
422128930Sjhb		}
423128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
424128930Sjhb			if (tolower(buf[0]) == 'h')
425269512Sroyger				*pol = INTR_POLARITY_HIGH;
426128930Sjhb			else if (tolower(buf[0]) == 'l')
427269512Sroyger				*pol = INTR_POLARITY_LOW;
428128930Sjhb			else
429128930Sjhb				panic(
430128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
431128930Sjhb				    buf);
432128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
433269512Sroyger			    *pol == INTR_POLARITY_HIGH ? "high" : "low");
434128930Sjhb		}
435128930Sjhb	}
436269512Sroyger}
437125048Sjhb
438269512Sroyger/*
439269512Sroyger * Parse an interrupt source override for an ISA interrupt.
440269512Sroyger */
441269512Sroygerstatic void
442269512Sroygermadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
443269512Sroyger{
444269512Sroyger	void *new_ioapic, *old_ioapic;
445269512Sroyger	u_int new_pin, old_pin;
446269512Sroyger	enum intr_trigger trig;
447269512Sroyger	enum intr_polarity pol;
448269512Sroyger
449269512Sroyger	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
450269512Sroyger	    intr->GlobalIrq == 2) {
451269512Sroyger		if (bootverbose)
452269512Sroyger			printf("MADT: Skipping timer override\n");
453269512Sroyger		return;
454269512Sroyger	}
455269512Sroyger
456269512Sroyger	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
457269512Sroyger		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
458269512Sroyger		    intr->GlobalIrq, intr->SourceIrq);
459269512Sroyger		return;
460269512Sroyger	}
461269512Sroyger
462269512Sroyger	madt_parse_interrupt_values(intr, &trig, &pol);
463269512Sroyger
464128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
465167814Sjkim	if (intr->SourceIrq != intr->GlobalIrq) {
466125048Sjhb		/*
467125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
468125048Sjhb		 * then override the vector we use to setup and allocate
469125048Sjhb		 * the interrupt.
470125048Sjhb		 */
471167814Sjkim		if (intr->GlobalIrq > 15 &&
472167814Sjkim		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
473167814Sjkim			acpi_OverrideInterruptLevel(intr->GlobalIrq);
474122502Sjhb		else
475167814Sjkim			ioapic_remap_vector(new_ioapic, new_pin,
476167814Sjkim			    intr->SourceIrq);
477167814Sjkim		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
478122149Sjhb		    &old_pin) != 0)
479167814Sjkim			printf("MADT: Could not find APIC for source IRQ %u\n",
480167814Sjkim			    intr->SourceIrq);
481122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
482167814Sjkim		    intr->SourceIrq)
483122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
484122149Sjhb	}
485128930Sjhb
486128930Sjhb	/* Program the polarity and trigger mode. */
487128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
488128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
489121992Sjhb}
490121992Sjhb
491121992Sjhb/*
492121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
493121992Sjhb */
494121992Sjhbstatic void
495167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
496121992Sjhb{
497121992Sjhb	void *ioapic;
498121992Sjhb	u_int pin;
499121992Sjhb
500167814Sjkim	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
501167814Sjkim		printf("MADT: Could not find APIC for vector %u\n",
502167814Sjkim		    nmi->GlobalIrq);
503121992Sjhb		return;
504121992Sjhb	}
505121992Sjhb
506121992Sjhb	ioapic_set_nmi(ioapic, pin);
507167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
508121992Sjhb		ioapic_set_triggermode(ioapic, pin,
509167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
510263794Stakawata	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
511121992Sjhb		ioapic_set_polarity(ioapic, pin,
512167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
513121992Sjhb}
514121992Sjhb
515121992Sjhb/*
516121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
517121992Sjhb */
518121992Sjhbstatic void
519167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
520121992Sjhb{
521121992Sjhb	u_int apic_id, pin;
522121992Sjhb
523123326Snjl	if (nmi->ProcessorId == 0xff)
524121992Sjhb		apic_id = APIC_ID_ALL;
525123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
526121992Sjhb		if (bootverbose)
527167814Sjkim			printf("MADT: Ignoring local NMI routed to "
528167814Sjkim			    "ACPI CPU %u\n", nmi->ProcessorId);
529121992Sjhb		return;
530121992Sjhb	}
531123326Snjl	if (nmi->Lint == 0)
532259140Sjhb		pin = APIC_LVT_LINT0;
533121992Sjhb	else
534259140Sjhb		pin = APIC_LVT_LINT1;
535121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
536167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
537121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
538167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
539167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
540121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
541167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
542121992Sjhb}
543121992Sjhb
544121992Sjhb/*
545121992Sjhb * Parse interrupt entries.
546121992Sjhb */
547121992Sjhbstatic void
548167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
549121992Sjhb{
550121992Sjhb
551121992Sjhb	switch (entry->Type) {
552167814Sjkim	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
553121992Sjhb		madt_parse_interrupt_override(
554167814Sjkim			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
555121992Sjhb		break;
556167814Sjkim	case ACPI_MADT_TYPE_NMI_SOURCE:
557167814Sjkim		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
558121992Sjhb		break;
559167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
560167814Sjkim		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
561121992Sjhb		break;
562121992Sjhb	}
563121992Sjhb}
564121992Sjhb
565121992Sjhb/*
566121992Sjhb * Setup per-CPU ACPI IDs.
567121992Sjhb */
568121992Sjhbstatic void
569121992Sjhbmadt_set_ids(void *dummy)
570121992Sjhb{
571129960Sjhb	struct lapic_info *la;
572121992Sjhb	struct pcpu *pc;
573129960Sjhb	u_int i;
574121992Sjhb
575121992Sjhb	if (madt == NULL)
576121992Sjhb		return;
577209059Sjhb	CPU_FOREACH(i) {
578121992Sjhb		pc = pcpu_find(i);
579167814Sjkim		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
580129960Sjhb		la = &lapics[pc->pc_apic_id];
581130310Sjhb		if (!la->la_enabled)
582129960Sjhb			panic("APIC: CPU with APIC ID %u is not enabled",
583129960Sjhb			    pc->pc_apic_id);
584129960Sjhb		pc->pc_acpi_id = la->la_acpi_id;
585129960Sjhb		if (bootverbose)
586129960Sjhb			printf("APIC: CPU %u has ACPI ID %u\n", i,
587129960Sjhb			    la->la_acpi_id);
588121992Sjhb	}
589121992Sjhb}
590256073SgibbsSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
591