madt.c revision 122502
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/i386/acpica/madt.c 122502 2003-11-11 18:20:10Z 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
40121992Sjhb#include <vm/vm.h>
41121992Sjhb#include <vm/vm_param.h>
42121992Sjhb#include <vm/pmap.h>
43121992Sjhb
44121992Sjhb#include <machine/apicreg.h>
45121992Sjhb#include <machine/frame.h>
46121992Sjhb#include <machine/intr_machdep.h>
47121992Sjhb#include <machine/apicvar.h>
48121992Sjhb#include <machine/md_var.h>
49121992Sjhb#include <machine/specialreg.h>
50121992Sjhb
51121992Sjhb#include "acpi.h"
52121992Sjhb#include <dev/acpica/acpivar.h>
53121992Sjhb#include <dev/acpica/madt.h>
54121992Sjhb#include <dev/pci/pcivar.h>
55121992Sjhb
56122434Sjhb#define	NIOAPICS		32	/* Max number of I/O APICs */
57122434Sjhb#define	NLAPICS			32	/* Max number of local APICs */
58121992Sjhb
59121992Sjhbtypedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
60121992Sjhb
61121992Sjhb/* These two arrays are indexed by APIC IDs. */
62121992Sjhbstruct ioapic_info {
63121992Sjhb	void *io_apic;
64121992Sjhb	UINT32 io_vector;
65121992Sjhb} ioapics[NIOAPICS];
66121992Sjhb
67121992Sjhbstruct lapic_info {
68121992Sjhb	u_int la_present:1;
69121992Sjhb	u_int la_enabled:1;
70121992Sjhb	u_int la_apic_id:8;
71121992Sjhb} lapics[NLAPICS + 1];
72121992Sjhb
73121992Sjhbstatic APIC_TABLE *madt;
74121992Sjhbstatic vm_paddr_t madt_physaddr;
75121992Sjhbstatic vm_offset_t madt_length;
76121992Sjhb
77121992SjhbMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
78121992Sjhb
79121992Sjhbstatic u_char	interrupt_polarity(UINT16 Polarity);
80121992Sjhbstatic u_char	interrupt_trigger(UINT16 TriggerMode);
81121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
82121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
83121992Sjhbstatic void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
84121992Sjhbstatic void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
85121992Sjhbstatic void	madt_parse_apics(APIC_HEADER *entry, void *arg);
86121992Sjhbstatic void	madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr);
87121992Sjhbstatic void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
88121992Sjhbstatic void	madt_parse_local_nmi(LAPIC_NMI *nmi);
89121992Sjhbstatic void	madt_parse_nmi(NMI *nmi);
90121992Sjhbstatic int	madt_probe(void);
91121992Sjhbstatic int	madt_probe_cpus(void);
92121992Sjhbstatic void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
93121992Sjhbstatic int	madt_probe_table(vm_paddr_t address);
94121992Sjhbstatic void	madt_register(void *dummy);
95121992Sjhbstatic int	madt_setup_local(void);
96121992Sjhbstatic int	madt_setup_io(void);
97121992Sjhbstatic void	madt_unmap(void *data, vm_offset_t length);
98121992Sjhbstatic void	madt_unmap_table(void *table);
99121992Sjhbstatic void	madt_walk_table(madt_entry_handler *handler, void *arg);
100121992Sjhb
101121992Sjhbstatic struct apic_enumerator madt_enumerator = {
102121992Sjhb	"MADT",
103121992Sjhb	madt_probe,
104121992Sjhb	madt_probe_cpus,
105121992Sjhb	madt_setup_local,
106121992Sjhb	madt_setup_io
107121992Sjhb};
108121992Sjhb
109121992Sjhb/*
110121992Sjhb * Code to abuse the crashdump map to map in the tables for the early
111121992Sjhb * probe.  We cheat and make the following assumptions about how we
112121992Sjhb * use this KVA: page 0 is used to map in the first page of each table
113121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the
114121992Sjhb * RSDT or XSDT.  The offset is in pages; the length is in bytes.
115121992Sjhb */
116121992Sjhbstatic void *
117121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length)
118121992Sjhb{
119121992Sjhb	vm_offset_t va, off;
120121992Sjhb	void *data;
121121992Sjhb
122121992Sjhb	off = pa & PAGE_MASK;
123121992Sjhb	length = roundup(length + off, PAGE_SIZE);
124121992Sjhb	pa = pa & PG_FRAME;
125121992Sjhb	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
126121992Sjhb	    (offset * PAGE_SIZE);
127121992Sjhb	data = (void *)(va + off);
128121992Sjhb	length -= PAGE_SIZE;
129121992Sjhb	while (length > 0) {
130121992Sjhb		va += PAGE_SIZE;
131121992Sjhb		pa += PAGE_SIZE;
132121992Sjhb		length -= PAGE_SIZE;
133121992Sjhb		pmap_kenter(va, pa);
134121992Sjhb		invlpg(va);
135121992Sjhb	}
136121992Sjhb	return (data);
137121992Sjhb}
138121992Sjhb
139121992Sjhbstatic void
140121992Sjhbmadt_unmap(void *data, vm_offset_t length)
141121992Sjhb{
142121992Sjhb	vm_offset_t va, off;
143121992Sjhb
144121992Sjhb	va = (vm_offset_t)data;
145121992Sjhb	off = va & PAGE_MASK;
146121992Sjhb	length = roundup(length + off, PAGE_SIZE);
147121992Sjhb	va &= ~PAGE_MASK;
148121992Sjhb	while (length > 0) {
149121992Sjhb		pmap_kremove(va);
150121992Sjhb		invlpg(va);
151121992Sjhb		va += PAGE_SIZE;
152121992Sjhb		length -= PAGE_SIZE;
153121992Sjhb	}
154121992Sjhb}
155121992Sjhb
156121992Sjhbstatic void *
157121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig)
158121992Sjhb{
159121992Sjhb	ACPI_TABLE_HEADER *header;
160121992Sjhb	vm_offset_t length;
161121992Sjhb
162121992Sjhb	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
163121992Sjhb	if (strncmp(header->Signature, sig, 4) != 0) {
164121992Sjhb		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
165121992Sjhb		return (NULL);
166121992Sjhb	}
167121992Sjhb	length = header->Length;
168121992Sjhb	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
169121992Sjhb	return (madt_map(pa, offset, length));
170121992Sjhb}
171121992Sjhb
172121992Sjhbstatic void
173121992Sjhbmadt_unmap_table(void *table)
174121992Sjhb{
175121992Sjhb	ACPI_TABLE_HEADER *header;
176121992Sjhb
177121992Sjhb	header = (ACPI_TABLE_HEADER *)table;
178121992Sjhb	madt_unmap(table, header->Length);
179121992Sjhb}
180121992Sjhb
181121992Sjhb/*
182121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
183121992Sjhb */
184121992Sjhbstatic int
185121992Sjhbmadt_probe(void)
186121992Sjhb{
187121992Sjhb	ACPI_POINTER rsdp_ptr;
188121992Sjhb	RSDP_DESCRIPTOR *rsdp;
189121992Sjhb	RSDT_DESCRIPTOR *rsdt;
190121992Sjhb	XSDT_DESCRIPTOR *xsdt;
191121992Sjhb	int i, count;
192121992Sjhb
193121992Sjhb	if (resource_disabled("acpi", 0))
194121992Sjhb		return (ENXIO);
195121992Sjhb
196121992Sjhb	/*
197121992Sjhb	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
198121992Sjhb	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
199121992Sjhb	 * pmap_mapdev() to map the RSDP.
200121992Sjhb	 */
201121992Sjhb	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
202121992Sjhb		return (ENXIO);
203121992Sjhb	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
204121992Sjhb	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
205121992Sjhb	if (rsdp == NULL) {
206121992Sjhb		if (bootverbose)
207121992Sjhb			printf("MADT: Failed to map RSDP\n");
208121992Sjhb		return (ENXIO);
209121992Sjhb	}
210121992Sjhb
211121992Sjhb	/*
212121992Sjhb	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
213121992Sjhb	 * We map the XSDT and RSDT at page 1 in the crashdump area.
214121992Sjhb	 * Page 0 is used to map in the headers of candidate ACPI tables.
215121992Sjhb	 */
216121992Sjhb	if (rsdp->Revision >= 2) {
217121992Sjhb		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
218121992Sjhb		if (xsdt == NULL) {
219121992Sjhb			if (bootverbose)
220121992Sjhb				printf("MADT: Failed to map XSDT\n");
221121992Sjhb			return (ENXIO);
222121992Sjhb		}
223121992Sjhb		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
224121992Sjhb		    sizeof(UINT64);
225121992Sjhb		for (i = 0; i < count; i++)
226121992Sjhb			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
227121992Sjhb				break;
228121992Sjhb		madt_unmap_table(xsdt);
229121992Sjhb	} else {
230121992Sjhb		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
231121992Sjhb		if (rsdt == NULL) {
232121992Sjhb			if (bootverbose)
233121992Sjhb				printf("MADT: Failed to map RSDT\n");
234121992Sjhb			return (ENXIO);
235121992Sjhb		}
236121992Sjhb		count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
237121992Sjhb		    sizeof(UINT32);
238121992Sjhb		for (i = 0; i < count; i++)
239121992Sjhb			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
240121992Sjhb				break;
241121992Sjhb		madt_unmap_table(rsdt);
242121992Sjhb	}
243121992Sjhb	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
244121992Sjhb	if (madt_physaddr == 0) {
245121992Sjhb		if (bootverbose)
246121992Sjhb			printf("MADT: No MADT table found\n");
247121992Sjhb		return (ENXIO);
248121992Sjhb	}
249121992Sjhb	if (bootverbose)
250122016Speter		printf("MADT: Found table at 0x%jx\n",
251122016Speter		    (uintmax_t)madt_physaddr);
252121992Sjhb
253121992Sjhb	return (0);
254121992Sjhb}
255121992Sjhb
256121992Sjhb/*
257121992Sjhb * See if a given ACPI table is the MADT.
258121992Sjhb */
259121992Sjhbstatic int
260121992Sjhbmadt_probe_table(vm_paddr_t address)
261121992Sjhb{
262121992Sjhb	ACPI_TABLE_HEADER *table;
263121992Sjhb
264121992Sjhb	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
265121992Sjhb	if (table == NULL) {
266121992Sjhb		if (bootverbose)
267122016Speter			printf("MADT: Failed to map table at 0x%jx\n",
268122016Speter			    (uintmax_t)address);
269121992Sjhb		return (0);
270121992Sjhb	}
271121992Sjhb	if (bootverbose)
272122016Speter		printf("Table '%.4s' at 0x%jx\n", table->Signature,
273122016Speter		    (uintmax_t)address);
274121992Sjhb
275121992Sjhb	/* XXX: Verify checksum? */
276121992Sjhb	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
277121992Sjhb		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
278121992Sjhb		return (0);
279121992Sjhb	}
280121992Sjhb	madt_physaddr = address;
281121992Sjhb	madt_length = table->Length;
282121992Sjhb	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
283121992Sjhb	return (1);
284121992Sjhb}
285121992Sjhb
286121992Sjhb/*
287121992Sjhb * Run through the MP table enumerating CPUs.
288121992Sjhb */
289121992Sjhbstatic int
290121992Sjhbmadt_probe_cpus(void)
291121992Sjhb{
292121992Sjhb
293121992Sjhb	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
294121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
295121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
296121992Sjhb	madt_unmap_table(madt);
297121992Sjhb	madt = NULL;
298121992Sjhb	return (0);
299121992Sjhb}
300121992Sjhb
301121992Sjhb/*
302121992Sjhb * Initialize the local APIC on the BSP.
303121992Sjhb */
304121992Sjhbstatic int
305121992Sjhbmadt_setup_local(void)
306121992Sjhb{
307121992Sjhb
308121992Sjhb	madt = pmap_mapdev(madt_physaddr, madt_length);
309121992Sjhb	lapic_init((uintptr_t)madt->LocalApicAddress);
310121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
311121992Sjhb	    sizeof(madt->Header.OemId), madt->Header.OemId,
312121992Sjhb	    sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
313121992Sjhb
314121992Sjhb	/*
315121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
316121992Sjhb	 * perhaps emit a warning here if we find one?
317121992Sjhb	 */
318121992Sjhb	return (0);
319121992Sjhb}
320121992Sjhb
321121992Sjhb/*
322121992Sjhb * Run through the MP table enumerating I/O APICs.
323121992Sjhb */
324121992Sjhbstatic int
325121992Sjhbmadt_setup_io(void)
326121992Sjhb{
327121992Sjhb	int i;
328121992Sjhb
329121992Sjhb	/* First, we run through adding I/O APIC's. */
330121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
331121992Sjhb
332121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
333121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
334121992Sjhb
335121992Sjhb	/* Third, we register all the I/O APIC's. */
336121992Sjhb	for (i = 0; i < NIOAPICS; i++)
337121992Sjhb		if (ioapics[i].io_apic != NULL)
338121992Sjhb			ioapic_register(ioapics[i].io_apic);
339121992Sjhb
340121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
341121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
342121992Sjhb
343121992Sjhb	return (0);
344121992Sjhb}
345121992Sjhb
346121992Sjhbstatic void
347121992Sjhbmadt_register(void *dummy __unused)
348121992Sjhb{
349121992Sjhb
350121992Sjhb	apic_register_enumerator(&madt_enumerator);
351121992Sjhb}
352121992SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,
353121992Sjhb    madt_register, NULL)
354121992Sjhb
355121992Sjhb/*
356121992Sjhb * Call the handler routine for each entry in the MADT table.
357121992Sjhb */
358121992Sjhbstatic void
359121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg)
360121992Sjhb{
361121992Sjhb	APIC_HEADER *entry;
362121992Sjhb	u_char *p, *end;
363121992Sjhb
364121992Sjhb	end = (u_char *)(madt) + madt->Header.Length;
365121992Sjhb	for (p = (u_char *)(madt + 1); p < end; ) {
366121992Sjhb		entry = (APIC_HEADER *)p;
367121992Sjhb		handler(entry, arg);
368121992Sjhb		p += entry->Length;
369121992Sjhb	}
370121992Sjhb}
371121992Sjhb
372121992Sjhbstatic void
373121992Sjhbmadt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
374121992Sjhb{
375121992Sjhb	PROCESSOR_APIC *proc;
376121992Sjhb	struct lapic_info *la;
377121992Sjhb
378121992Sjhb	switch (entry->Type) {
379121992Sjhb	case APIC_PROC:
380121992Sjhb		/*
381121992Sjhb		 * The MADT does not include a BSP flag, so we have to
382121992Sjhb		 * let the MP code figure out which CPU is the BSP on
383121992Sjhb		 * its own.
384121992Sjhb		 */
385121992Sjhb		proc = (PROCESSOR_APIC *)entry;
386121992Sjhb		if (bootverbose)
387121992Sjhb			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
388121992Sjhb			    proc->LocalApicId, proc->ProcessorApicId,
389121992Sjhb			    proc->ProcessorEnabled ? "enabled" : "disabled");
390121992Sjhb		if (proc->ProcessorApicId > NLAPICS)
391121992Sjhb			panic("%s: CPU ID %d too high", __func__,
392121992Sjhb			    proc->ProcessorApicId);
393121992Sjhb		la = &lapics[proc->ProcessorApicId];
394121992Sjhb		KASSERT(la->la_present == 0,
395121992Sjhb		    ("Duplicate local ACPI ID %d", proc->ProcessorApicId));
396121992Sjhb		la->la_present = 1;
397121992Sjhb		la->la_apic_id = proc->LocalApicId;
398121992Sjhb		if (proc->ProcessorEnabled) {
399121992Sjhb			la->la_enabled = 1;
400121992Sjhb			lapic_create(proc->LocalApicId, 0);
401121992Sjhb		}
402121992Sjhb		break;
403121992Sjhb	}
404121992Sjhb}
405121992Sjhb
406121992Sjhb
407121992Sjhb/*
408121992Sjhb * Add an I/O APIC from an entry in the table.
409121992Sjhb */
410121992Sjhbstatic void
411121992Sjhbmadt_parse_apics(APIC_HEADER *entry, void *arg __unused)
412121992Sjhb{
413121992Sjhb	IO_APIC *apic;
414121992Sjhb
415121992Sjhb
416121992Sjhb	switch (entry->Type) {
417121992Sjhb	case APIC_IO:
418121992Sjhb		apic = (IO_APIC *)entry;
419121992Sjhb		if (bootverbose)
420121992Sjhb			printf("MADT: Found IO APIC ID %d, Vector %d at %p\n",
421121992Sjhb			    apic->IoApicId, apic->Vector,
422121992Sjhb			    (void *)apic->IoApicAddress);
423121992Sjhb		if (apic->IoApicId >= NIOAPICS)
424121992Sjhb			panic("%s: I/O APIC ID %d too high", __func__,
425121992Sjhb			    apic->IoApicId);
426121992Sjhb		if (ioapics[apic->IoApicId].io_apic != NULL)
427121992Sjhb			panic("%s: Double APIC ID %d", __func__,
428121992Sjhb			    apic->IoApicId);
429121992Sjhb		ioapics[apic->IoApicId].io_apic = ioapic_create(
430121992Sjhb			(uintptr_t)apic->IoApicAddress, apic->IoApicId,
431121992Sjhb			    apic->Vector);
432121992Sjhb		ioapics[apic->IoApicId].io_vector = apic->Vector;
433121992Sjhb		break;
434121992Sjhb	default:
435121992Sjhb		break;
436121992Sjhb	}
437121992Sjhb}
438121992Sjhb
439121992Sjhb/*
440121992Sjhb * Determine properties of an interrupt source.  Note that for ACPI,
441121992Sjhb * these are only used for ISA interrupts, so we assume ISA bus values
442121992Sjhb * (Active Hi, Edge Triggered) for conforming values.
443121992Sjhb */
444121992Sjhbstatic u_char
445121992Sjhbinterrupt_polarity(UINT16 Polarity)
446121992Sjhb{
447121992Sjhb
448121992Sjhb	switch (Polarity) {
449121992Sjhb	case APIC_POLARITY_CONFORM:
450121992Sjhb	case APIC_POLARITY_ACTIVEHI:
451121992Sjhb		return (1);
452121992Sjhb	case APIC_POLARITY_ACTIVELO:
453121992Sjhb		return (0);
454121992Sjhb	default:
455121992Sjhb		panic("Bogus Interrupt Polarity");
456121992Sjhb	}
457121992Sjhb}
458121992Sjhb
459121992Sjhbstatic u_char
460121992Sjhbinterrupt_trigger(UINT16 TriggerMode)
461121992Sjhb{
462121992Sjhb
463121992Sjhb	switch (TriggerMode) {
464121992Sjhb	case APIC_TRIGGER_CONFORM:
465121992Sjhb	case APIC_TRIGGER_EDGE:
466121992Sjhb		return (1);
467121992Sjhb	case APIC_TRIGGER_LEVEL:
468121992Sjhb		return (0);
469121992Sjhb	default:
470121992Sjhb		panic("Bogus Interrupt Trigger Mode");
471121992Sjhb	}
472121992Sjhb}
473121992Sjhb
474121992Sjhb/*
475121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
476121992Sjhb */
477121992Sjhbstatic int
478121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
479121992Sjhb{
480121992Sjhb
481121992Sjhb	if (!lapics[acpi_id].la_present)
482121992Sjhb		return (ENOENT);
483121992Sjhb	*apic_id = lapics[acpi_id].la_apic_id;
484121992Sjhb	if (lapics[acpi_id].la_enabled)
485121992Sjhb		return (0);
486121992Sjhb	else
487121992Sjhb		return (ENXIO);
488121992Sjhb}
489121992Sjhb
490121992Sjhb/*
491121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
492121992Sjhb * interrupt.
493121992Sjhb */
494121992Sjhbstatic int
495121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
496121992Sjhb{
497121992Sjhb	int i, best;
498121992Sjhb
499121992Sjhb	best = -1;
500121992Sjhb	for (i = 0; i < NIOAPICS; i++) {
501121992Sjhb		if (ioapics[i].io_apic == NULL ||
502121992Sjhb		    ioapics[i].io_vector > intr)
503121992Sjhb			continue;
504121992Sjhb		if (best == -1 ||
505121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
506121992Sjhb			best = i;
507121992Sjhb	}
508121992Sjhb	if (best == -1)
509121992Sjhb		return (ENOENT);
510121992Sjhb	*apic = ioapics[best].io_apic;
511121992Sjhb	*pin = intr - ioapics[best].io_vector;
512121992Sjhb	if (*pin > 32)
513121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
514121992Sjhb		    intr);
515121992Sjhb	return (0);
516121992Sjhb}
517121992Sjhb
518121992Sjhb/*
519121992Sjhb * Parse an interrupt source override for an ISA interrupt.
520121992Sjhb */
521121992Sjhbstatic void
522121992Sjhbmadt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr)
523121992Sjhb{
524122149Sjhb	void *new_ioapic, *old_ioapic;
525122149Sjhb	u_int new_pin, old_pin;
526121992Sjhb
527121992Sjhb	if (bootverbose)
528121992Sjhb		printf("MADT: intr override: source %u, irq %u\n",
529121992Sjhb		    intr->Source, intr->GlobalSystemInterrupt);
530121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
531122149Sjhb	if (madt_find_interrupt(intr->GlobalSystemInterrupt, &new_ioapic,
532122149Sjhb	    &new_pin) != 0) {
533121992Sjhb		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
534121992Sjhb		    intr->GlobalSystemInterrupt, intr->Source);
535121992Sjhb		return;
536121992Sjhb	}
537121992Sjhb
538122149Sjhb	if (intr->Source != intr->GlobalSystemInterrupt) {
539122502Sjhb		/* XXX: This assumes that the SCI uses IRQ 9. */
540122502Sjhb		if (intr->GlobalSystemInterrupt > 15 && intr->Source == 9)
541122502Sjhb			acpi_OverrideInterruptLevel(
542122502Sjhb				intr->GlobalSystemInterrupt);
543122502Sjhb		else
544122502Sjhb			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
545122149Sjhb		if (madt_find_interrupt(intr->Source, &old_ioapic,
546122149Sjhb		    &old_pin) != 0)
547122149Sjhb			printf("MADT: Could not find APIC for source IRQ %d\n",
548122149Sjhb			    intr->Source);
549122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
550122172Sjhb		    intr->Source)
551122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
552122149Sjhb	}
553122149Sjhb	ioapic_set_triggermode(new_ioapic, new_pin,
554121992Sjhb	    interrupt_trigger(intr->TriggerMode));
555122149Sjhb	ioapic_set_polarity(new_ioapic, new_pin,
556122149Sjhb	    interrupt_polarity(intr->Polarity));
557121992Sjhb}
558121992Sjhb
559121992Sjhb/*
560121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
561121992Sjhb */
562121992Sjhbstatic void
563121992Sjhbmadt_parse_nmi(NMI *nmi)
564121992Sjhb{
565121992Sjhb	void *ioapic;
566121992Sjhb	u_int pin;
567121992Sjhb
568121992Sjhb	if (madt_find_interrupt(nmi->GlobalSystemInterrupt,
569121992Sjhb	    &ioapic, &pin) != 0) {
570121992Sjhb		printf("MADT: Could not find APIC for vector %d\n",
571121992Sjhb		    nmi->GlobalSystemInterrupt);
572121992Sjhb		return;
573121992Sjhb	}
574121992Sjhb
575121992Sjhb	ioapic_set_nmi(ioapic, pin);
576121992Sjhb	if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
577121992Sjhb		ioapic_set_triggermode(ioapic, pin,
578121992Sjhb		    interrupt_trigger(nmi->TriggerMode));
579121992Sjhb	if (nmi->Polarity != APIC_TRIGGER_CONFORM)
580121992Sjhb		ioapic_set_polarity(ioapic, pin,
581121992Sjhb		    interrupt_polarity(nmi->Polarity));
582121992Sjhb}
583121992Sjhb
584121992Sjhb/*
585121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
586121992Sjhb */
587121992Sjhbstatic void
588121992Sjhbmadt_parse_local_nmi(LAPIC_NMI *nmi)
589121992Sjhb{
590121992Sjhb	u_int apic_id, pin;
591121992Sjhb
592121992Sjhb	if (nmi->ProcessorApicId == 0xff)
593121992Sjhb		apic_id = APIC_ID_ALL;
594121992Sjhb	else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) != 0) {
595121992Sjhb		if (bootverbose)
596121992Sjhb			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
597121992Sjhb			    nmi->ProcessorApicId);
598121992Sjhb		return;
599121992Sjhb	}
600121992Sjhb	if (nmi->LINTPin == 0)
601121992Sjhb		pin = LVT_LINT0;
602121992Sjhb	else
603121992Sjhb		pin = LVT_LINT1;
604121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
605121992Sjhb	if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
606121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
607121992Sjhb		    interrupt_trigger(nmi->TriggerMode));
608121992Sjhb	if (nmi->Polarity != APIC_POLARITY_CONFORM)
609121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
610121992Sjhb		    interrupt_polarity(nmi->Polarity));
611121992Sjhb}
612121992Sjhb
613121992Sjhb/*
614121992Sjhb * Parse interrupt entries.
615121992Sjhb */
616121992Sjhbstatic void
617121992Sjhbmadt_parse_ints(APIC_HEADER *entry, void *arg __unused)
618121992Sjhb{
619121992Sjhb
620121992Sjhb	switch (entry->Type) {
621121992Sjhb	case APIC_INTERRUPT_SOURCE_OVERRIDE:
622121992Sjhb		madt_parse_interrupt_override(
623121992Sjhb			(INTERRUPT_SOURCE_OVERRIDE *)entry);
624121992Sjhb		break;
625121992Sjhb	case APIC_NMI:
626121992Sjhb		madt_parse_nmi((NMI *)entry);
627121992Sjhb		break;
628121992Sjhb	case APIC_LOCAL_APIC_NMI:
629121992Sjhb		madt_parse_local_nmi((LAPIC_NMI *)entry);
630121992Sjhb		break;
631121992Sjhb	}
632121992Sjhb}
633121992Sjhb
634121992Sjhb/*
635121992Sjhb * Setup per-CPU ACPI IDs.
636121992Sjhb */
637121992Sjhbstatic void
638121992Sjhbmadt_set_ids(void *dummy)
639121992Sjhb{
640121992Sjhb	struct pcpu *pc;
641121992Sjhb	u_int i, j;
642121992Sjhb
643121992Sjhb	if (madt == NULL)
644121992Sjhb		return;
645121992Sjhb	for (i = 0; i < MAXCPU; i++) {
646121992Sjhb		if (CPU_ABSENT(i))
647121992Sjhb			continue;
648121992Sjhb		pc = pcpu_find(i);
649121992Sjhb		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
650121992Sjhb		for (j = 0; j < NLAPICS + 1; j++) {
651121992Sjhb			if (!lapics[j].la_present || !lapics[j].la_enabled)
652121992Sjhb				continue;
653121992Sjhb			if (lapics[j].la_apic_id == pc->pc_apic_id) {
654121992Sjhb				pc->pc_acpi_id = j;
655121992Sjhb				if (bootverbose)
656121992Sjhb					printf("APIC: CPU %u has ACPI ID %u\n",
657121992Sjhb					    i, j);
658121992Sjhb				break;
659121992Sjhb			}
660121992Sjhb		}
661121992Sjhb		if (j == NLAPICS + 1)
662121992Sjhb			panic("Unable to find ACPI ID for CPU %d", i);
663121992Sjhb	}
664121992Sjhb}
665121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
666