madt.c revision 123326
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 123326 2003-12-09 03:04:19Z njl $");
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/pci/pcivar.h>
54121992Sjhb
55122434Sjhb#define	NIOAPICS		32	/* Max number of I/O APICs */
56122434Sjhb#define	NLAPICS			32	/* Max number of local APICs */
57121992Sjhb
58121992Sjhbtypedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
59121992Sjhb
60121992Sjhb/* These two arrays are indexed by APIC IDs. */
61121992Sjhbstruct ioapic_info {
62121992Sjhb	void *io_apic;
63121992Sjhb	UINT32 io_vector;
64121992Sjhb} ioapics[NIOAPICS];
65121992Sjhb
66121992Sjhbstruct lapic_info {
67121992Sjhb	u_int la_present:1;
68121992Sjhb	u_int la_enabled:1;
69121992Sjhb	u_int la_apic_id:8;
70121992Sjhb} lapics[NLAPICS + 1];
71121992Sjhb
72123326Snjlstatic MULTIPLE_APIC_TABLE *madt;
73121992Sjhbstatic vm_paddr_t madt_physaddr;
74121992Sjhbstatic vm_offset_t madt_length;
75121992Sjhb
76121992SjhbMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
77121992Sjhb
78121992Sjhbstatic u_char	interrupt_polarity(UINT16 Polarity);
79121992Sjhbstatic u_char	interrupt_trigger(UINT16 TriggerMode);
80121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
81121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
82121992Sjhbstatic void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
83121992Sjhbstatic void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
84121992Sjhbstatic void	madt_parse_apics(APIC_HEADER *entry, void *arg);
85123326Snjlstatic void	madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
86121992Sjhbstatic void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
87123326Snjlstatic void	madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
88123326Snjlstatic void	madt_parse_nmi(MADT_NMI_SOURCE *nmi);
89121992Sjhbstatic int	madt_probe(void);
90121992Sjhbstatic int	madt_probe_cpus(void);
91121992Sjhbstatic void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
92121992Sjhbstatic int	madt_probe_table(vm_paddr_t address);
93121992Sjhbstatic void	madt_register(void *dummy);
94121992Sjhbstatic int	madt_setup_local(void);
95121992Sjhbstatic int	madt_setup_io(void);
96121992Sjhbstatic void	madt_unmap(void *data, vm_offset_t length);
97121992Sjhbstatic void	madt_unmap_table(void *table);
98121992Sjhbstatic void	madt_walk_table(madt_entry_handler *handler, void *arg);
99121992Sjhb
100121992Sjhbstatic struct apic_enumerator madt_enumerator = {
101121992Sjhb	"MADT",
102121992Sjhb	madt_probe,
103121992Sjhb	madt_probe_cpus,
104121992Sjhb	madt_setup_local,
105121992Sjhb	madt_setup_io
106121992Sjhb};
107121992Sjhb
108121992Sjhb/*
109121992Sjhb * Code to abuse the crashdump map to map in the tables for the early
110121992Sjhb * probe.  We cheat and make the following assumptions about how we
111121992Sjhb * use this KVA: page 0 is used to map in the first page of each table
112121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the
113121992Sjhb * RSDT or XSDT.  The offset is in pages; the length is in bytes.
114121992Sjhb */
115121992Sjhbstatic void *
116121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length)
117121992Sjhb{
118121992Sjhb	vm_offset_t va, off;
119121992Sjhb	void *data;
120121992Sjhb
121121992Sjhb	off = pa & PAGE_MASK;
122121992Sjhb	length = roundup(length + off, PAGE_SIZE);
123121992Sjhb	pa = pa & PG_FRAME;
124121992Sjhb	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
125121992Sjhb	    (offset * PAGE_SIZE);
126121992Sjhb	data = (void *)(va + off);
127121992Sjhb	length -= PAGE_SIZE;
128121992Sjhb	while (length > 0) {
129121992Sjhb		va += PAGE_SIZE;
130121992Sjhb		pa += PAGE_SIZE;
131121992Sjhb		length -= PAGE_SIZE;
132121992Sjhb		pmap_kenter(va, pa);
133121992Sjhb		invlpg(va);
134121992Sjhb	}
135121992Sjhb	return (data);
136121992Sjhb}
137121992Sjhb
138121992Sjhbstatic void
139121992Sjhbmadt_unmap(void *data, vm_offset_t length)
140121992Sjhb{
141121992Sjhb	vm_offset_t va, off;
142121992Sjhb
143121992Sjhb	va = (vm_offset_t)data;
144121992Sjhb	off = va & PAGE_MASK;
145121992Sjhb	length = roundup(length + off, PAGE_SIZE);
146121992Sjhb	va &= ~PAGE_MASK;
147121992Sjhb	while (length > 0) {
148121992Sjhb		pmap_kremove(va);
149121992Sjhb		invlpg(va);
150121992Sjhb		va += PAGE_SIZE;
151121992Sjhb		length -= PAGE_SIZE;
152121992Sjhb	}
153121992Sjhb}
154121992Sjhb
155121992Sjhbstatic void *
156121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig)
157121992Sjhb{
158121992Sjhb	ACPI_TABLE_HEADER *header;
159121992Sjhb	vm_offset_t length;
160121992Sjhb
161121992Sjhb	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
162121992Sjhb	if (strncmp(header->Signature, sig, 4) != 0) {
163121992Sjhb		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
164121992Sjhb		return (NULL);
165121992Sjhb	}
166121992Sjhb	length = header->Length;
167121992Sjhb	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
168121992Sjhb	return (madt_map(pa, offset, length));
169121992Sjhb}
170121992Sjhb
171121992Sjhbstatic void
172121992Sjhbmadt_unmap_table(void *table)
173121992Sjhb{
174121992Sjhb	ACPI_TABLE_HEADER *header;
175121992Sjhb
176121992Sjhb	header = (ACPI_TABLE_HEADER *)table;
177121992Sjhb	madt_unmap(table, header->Length);
178121992Sjhb}
179121992Sjhb
180121992Sjhb/*
181121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
182121992Sjhb */
183121992Sjhbstatic int
184121992Sjhbmadt_probe(void)
185121992Sjhb{
186121992Sjhb	ACPI_POINTER rsdp_ptr;
187121992Sjhb	RSDP_DESCRIPTOR *rsdp;
188121992Sjhb	RSDT_DESCRIPTOR *rsdt;
189121992Sjhb	XSDT_DESCRIPTOR *xsdt;
190121992Sjhb	int i, count;
191121992Sjhb
192121992Sjhb	if (resource_disabled("acpi", 0))
193121992Sjhb		return (ENXIO);
194121992Sjhb
195121992Sjhb	/*
196121992Sjhb	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
197121992Sjhb	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
198121992Sjhb	 * pmap_mapdev() to map the RSDP.
199121992Sjhb	 */
200121992Sjhb	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
201121992Sjhb		return (ENXIO);
202122712Speter#ifdef __i386__
203121992Sjhb	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
204122712Speter#endif
205121992Sjhb	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
206121992Sjhb	if (rsdp == NULL) {
207121992Sjhb		if (bootverbose)
208121992Sjhb			printf("MADT: Failed to map RSDP\n");
209121992Sjhb		return (ENXIO);
210121992Sjhb	}
211121992Sjhb
212121992Sjhb	/*
213121992Sjhb	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
214121992Sjhb	 * We map the XSDT and RSDT at page 1 in the crashdump area.
215121992Sjhb	 * Page 0 is used to map in the headers of candidate ACPI tables.
216121992Sjhb	 */
217121992Sjhb	if (rsdp->Revision >= 2) {
218121992Sjhb		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
219121992Sjhb		if (xsdt == NULL) {
220121992Sjhb			if (bootverbose)
221121992Sjhb				printf("MADT: Failed to map XSDT\n");
222121992Sjhb			return (ENXIO);
223121992Sjhb		}
224123326Snjl		count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
225121992Sjhb		    sizeof(UINT64);
226121992Sjhb		for (i = 0; i < count; i++)
227121992Sjhb			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
228121992Sjhb				break;
229121992Sjhb		madt_unmap_table(xsdt);
230121992Sjhb	} else {
231121992Sjhb		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
232121992Sjhb		if (rsdt == NULL) {
233121992Sjhb			if (bootverbose)
234121992Sjhb				printf("MADT: Failed to map RSDT\n");
235121992Sjhb			return (ENXIO);
236121992Sjhb		}
237123326Snjl		count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
238121992Sjhb		    sizeof(UINT32);
239121992Sjhb		for (i = 0; i < count; i++)
240121992Sjhb			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
241121992Sjhb				break;
242121992Sjhb		madt_unmap_table(rsdt);
243121992Sjhb	}
244121992Sjhb	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
245121992Sjhb	if (madt_physaddr == 0) {
246121992Sjhb		if (bootverbose)
247121992Sjhb			printf("MADT: No MADT table found\n");
248121992Sjhb		return (ENXIO);
249121992Sjhb	}
250121992Sjhb	if (bootverbose)
251122016Speter		printf("MADT: Found table at 0x%jx\n",
252122016Speter		    (uintmax_t)madt_physaddr);
253121992Sjhb
254121992Sjhb	return (0);
255121992Sjhb}
256121992Sjhb
257121992Sjhb/*
258121992Sjhb * See if a given ACPI table is the MADT.
259121992Sjhb */
260121992Sjhbstatic int
261121992Sjhbmadt_probe_table(vm_paddr_t address)
262121992Sjhb{
263121992Sjhb	ACPI_TABLE_HEADER *table;
264121992Sjhb
265121992Sjhb	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
266121992Sjhb	if (table == NULL) {
267121992Sjhb		if (bootverbose)
268122016Speter			printf("MADT: Failed to map table at 0x%jx\n",
269122016Speter			    (uintmax_t)address);
270121992Sjhb		return (0);
271121992Sjhb	}
272121992Sjhb	if (bootverbose)
273122016Speter		printf("Table '%.4s' at 0x%jx\n", table->Signature,
274122016Speter		    (uintmax_t)address);
275121992Sjhb
276121992Sjhb	/* XXX: Verify checksum? */
277121992Sjhb	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
278121992Sjhb		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
279121992Sjhb		return (0);
280121992Sjhb	}
281121992Sjhb	madt_physaddr = address;
282121992Sjhb	madt_length = table->Length;
283121992Sjhb	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
284121992Sjhb	return (1);
285121992Sjhb}
286121992Sjhb
287121992Sjhb/*
288121992Sjhb * Run through the MP table enumerating CPUs.
289121992Sjhb */
290121992Sjhbstatic int
291121992Sjhbmadt_probe_cpus(void)
292121992Sjhb{
293121992Sjhb
294121992Sjhb	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
295121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
296121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
297121992Sjhb	madt_unmap_table(madt);
298121992Sjhb	madt = NULL;
299121992Sjhb	return (0);
300121992Sjhb}
301121992Sjhb
302121992Sjhb/*
303121992Sjhb * Initialize the local APIC on the BSP.
304121992Sjhb */
305121992Sjhbstatic int
306121992Sjhbmadt_setup_local(void)
307121992Sjhb{
308121992Sjhb
309121992Sjhb	madt = pmap_mapdev(madt_physaddr, madt_length);
310121992Sjhb	lapic_init((uintptr_t)madt->LocalApicAddress);
311121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
312123326Snjl	    (int)sizeof(madt->OemId), madt->OemId,
313123326Snjl	    (int)sizeof(madt->OemTableId), madt->OemTableId);
314121992Sjhb
315121992Sjhb	/*
316121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
317121992Sjhb	 * perhaps emit a warning here if we find one?
318121992Sjhb	 */
319121992Sjhb	return (0);
320121992Sjhb}
321121992Sjhb
322121992Sjhb/*
323121992Sjhb * Run through the MP table enumerating I/O APICs.
324121992Sjhb */
325121992Sjhbstatic int
326121992Sjhbmadt_setup_io(void)
327121992Sjhb{
328121992Sjhb	int i;
329121992Sjhb
330121992Sjhb	/* First, we run through adding I/O APIC's. */
331121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
332121992Sjhb
333121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
334121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
335121992Sjhb
336121992Sjhb	/* Third, we register all the I/O APIC's. */
337121992Sjhb	for (i = 0; i < NIOAPICS; i++)
338121992Sjhb		if (ioapics[i].io_apic != NULL)
339121992Sjhb			ioapic_register(ioapics[i].io_apic);
340121992Sjhb
341121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
342121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
343121992Sjhb
344121992Sjhb	return (0);
345121992Sjhb}
346121992Sjhb
347121992Sjhbstatic void
348121992Sjhbmadt_register(void *dummy __unused)
349121992Sjhb{
350121992Sjhb
351121992Sjhb	apic_register_enumerator(&madt_enumerator);
352121992Sjhb}
353123133SjhbSYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, 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
364123326Snjl	end = (u_char *)(madt) + madt->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{
375123326Snjl	MADT_PROCESSOR_APIC *proc;
376121992Sjhb	struct lapic_info *la;
377121992Sjhb
378121992Sjhb	switch (entry->Type) {
379123326Snjl	case APIC_PROCESSOR:
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		 */
385123326Snjl		proc = (MADT_PROCESSOR_APIC *)entry;
386121992Sjhb		if (bootverbose)
387121992Sjhb			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
388123326Snjl			    proc->LocalApicId, proc->ProcessorId,
389121992Sjhb			    proc->ProcessorEnabled ? "enabled" : "disabled");
390123326Snjl		if (proc->ProcessorId > NLAPICS)
391121992Sjhb			panic("%s: CPU ID %d too high", __func__,
392123326Snjl			    proc->ProcessorId);
393123326Snjl		la = &lapics[proc->ProcessorId];
394121992Sjhb		KASSERT(la->la_present == 0,
395123326Snjl		    ("Duplicate local ACPI ID %d", proc->ProcessorId));
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{
413123326Snjl	MADT_IO_APIC *apic;
414121992Sjhb
415121992Sjhb	switch (entry->Type) {
416121992Sjhb	case APIC_IO:
417123326Snjl		apic = (MADT_IO_APIC *)entry;
418121992Sjhb		if (bootverbose)
419123326Snjl			printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
420123326Snjl			    apic->IoApicId, apic->Interrupt,
421123326Snjl			    (void *)(uintptr_t)apic->Address);
422121992Sjhb		if (apic->IoApicId >= NIOAPICS)
423121992Sjhb			panic("%s: I/O APIC ID %d too high", __func__,
424121992Sjhb			    apic->IoApicId);
425121992Sjhb		if (ioapics[apic->IoApicId].io_apic != NULL)
426121992Sjhb			panic("%s: Double APIC ID %d", __func__,
427121992Sjhb			    apic->IoApicId);
428121992Sjhb		ioapics[apic->IoApicId].io_apic = ioapic_create(
429123326Snjl			(uintptr_t)apic->Address, apic->IoApicId,
430123326Snjl			    apic->Interrupt);
431123326Snjl		ioapics[apic->IoApicId].io_vector = apic->Interrupt;
432121992Sjhb		break;
433121992Sjhb	default:
434121992Sjhb		break;
435121992Sjhb	}
436121992Sjhb}
437121992Sjhb
438121992Sjhb/*
439121992Sjhb * Determine properties of an interrupt source.  Note that for ACPI,
440121992Sjhb * these are only used for ISA interrupts, so we assume ISA bus values
441121992Sjhb * (Active Hi, Edge Triggered) for conforming values.
442121992Sjhb */
443121992Sjhbstatic u_char
444121992Sjhbinterrupt_polarity(UINT16 Polarity)
445121992Sjhb{
446121992Sjhb
447121992Sjhb	switch (Polarity) {
448123326Snjl	case POLARITY_CONFORMS:
449123326Snjl	case POLARITY_ACTIVE_HIGH:
450121992Sjhb		return (1);
451123326Snjl	case POLARITY_ACTIVE_LOW:
452121992Sjhb		return (0);
453121992Sjhb	default:
454121992Sjhb		panic("Bogus Interrupt Polarity");
455121992Sjhb	}
456121992Sjhb}
457121992Sjhb
458121992Sjhbstatic u_char
459121992Sjhbinterrupt_trigger(UINT16 TriggerMode)
460121992Sjhb{
461121992Sjhb
462121992Sjhb	switch (TriggerMode) {
463123326Snjl	case TRIGGER_CONFORMS:
464123326Snjl	case TRIGGER_EDGE:
465121992Sjhb		return (1);
466123326Snjl	case TRIGGER_LEVEL:
467121992Sjhb		return (0);
468121992Sjhb	default:
469121992Sjhb		panic("Bogus Interrupt Trigger Mode");
470121992Sjhb	}
471121992Sjhb}
472121992Sjhb
473121992Sjhb/*
474121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
475121992Sjhb */
476121992Sjhbstatic int
477121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
478121992Sjhb{
479121992Sjhb
480121992Sjhb	if (!lapics[acpi_id].la_present)
481121992Sjhb		return (ENOENT);
482121992Sjhb	*apic_id = lapics[acpi_id].la_apic_id;
483121992Sjhb	if (lapics[acpi_id].la_enabled)
484121992Sjhb		return (0);
485121992Sjhb	else
486121992Sjhb		return (ENXIO);
487121992Sjhb}
488121992Sjhb
489121992Sjhb/*
490121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
491121992Sjhb * interrupt.
492121992Sjhb */
493121992Sjhbstatic int
494121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
495121992Sjhb{
496121992Sjhb	int i, best;
497121992Sjhb
498121992Sjhb	best = -1;
499121992Sjhb	for (i = 0; i < NIOAPICS; i++) {
500121992Sjhb		if (ioapics[i].io_apic == NULL ||
501121992Sjhb		    ioapics[i].io_vector > intr)
502121992Sjhb			continue;
503121992Sjhb		if (best == -1 ||
504121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
505121992Sjhb			best = i;
506121992Sjhb	}
507121992Sjhb	if (best == -1)
508121992Sjhb		return (ENOENT);
509121992Sjhb	*apic = ioapics[best].io_apic;
510121992Sjhb	*pin = intr - ioapics[best].io_vector;
511121992Sjhb	if (*pin > 32)
512121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
513121992Sjhb		    intr);
514121992Sjhb	return (0);
515121992Sjhb}
516121992Sjhb
517121992Sjhb/*
518121992Sjhb * Parse an interrupt source override for an ISA interrupt.
519121992Sjhb */
520121992Sjhbstatic void
521123326Snjlmadt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
522121992Sjhb{
523122149Sjhb	void *new_ioapic, *old_ioapic;
524122149Sjhb	u_int new_pin, old_pin;
525121992Sjhb
526121992Sjhb	if (bootverbose)
527121992Sjhb		printf("MADT: intr override: source %u, irq %u\n",
528123326Snjl		    intr->Source, intr->Interrupt);
529121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
530123326Snjl	if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
531122149Sjhb	    &new_pin) != 0) {
532121992Sjhb		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
533123326Snjl		    intr->Interrupt, intr->Source);
534121992Sjhb		return;
535121992Sjhb	}
536121992Sjhb
537123326Snjl	if (intr->Source != intr->Interrupt) {
538122502Sjhb		/* XXX: This assumes that the SCI uses IRQ 9. */
539123326Snjl		if (intr->Interrupt > 15 && intr->Source == 9)
540123326Snjl			acpi_OverrideInterruptLevel(intr->Interrupt);
541122502Sjhb		else
542122502Sjhb			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
543122149Sjhb		if (madt_find_interrupt(intr->Source, &old_ioapic,
544122149Sjhb		    &old_pin) != 0)
545122149Sjhb			printf("MADT: Could not find APIC for source IRQ %d\n",
546122149Sjhb			    intr->Source);
547122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
548122172Sjhb		    intr->Source)
549122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
550122149Sjhb	}
551122149Sjhb	ioapic_set_triggermode(new_ioapic, new_pin,
552121992Sjhb	    interrupt_trigger(intr->TriggerMode));
553122149Sjhb	ioapic_set_polarity(new_ioapic, new_pin,
554122149Sjhb	    interrupt_polarity(intr->Polarity));
555121992Sjhb}
556121992Sjhb
557121992Sjhb/*
558121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
559121992Sjhb */
560121992Sjhbstatic void
561123326Snjlmadt_parse_nmi(MADT_NMI_SOURCE *nmi)
562121992Sjhb{
563121992Sjhb	void *ioapic;
564121992Sjhb	u_int pin;
565121992Sjhb
566123326Snjl	if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
567121992Sjhb		printf("MADT: Could not find APIC for vector %d\n",
568123326Snjl		    nmi->Interrupt);
569121992Sjhb		return;
570121992Sjhb	}
571121992Sjhb
572121992Sjhb	ioapic_set_nmi(ioapic, pin);
573123326Snjl	if (nmi->TriggerMode != TRIGGER_CONFORMS)
574121992Sjhb		ioapic_set_triggermode(ioapic, pin,
575121992Sjhb		    interrupt_trigger(nmi->TriggerMode));
576123326Snjl	if (nmi->Polarity != TRIGGER_CONFORMS)
577121992Sjhb		ioapic_set_polarity(ioapic, pin,
578121992Sjhb		    interrupt_polarity(nmi->Polarity));
579121992Sjhb}
580121992Sjhb
581121992Sjhb/*
582121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
583121992Sjhb */
584121992Sjhbstatic void
585123326Snjlmadt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
586121992Sjhb{
587121992Sjhb	u_int apic_id, pin;
588121992Sjhb
589123326Snjl	if (nmi->ProcessorId == 0xff)
590121992Sjhb		apic_id = APIC_ID_ALL;
591123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
592121992Sjhb		if (bootverbose)
593121992Sjhb			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
594123326Snjl			    nmi->ProcessorId);
595121992Sjhb		return;
596121992Sjhb	}
597123326Snjl	if (nmi->Lint == 0)
598121992Sjhb		pin = LVT_LINT0;
599121992Sjhb	else
600121992Sjhb		pin = LVT_LINT1;
601121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
602123326Snjl	if (nmi->TriggerMode != TRIGGER_CONFORMS)
603121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
604121992Sjhb		    interrupt_trigger(nmi->TriggerMode));
605123326Snjl	if (nmi->Polarity != POLARITY_CONFORMS)
606121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
607121992Sjhb		    interrupt_polarity(nmi->Polarity));
608121992Sjhb}
609121992Sjhb
610121992Sjhb/*
611121992Sjhb * Parse interrupt entries.
612121992Sjhb */
613121992Sjhbstatic void
614121992Sjhbmadt_parse_ints(APIC_HEADER *entry, void *arg __unused)
615121992Sjhb{
616121992Sjhb
617121992Sjhb	switch (entry->Type) {
618123326Snjl	case APIC_XRUPT_OVERRIDE:
619121992Sjhb		madt_parse_interrupt_override(
620123326Snjl			(MADT_INTERRUPT_OVERRIDE *)entry);
621121992Sjhb		break;
622121992Sjhb	case APIC_NMI:
623123326Snjl		madt_parse_nmi((MADT_NMI_SOURCE *)entry);
624121992Sjhb		break;
625123326Snjl	case APIC_LOCAL_NMI:
626123326Snjl		madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
627121992Sjhb		break;
628121992Sjhb	}
629121992Sjhb}
630121992Sjhb
631121992Sjhb/*
632121992Sjhb * Setup per-CPU ACPI IDs.
633121992Sjhb */
634121992Sjhbstatic void
635121992Sjhbmadt_set_ids(void *dummy)
636121992Sjhb{
637121992Sjhb	struct pcpu *pc;
638121992Sjhb	u_int i, j;
639121992Sjhb
640121992Sjhb	if (madt == NULL)
641121992Sjhb		return;
642123133Sjhb	for (i = 0; i <= mp_maxid; i++) {
643121992Sjhb		if (CPU_ABSENT(i))
644121992Sjhb			continue;
645121992Sjhb		pc = pcpu_find(i);
646121992Sjhb		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
647121992Sjhb		for (j = 0; j < NLAPICS + 1; j++) {
648121992Sjhb			if (!lapics[j].la_present || !lapics[j].la_enabled)
649121992Sjhb				continue;
650121992Sjhb			if (lapics[j].la_apic_id == pc->pc_apic_id) {
651121992Sjhb				pc->pc_acpi_id = j;
652121992Sjhb				if (bootverbose)
653121992Sjhb					printf("APIC: CPU %u has ACPI ID %u\n",
654121992Sjhb					    i, j);
655121992Sjhb				break;
656121992Sjhb			}
657121992Sjhb		}
658121992Sjhb		if (j == NLAPICS + 1)
659121992Sjhb			panic("Unable to find ACPI ID for CPU %d", i);
660121992Sjhb	}
661121992Sjhb}
662121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
663