madt.c revision 129128
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 129128 2004-05-11 20:06:32Z 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"
52129094Sjhb#include <contrib/dev/acpica/actables.h>
53121992Sjhb#include <dev/acpica/acpivar.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
73128930Sjhbstatic int madt_found_sci_override;
74123326Snjlstatic MULTIPLE_APIC_TABLE *madt;
75121992Sjhbstatic vm_paddr_t madt_physaddr;
76121992Sjhbstatic vm_offset_t madt_length;
77121992Sjhb
78121992SjhbMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
79121992Sjhb
80128930Sjhbstatic enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
81128930Sjhbstatic enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
82121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
83121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
84121992Sjhbstatic void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
85121992Sjhbstatic void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
86121992Sjhbstatic void	madt_parse_apics(APIC_HEADER *entry, void *arg);
87123326Snjlstatic void	madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
88121992Sjhbstatic void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
89123326Snjlstatic void	madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
90123326Snjlstatic void	madt_parse_nmi(MADT_NMI_SOURCE *nmi);
91121992Sjhbstatic int	madt_probe(void);
92121992Sjhbstatic int	madt_probe_cpus(void);
93121992Sjhbstatic void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
94121992Sjhbstatic int	madt_probe_table(vm_paddr_t address);
95121992Sjhbstatic void	madt_register(void *dummy);
96121992Sjhbstatic int	madt_setup_local(void);
97121992Sjhbstatic int	madt_setup_io(void);
98121992Sjhbstatic void	madt_unmap(void *data, vm_offset_t length);
99121992Sjhbstatic void	madt_unmap_table(void *table);
100121992Sjhbstatic void	madt_walk_table(madt_entry_handler *handler, void *arg);
101121992Sjhb
102121992Sjhbstatic struct apic_enumerator madt_enumerator = {
103121992Sjhb	"MADT",
104121992Sjhb	madt_probe,
105121992Sjhb	madt_probe_cpus,
106121992Sjhb	madt_setup_local,
107121992Sjhb	madt_setup_io
108121992Sjhb};
109121992Sjhb
110121992Sjhb/*
111121992Sjhb * Code to abuse the crashdump map to map in the tables for the early
112121992Sjhb * probe.  We cheat and make the following assumptions about how we
113121992Sjhb * use this KVA: page 0 is used to map in the first page of each table
114121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the
115121992Sjhb * RSDT or XSDT.  The offset is in pages; the length is in bytes.
116121992Sjhb */
117121992Sjhbstatic void *
118121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length)
119121992Sjhb{
120121992Sjhb	vm_offset_t va, off;
121121992Sjhb	void *data;
122121992Sjhb
123121992Sjhb	off = pa & PAGE_MASK;
124121992Sjhb	length = roundup(length + off, PAGE_SIZE);
125121992Sjhb	pa = pa & PG_FRAME;
126121992Sjhb	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
127121992Sjhb	    (offset * PAGE_SIZE);
128121992Sjhb	data = (void *)(va + off);
129121992Sjhb	length -= PAGE_SIZE;
130121992Sjhb	while (length > 0) {
131121992Sjhb		va += PAGE_SIZE;
132121992Sjhb		pa += PAGE_SIZE;
133121992Sjhb		length -= PAGE_SIZE;
134121992Sjhb		pmap_kenter(va, pa);
135121992Sjhb		invlpg(va);
136121992Sjhb	}
137121992Sjhb	return (data);
138121992Sjhb}
139121992Sjhb
140121992Sjhbstatic void
141121992Sjhbmadt_unmap(void *data, vm_offset_t length)
142121992Sjhb{
143121992Sjhb	vm_offset_t va, off;
144121992Sjhb
145121992Sjhb	va = (vm_offset_t)data;
146121992Sjhb	off = va & PAGE_MASK;
147121992Sjhb	length = roundup(length + off, PAGE_SIZE);
148121992Sjhb	va &= ~PAGE_MASK;
149121992Sjhb	while (length > 0) {
150121992Sjhb		pmap_kremove(va);
151121992Sjhb		invlpg(va);
152121992Sjhb		va += PAGE_SIZE;
153121992Sjhb		length -= PAGE_SIZE;
154121992Sjhb	}
155121992Sjhb}
156121992Sjhb
157121992Sjhbstatic void *
158121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig)
159121992Sjhb{
160121992Sjhb	ACPI_TABLE_HEADER *header;
161121992Sjhb	vm_offset_t length;
162129094Sjhb	void *table;
163121992Sjhb
164121992Sjhb	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
165121992Sjhb	if (strncmp(header->Signature, sig, 4) != 0) {
166121992Sjhb		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
167121992Sjhb		return (NULL);
168121992Sjhb	}
169121992Sjhb	length = header->Length;
170121992Sjhb	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
171129094Sjhb	table = madt_map(pa, offset, length);
172129094Sjhb	if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
173129094Sjhb		if (bootverbose)
174129094Sjhb			printf("MADT: Failed checksum for table %s\n", sig);
175129094Sjhb		madt_unmap(table, length);
176129094Sjhb		return (NULL);
177129094Sjhb	}
178129094Sjhb	return (table);
179121992Sjhb}
180121992Sjhb
181121992Sjhbstatic void
182121992Sjhbmadt_unmap_table(void *table)
183121992Sjhb{
184121992Sjhb	ACPI_TABLE_HEADER *header;
185121992Sjhb
186121992Sjhb	header = (ACPI_TABLE_HEADER *)table;
187121992Sjhb	madt_unmap(table, header->Length);
188121992Sjhb}
189121992Sjhb
190121992Sjhb/*
191121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
192121992Sjhb */
193121992Sjhbstatic int
194121992Sjhbmadt_probe(void)
195121992Sjhb{
196121992Sjhb	ACPI_POINTER rsdp_ptr;
197121992Sjhb	RSDP_DESCRIPTOR *rsdp;
198121992Sjhb	RSDT_DESCRIPTOR *rsdt;
199121992Sjhb	XSDT_DESCRIPTOR *xsdt;
200121992Sjhb	int i, count;
201121992Sjhb
202121992Sjhb	if (resource_disabled("acpi", 0))
203121992Sjhb		return (ENXIO);
204121992Sjhb
205121992Sjhb	/*
206121992Sjhb	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
207121992Sjhb	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
208121992Sjhb	 * pmap_mapdev() to map the RSDP.
209121992Sjhb	 */
210121992Sjhb	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
211121992Sjhb		return (ENXIO);
212122712Speter#ifdef __i386__
213121992Sjhb	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
214122712Speter#endif
215121992Sjhb	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
216121992Sjhb	if (rsdp == NULL) {
217121992Sjhb		if (bootverbose)
218121992Sjhb			printf("MADT: Failed to map RSDP\n");
219121992Sjhb		return (ENXIO);
220121992Sjhb	}
221121992Sjhb
222121992Sjhb	/*
223121992Sjhb	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
224121992Sjhb	 * We map the XSDT and RSDT at page 1 in the crashdump area.
225121992Sjhb	 * Page 0 is used to map in the headers of candidate ACPI tables.
226121992Sjhb	 */
227121992Sjhb	if (rsdp->Revision >= 2) {
228129094Sjhb		/*
229129094Sjhb		 * AcpiOsGetRootPointer only verifies the checksum for
230129094Sjhb		 * the version 1.0 portion of the RSDP.  Version 2.0 has
231129094Sjhb		 * an additional checksum that we verify first.
232129094Sjhb		 */
233129094Sjhb		if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
234129094Sjhb			if (bootverbose)
235129094Sjhb				printf("MADT: RSDP failed extended checksum\n");
236129094Sjhb			return (ENXIO);
237129094Sjhb		}
238121992Sjhb		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
239121992Sjhb		if (xsdt == NULL) {
240121992Sjhb			if (bootverbose)
241121992Sjhb				printf("MADT: Failed to map XSDT\n");
242121992Sjhb			return (ENXIO);
243121992Sjhb		}
244123326Snjl		count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
245121992Sjhb		    sizeof(UINT64);
246121992Sjhb		for (i = 0; i < count; i++)
247121992Sjhb			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
248121992Sjhb				break;
249121992Sjhb		madt_unmap_table(xsdt);
250121992Sjhb	} else {
251121992Sjhb		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
252121992Sjhb		if (rsdt == NULL) {
253121992Sjhb			if (bootverbose)
254121992Sjhb				printf("MADT: Failed to map RSDT\n");
255121992Sjhb			return (ENXIO);
256121992Sjhb		}
257123326Snjl		count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
258121992Sjhb		    sizeof(UINT32);
259121992Sjhb		for (i = 0; i < count; i++)
260121992Sjhb			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
261121992Sjhb				break;
262121992Sjhb		madt_unmap_table(rsdt);
263121992Sjhb	}
264121992Sjhb	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
265121992Sjhb	if (madt_physaddr == 0) {
266121992Sjhb		if (bootverbose)
267121992Sjhb			printf("MADT: No MADT table found\n");
268121992Sjhb		return (ENXIO);
269121992Sjhb	}
270121992Sjhb	if (bootverbose)
271122016Speter		printf("MADT: Found table at 0x%jx\n",
272122016Speter		    (uintmax_t)madt_physaddr);
273121992Sjhb
274129094Sjhb	/*
275129094Sjhb	 * Verify that we can map the full table and that its checksum is
276129094Sjhb	 * correct, etc.
277129094Sjhb	 */
278129094Sjhb	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
279129094Sjhb	if (madt == NULL)
280129094Sjhb		return (ENXIO);
281129094Sjhb	madt_unmap_table(madt);
282129094Sjhb	madt = NULL;
283129094Sjhb
284121992Sjhb	return (0);
285121992Sjhb}
286121992Sjhb
287121992Sjhb/*
288121992Sjhb * See if a given ACPI table is the MADT.
289121992Sjhb */
290121992Sjhbstatic int
291121992Sjhbmadt_probe_table(vm_paddr_t address)
292121992Sjhb{
293121992Sjhb	ACPI_TABLE_HEADER *table;
294121992Sjhb
295121992Sjhb	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
296121992Sjhb	if (table == NULL) {
297121992Sjhb		if (bootverbose)
298122016Speter			printf("MADT: Failed to map table at 0x%jx\n",
299122016Speter			    (uintmax_t)address);
300121992Sjhb		return (0);
301121992Sjhb	}
302121992Sjhb	if (bootverbose)
303122016Speter		printf("Table '%.4s' at 0x%jx\n", table->Signature,
304122016Speter		    (uintmax_t)address);
305121992Sjhb
306121992Sjhb	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
307121992Sjhb		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
308121992Sjhb		return (0);
309121992Sjhb	}
310121992Sjhb	madt_physaddr = address;
311121992Sjhb	madt_length = table->Length;
312121992Sjhb	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
313121992Sjhb	return (1);
314121992Sjhb}
315121992Sjhb
316121992Sjhb/*
317121992Sjhb * Run through the MP table enumerating CPUs.
318121992Sjhb */
319121992Sjhbstatic int
320121992Sjhbmadt_probe_cpus(void)
321121992Sjhb{
322121992Sjhb
323121992Sjhb	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
324121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
325121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
326121992Sjhb	madt_unmap_table(madt);
327121992Sjhb	madt = NULL;
328121992Sjhb	return (0);
329121992Sjhb}
330121992Sjhb
331121992Sjhb/*
332121992Sjhb * Initialize the local APIC on the BSP.
333121992Sjhb */
334121992Sjhbstatic int
335121992Sjhbmadt_setup_local(void)
336121992Sjhb{
337121992Sjhb
338121992Sjhb	madt = pmap_mapdev(madt_physaddr, madt_length);
339121992Sjhb	lapic_init((uintptr_t)madt->LocalApicAddress);
340121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
341123326Snjl	    (int)sizeof(madt->OemId), madt->OemId,
342123326Snjl	    (int)sizeof(madt->OemTableId), madt->OemTableId);
343121992Sjhb
344121992Sjhb	/*
345121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
346121992Sjhb	 * perhaps emit a warning here if we find one?
347121992Sjhb	 */
348121992Sjhb	return (0);
349121992Sjhb}
350121992Sjhb
351121992Sjhb/*
352125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
353121992Sjhb */
354121992Sjhbstatic int
355121992Sjhbmadt_setup_io(void)
356121992Sjhb{
357128930Sjhb	void *ioapic;
358128930Sjhb	u_int pin;
359121992Sjhb	int i;
360121992Sjhb
361125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
362125048Sjhb	i = acpi_Startup();
363125048Sjhb	if (ACPI_FAILURE(i)) {
364125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
365125048Sjhb		    AcpiFormatException(i));
366125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
367125048Sjhb		panic("Using MADT but ACPI doesn't work");
368125048Sjhb	}
369125048Sjhb
370121992Sjhb	/* First, we run through adding I/O APIC's. */
371129097Sjhb	if (madt->PCATCompat)
372129097Sjhb		ioapic_enable_mixed_mode();
373121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
374121992Sjhb
375121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
376121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
377121992Sjhb
378128930Sjhb	/*
379128930Sjhb	 * If there was not an explicit override entry for the SCI,
380128930Sjhb	 * force it to use level trigger and active-low polarity.
381128930Sjhb	 */
382128930Sjhb	if (!madt_found_sci_override) {
383128930Sjhb		if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
384128930Sjhb		    != 0)
385128930Sjhb			printf("MADT: Could not find APIC for SCI IRQ %d\n",
386128930Sjhb			    AcpiGbl_FADT->SciInt);
387128930Sjhb		else {
388128930Sjhb			printf(
389128930Sjhb	"MADT: Forcing active-low polarity and level trigger for SCI\n");
390128930Sjhb			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
391128930Sjhb			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
392128930Sjhb		}
393128930Sjhb	}
394128930Sjhb
395121992Sjhb	/* Third, we register all the I/O APIC's. */
396121992Sjhb	for (i = 0; i < NIOAPICS; i++)
397121992Sjhb		if (ioapics[i].io_apic != NULL)
398121992Sjhb			ioapic_register(ioapics[i].io_apic);
399121992Sjhb
400121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
401121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
402121992Sjhb
403121992Sjhb	return (0);
404121992Sjhb}
405121992Sjhb
406121992Sjhbstatic void
407121992Sjhbmadt_register(void *dummy __unused)
408121992Sjhb{
409121992Sjhb
410121992Sjhb	apic_register_enumerator(&madt_enumerator);
411121992Sjhb}
412123133SjhbSYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
413121992Sjhb
414121992Sjhb/*
415121992Sjhb * Call the handler routine for each entry in the MADT table.
416121992Sjhb */
417121992Sjhbstatic void
418121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg)
419121992Sjhb{
420121992Sjhb	APIC_HEADER *entry;
421121992Sjhb	u_char *p, *end;
422121992Sjhb
423123326Snjl	end = (u_char *)(madt) + madt->Length;
424121992Sjhb	for (p = (u_char *)(madt + 1); p < end; ) {
425121992Sjhb		entry = (APIC_HEADER *)p;
426121992Sjhb		handler(entry, arg);
427121992Sjhb		p += entry->Length;
428121992Sjhb	}
429121992Sjhb}
430121992Sjhb
431121992Sjhbstatic void
432121992Sjhbmadt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
433121992Sjhb{
434123326Snjl	MADT_PROCESSOR_APIC *proc;
435121992Sjhb	struct lapic_info *la;
436121992Sjhb
437121992Sjhb	switch (entry->Type) {
438123326Snjl	case APIC_PROCESSOR:
439121992Sjhb		/*
440121992Sjhb		 * The MADT does not include a BSP flag, so we have to
441121992Sjhb		 * let the MP code figure out which CPU is the BSP on
442121992Sjhb		 * its own.
443121992Sjhb		 */
444123326Snjl		proc = (MADT_PROCESSOR_APIC *)entry;
445121992Sjhb		if (bootverbose)
446121992Sjhb			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
447123326Snjl			    proc->LocalApicId, proc->ProcessorId,
448121992Sjhb			    proc->ProcessorEnabled ? "enabled" : "disabled");
449123326Snjl		if (proc->ProcessorId > NLAPICS)
450121992Sjhb			panic("%s: CPU ID %d too high", __func__,
451123326Snjl			    proc->ProcessorId);
452123326Snjl		la = &lapics[proc->ProcessorId];
453121992Sjhb		KASSERT(la->la_present == 0,
454123326Snjl		    ("Duplicate local ACPI ID %d", proc->ProcessorId));
455121992Sjhb		la->la_present = 1;
456121992Sjhb		la->la_apic_id = proc->LocalApicId;
457121992Sjhb		if (proc->ProcessorEnabled) {
458121992Sjhb			la->la_enabled = 1;
459121992Sjhb			lapic_create(proc->LocalApicId, 0);
460121992Sjhb		}
461121992Sjhb		break;
462121992Sjhb	}
463121992Sjhb}
464121992Sjhb
465121992Sjhb
466121992Sjhb/*
467121992Sjhb * Add an I/O APIC from an entry in the table.
468121992Sjhb */
469121992Sjhbstatic void
470121992Sjhbmadt_parse_apics(APIC_HEADER *entry, void *arg __unused)
471121992Sjhb{
472123326Snjl	MADT_IO_APIC *apic;
473121992Sjhb
474121992Sjhb	switch (entry->Type) {
475121992Sjhb	case APIC_IO:
476123326Snjl		apic = (MADT_IO_APIC *)entry;
477121992Sjhb		if (bootverbose)
478123326Snjl			printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
479123326Snjl			    apic->IoApicId, apic->Interrupt,
480123326Snjl			    (void *)(uintptr_t)apic->Address);
481121992Sjhb		if (apic->IoApicId >= NIOAPICS)
482121992Sjhb			panic("%s: I/O APIC ID %d too high", __func__,
483121992Sjhb			    apic->IoApicId);
484121992Sjhb		if (ioapics[apic->IoApicId].io_apic != NULL)
485121992Sjhb			panic("%s: Double APIC ID %d", __func__,
486121992Sjhb			    apic->IoApicId);
487121992Sjhb		ioapics[apic->IoApicId].io_apic = ioapic_create(
488123326Snjl			(uintptr_t)apic->Address, apic->IoApicId,
489123326Snjl			    apic->Interrupt);
490123326Snjl		ioapics[apic->IoApicId].io_vector = apic->Interrupt;
491121992Sjhb		break;
492121992Sjhb	default:
493121992Sjhb		break;
494121992Sjhb	}
495121992Sjhb}
496121992Sjhb
497121992Sjhb/*
498129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
499129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
500128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
501129128Sjhb * SCI for which we use Active Lo, Level Triggered.
502121992Sjhb */
503128930Sjhbstatic enum intr_polarity
504128930Sjhbinterrupt_polarity(UINT16 Polarity, UINT8 Source)
505121992Sjhb{
506121992Sjhb
507121992Sjhb	switch (Polarity) {
508123326Snjl	case POLARITY_CONFORMS:
509128930Sjhb		if (Source == AcpiGbl_FADT->SciInt)
510128930Sjhb			return (INTR_POLARITY_LOW);
511128930Sjhb		else
512128930Sjhb			return (INTR_POLARITY_HIGH);
513123326Snjl	case POLARITY_ACTIVE_HIGH:
514128930Sjhb		return (INTR_POLARITY_HIGH);
515123326Snjl	case POLARITY_ACTIVE_LOW:
516128930Sjhb		return (INTR_POLARITY_LOW);
517121992Sjhb	default:
518121992Sjhb		panic("Bogus Interrupt Polarity");
519121992Sjhb	}
520121992Sjhb}
521121992Sjhb
522128930Sjhbstatic enum intr_trigger
523128930Sjhbinterrupt_trigger(UINT16 TriggerMode, UINT8 Source)
524121992Sjhb{
525121992Sjhb
526121992Sjhb	switch (TriggerMode) {
527123326Snjl	case TRIGGER_CONFORMS:
528128930Sjhb		if (Source == AcpiGbl_FADT->SciInt)
529128930Sjhb			return (INTR_TRIGGER_LEVEL);
530128930Sjhb		else
531128930Sjhb			return (INTR_TRIGGER_EDGE);
532123326Snjl	case TRIGGER_EDGE:
533128930Sjhb		return (INTR_TRIGGER_EDGE);
534123326Snjl	case TRIGGER_LEVEL:
535128930Sjhb		return (INTR_TRIGGER_LEVEL);
536121992Sjhb	default:
537121992Sjhb		panic("Bogus Interrupt Trigger Mode");
538121992Sjhb	}
539121992Sjhb}
540121992Sjhb
541121992Sjhb/*
542121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
543121992Sjhb */
544121992Sjhbstatic int
545121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
546121992Sjhb{
547121992Sjhb
548121992Sjhb	if (!lapics[acpi_id].la_present)
549121992Sjhb		return (ENOENT);
550121992Sjhb	*apic_id = lapics[acpi_id].la_apic_id;
551121992Sjhb	if (lapics[acpi_id].la_enabled)
552121992Sjhb		return (0);
553121992Sjhb	else
554121992Sjhb		return (ENXIO);
555121992Sjhb}
556121992Sjhb
557121992Sjhb/*
558121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
559121992Sjhb * interrupt.
560121992Sjhb */
561121992Sjhbstatic int
562121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
563121992Sjhb{
564121992Sjhb	int i, best;
565121992Sjhb
566121992Sjhb	best = -1;
567121992Sjhb	for (i = 0; i < NIOAPICS; i++) {
568121992Sjhb		if (ioapics[i].io_apic == NULL ||
569121992Sjhb		    ioapics[i].io_vector > intr)
570121992Sjhb			continue;
571121992Sjhb		if (best == -1 ||
572121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
573121992Sjhb			best = i;
574121992Sjhb	}
575121992Sjhb	if (best == -1)
576121992Sjhb		return (ENOENT);
577121992Sjhb	*apic = ioapics[best].io_apic;
578121992Sjhb	*pin = intr - ioapics[best].io_vector;
579121992Sjhb	if (*pin > 32)
580121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
581121992Sjhb		    intr);
582121992Sjhb	return (0);
583121992Sjhb}
584121992Sjhb
585121992Sjhb/*
586121992Sjhb * Parse an interrupt source override for an ISA interrupt.
587121992Sjhb */
588121992Sjhbstatic void
589123326Snjlmadt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
590121992Sjhb{
591122149Sjhb	void *new_ioapic, *old_ioapic;
592122149Sjhb	u_int new_pin, old_pin;
593128930Sjhb	enum intr_trigger trig;
594128930Sjhb	enum intr_polarity pol;
595128930Sjhb	char buf[64];
596121992Sjhb
597121992Sjhb	if (bootverbose)
598121992Sjhb		printf("MADT: intr override: source %u, irq %u\n",
599123326Snjl		    intr->Source, intr->Interrupt);
600121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
601123326Snjl	if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
602122149Sjhb	    &new_pin) != 0) {
603121992Sjhb		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
604123326Snjl		    intr->Interrupt, intr->Source);
605121992Sjhb		return;
606121992Sjhb	}
607121992Sjhb
608125048Sjhb	/*
609128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
610128930Sjhb	 * entry.
611128930Sjhb	 */
612128930Sjhb	trig = interrupt_trigger(intr->TriggerMode, intr->Source);
613128930Sjhb	pol = interrupt_polarity(intr->Polarity, intr->Source);
614128930Sjhb
615128930Sjhb	/*
616125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
617128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
618128329Sjhb	 * force it to use level/lo.
619125048Sjhb	 */
620128930Sjhb	if (intr->Source == AcpiGbl_FADT->SciInt) {
621128930Sjhb		madt_found_sci_override = 1;
622128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
623128930Sjhb			if (tolower(buf[0]) == 'e')
624128930Sjhb				trig = INTR_TRIGGER_EDGE;
625128930Sjhb			else if (tolower(buf[0]) == 'l')
626128930Sjhb				trig = INTR_TRIGGER_LEVEL;
627128930Sjhb			else
628128930Sjhb				panic(
629128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
630128930Sjhb				    buf);
631128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
632128930Sjhb			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
633128930Sjhb		}
634128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
635128930Sjhb			if (tolower(buf[0]) == 'h')
636128930Sjhb				pol = INTR_POLARITY_HIGH;
637128930Sjhb			else if (tolower(buf[0]) == 'l')
638128930Sjhb				pol = INTR_POLARITY_LOW;
639128930Sjhb			else
640128930Sjhb				panic(
641128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
642128930Sjhb				    buf);
643128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
644128930Sjhb			    pol == INTR_POLARITY_HIGH ? "high" : "low");
645128930Sjhb		}
646128930Sjhb	}
647125048Sjhb
648128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
649123326Snjl	if (intr->Source != intr->Interrupt) {
650125048Sjhb		/*
651125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
652125048Sjhb		 * then override the vector we use to setup and allocate
653125048Sjhb		 * the interrupt.
654125048Sjhb		 */
655125048Sjhb		if (intr->Interrupt > 15 &&
656125048Sjhb		    intr->Source == AcpiGbl_FADT->SciInt)
657123326Snjl			acpi_OverrideInterruptLevel(intr->Interrupt);
658122502Sjhb		else
659122502Sjhb			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
660122149Sjhb		if (madt_find_interrupt(intr->Source, &old_ioapic,
661122149Sjhb		    &old_pin) != 0)
662122149Sjhb			printf("MADT: Could not find APIC for source IRQ %d\n",
663122149Sjhb			    intr->Source);
664122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
665122172Sjhb		    intr->Source)
666122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
667122149Sjhb	}
668128930Sjhb
669128930Sjhb	/* Program the polarity and trigger mode. */
670128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
671128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
672121992Sjhb}
673121992Sjhb
674121992Sjhb/*
675121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
676121992Sjhb */
677121992Sjhbstatic void
678123326Snjlmadt_parse_nmi(MADT_NMI_SOURCE *nmi)
679121992Sjhb{
680121992Sjhb	void *ioapic;
681121992Sjhb	u_int pin;
682121992Sjhb
683123326Snjl	if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
684121992Sjhb		printf("MADT: Could not find APIC for vector %d\n",
685123326Snjl		    nmi->Interrupt);
686121992Sjhb		return;
687121992Sjhb	}
688121992Sjhb
689121992Sjhb	ioapic_set_nmi(ioapic, pin);
690123326Snjl	if (nmi->TriggerMode != TRIGGER_CONFORMS)
691121992Sjhb		ioapic_set_triggermode(ioapic, pin,
692128930Sjhb		    interrupt_trigger(nmi->TriggerMode, 0));
693123326Snjl	if (nmi->Polarity != TRIGGER_CONFORMS)
694121992Sjhb		ioapic_set_polarity(ioapic, pin,
695128930Sjhb		    interrupt_polarity(nmi->Polarity, 0));
696121992Sjhb}
697121992Sjhb
698121992Sjhb/*
699121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
700121992Sjhb */
701121992Sjhbstatic void
702123326Snjlmadt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
703121992Sjhb{
704121992Sjhb	u_int apic_id, pin;
705121992Sjhb
706123326Snjl	if (nmi->ProcessorId == 0xff)
707121992Sjhb		apic_id = APIC_ID_ALL;
708123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
709121992Sjhb		if (bootverbose)
710121992Sjhb			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
711123326Snjl			    nmi->ProcessorId);
712121992Sjhb		return;
713121992Sjhb	}
714123326Snjl	if (nmi->Lint == 0)
715121992Sjhb		pin = LVT_LINT0;
716121992Sjhb	else
717121992Sjhb		pin = LVT_LINT1;
718121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
719123326Snjl	if (nmi->TriggerMode != TRIGGER_CONFORMS)
720121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
721128930Sjhb		    interrupt_trigger(nmi->TriggerMode, 0));
722123326Snjl	if (nmi->Polarity != POLARITY_CONFORMS)
723121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
724128930Sjhb		    interrupt_polarity(nmi->Polarity, 0));
725121992Sjhb}
726121992Sjhb
727121992Sjhb/*
728121992Sjhb * Parse interrupt entries.
729121992Sjhb */
730121992Sjhbstatic void
731121992Sjhbmadt_parse_ints(APIC_HEADER *entry, void *arg __unused)
732121992Sjhb{
733121992Sjhb
734121992Sjhb	switch (entry->Type) {
735123326Snjl	case APIC_XRUPT_OVERRIDE:
736121992Sjhb		madt_parse_interrupt_override(
737123326Snjl			(MADT_INTERRUPT_OVERRIDE *)entry);
738121992Sjhb		break;
739121992Sjhb	case APIC_NMI:
740123326Snjl		madt_parse_nmi((MADT_NMI_SOURCE *)entry);
741121992Sjhb		break;
742123326Snjl	case APIC_LOCAL_NMI:
743123326Snjl		madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
744121992Sjhb		break;
745121992Sjhb	}
746121992Sjhb}
747121992Sjhb
748121992Sjhb/*
749121992Sjhb * Setup per-CPU ACPI IDs.
750121992Sjhb */
751121992Sjhbstatic void
752121992Sjhbmadt_set_ids(void *dummy)
753121992Sjhb{
754121992Sjhb	struct pcpu *pc;
755121992Sjhb	u_int i, j;
756121992Sjhb
757121992Sjhb	if (madt == NULL)
758121992Sjhb		return;
759123133Sjhb	for (i = 0; i <= mp_maxid; i++) {
760121992Sjhb		if (CPU_ABSENT(i))
761121992Sjhb			continue;
762121992Sjhb		pc = pcpu_find(i);
763121992Sjhb		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
764121992Sjhb		for (j = 0; j < NLAPICS + 1; j++) {
765121992Sjhb			if (!lapics[j].la_present || !lapics[j].la_enabled)
766121992Sjhb				continue;
767121992Sjhb			if (lapics[j].la_apic_id == pc->pc_apic_id) {
768121992Sjhb				pc->pc_acpi_id = j;
769121992Sjhb				if (bootverbose)
770121992Sjhb					printf("APIC: CPU %u has ACPI ID %u\n",
771121992Sjhb					    i, j);
772121992Sjhb				break;
773121992Sjhb			}
774121992Sjhb		}
775121992Sjhb		if (j == NLAPICS + 1)
776121992Sjhb			panic("Unable to find ACPI ID for CPU %d", i);
777121992Sjhb	}
778121992Sjhb}
779121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
780