madt.c revision 169395
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 169395 2007-05-08 22:01:04Z 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
51150003Sobrien#include <contrib/dev/acpica/acpi.h>
52129094Sjhb#include <contrib/dev/acpica/actables.h>
53121992Sjhb#include <dev/acpica/acpivar.h>
54121992Sjhb#include <dev/pci/pcivar.h>
55121992Sjhb
56167814Sjkimtypedef	void madt_entry_handler(ACPI_SUBTABLE_HEADER *entry, void *arg);
57121992Sjhb
58121992Sjhb/* These two arrays are indexed by APIC IDs. */
59121992Sjhbstruct ioapic_info {
60121992Sjhb	void *io_apic;
61121992Sjhb	UINT32 io_vector;
62169395Sjhb} ioapics[MAX_APIC_ID + 1];
63121992Sjhb
64121992Sjhbstruct lapic_info {
65121992Sjhb	u_int la_enabled:1;
66129960Sjhb	u_int la_acpi_id:8;
67169395Sjhb} lapics[MAX_APIC_ID + 1];
68121992Sjhb
69128930Sjhbstatic int madt_found_sci_override;
70167814Sjkimstatic ACPI_TABLE_MADT *madt;
71121992Sjhbstatic vm_paddr_t madt_physaddr;
72121992Sjhbstatic vm_offset_t madt_length;
73121992Sjhb
74151897SrwatsonMALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
75121992Sjhb
76167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
77167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
78121992Sjhbstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
79121992Sjhbstatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
80121992Sjhbstatic void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
81121992Sjhbstatic void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
82167814Sjkimstatic void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
83167814Sjkimstatic void	madt_parse_interrupt_override(
84167814Sjkim		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
85167814Sjkimstatic void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
86167814Sjkim		    void *arg __unused);
87167814Sjkimstatic void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
88167814Sjkimstatic void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
89121992Sjhbstatic int	madt_probe(void);
90121992Sjhbstatic int	madt_probe_cpus(void);
91167814Sjkimstatic void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
92167814Sjkim		    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;
161129094Sjhb	void *table;
162121992Sjhb
163121992Sjhb	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
164167814Sjkim	if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) {
165121992Sjhb		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
166121992Sjhb		return (NULL);
167121992Sjhb	}
168121992Sjhb	length = header->Length;
169121992Sjhb	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
170129094Sjhb	table = madt_map(pa, offset, length);
171167814Sjkim	if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
172129094Sjhb		if (bootverbose)
173129094Sjhb			printf("MADT: Failed checksum for table %s\n", sig);
174129094Sjhb		madt_unmap(table, length);
175129094Sjhb		return (NULL);
176129094Sjhb	}
177129094Sjhb	return (table);
178121992Sjhb}
179121992Sjhb
180121992Sjhbstatic void
181121992Sjhbmadt_unmap_table(void *table)
182121992Sjhb{
183121992Sjhb	ACPI_TABLE_HEADER *header;
184121992Sjhb
185121992Sjhb	header = (ACPI_TABLE_HEADER *)table;
186121992Sjhb	madt_unmap(table, header->Length);
187121992Sjhb}
188121992Sjhb
189121992Sjhb/*
190121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
191121992Sjhb */
192121992Sjhbstatic int
193121992Sjhbmadt_probe(void)
194121992Sjhb{
195167814Sjkim	ACPI_PHYSICAL_ADDRESS rsdp_ptr;
196167814Sjkim	ACPI_TABLE_RSDP *rsdp;
197167814Sjkim	ACPI_TABLE_RSDT *rsdt;
198167814Sjkim	ACPI_TABLE_XSDT *xsdt;
199121992Sjhb	int i, count;
200121992Sjhb
201121992Sjhb	if (resource_disabled("acpi", 0))
202121992Sjhb		return (ENXIO);
203121992Sjhb
204121992Sjhb	/*
205121992Sjhb	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
206161223Sjhb	 * calls pmap_mapbios() to find the RSDP, we assume that we can use
207161223Sjhb	 * pmap_mapbios() to map the RSDP.
208121992Sjhb	 */
209167814Sjkim	if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
210121992Sjhb		return (ENXIO);
211167814Sjkim	rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
212121992Sjhb	if (rsdp == NULL) {
213121992Sjhb		if (bootverbose)
214121992Sjhb			printf("MADT: Failed to map RSDP\n");
215121992Sjhb		return (ENXIO);
216121992Sjhb	}
217121992Sjhb
218121992Sjhb	/*
219157179Sjhb	 * For ACPI >= 2.0, use the XSDT if it is available.
220157179Sjhb	 * Otherwise, use the RSDT.  We map the XSDT or RSDT at page 1
221157179Sjhb	 * in the crashdump area.  Page 0 is used to map in the
222157179Sjhb	 * headers of candidate ACPI tables.
223121992Sjhb	 */
224157179Sjhb	if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
225129094Sjhb		/*
226129094Sjhb		 * AcpiOsGetRootPointer only verifies the checksum for
227129094Sjhb		 * the version 1.0 portion of the RSDP.  Version 2.0 has
228129094Sjhb		 * an additional checksum that we verify first.
229129094Sjhb		 */
230167814Sjkim		if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
231129094Sjhb			if (bootverbose)
232129094Sjhb				printf("MADT: RSDP failed extended checksum\n");
233129094Sjhb			return (ENXIO);
234129094Sjhb		}
235167814Sjkim		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1,
236167814Sjkim		    ACPI_SIG_XSDT);
237121992Sjhb		if (xsdt == NULL) {
238121992Sjhb			if (bootverbose)
239121992Sjhb				printf("MADT: Failed to map XSDT\n");
240121992Sjhb			return (ENXIO);
241121992Sjhb		}
242167814Sjkim		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
243121992Sjhb		    sizeof(UINT64);
244121992Sjhb		for (i = 0; i < count; i++)
245121992Sjhb			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
246121992Sjhb				break;
247121992Sjhb		madt_unmap_table(xsdt);
248121992Sjhb	} else {
249167814Sjkim		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1,
250167814Sjkim		    ACPI_SIG_RSDT);
251121992Sjhb		if (rsdt == NULL) {
252121992Sjhb			if (bootverbose)
253121992Sjhb				printf("MADT: Failed to map RSDT\n");
254121992Sjhb			return (ENXIO);
255121992Sjhb		}
256167814Sjkim		count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
257121992Sjhb		    sizeof(UINT32);
258121992Sjhb		for (i = 0; i < count; i++)
259121992Sjhb			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
260121992Sjhb				break;
261121992Sjhb		madt_unmap_table(rsdt);
262121992Sjhb	}
263167814Sjkim	pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));
264121992Sjhb	if (madt_physaddr == 0) {
265121992Sjhb		if (bootverbose)
266121992Sjhb			printf("MADT: No MADT table found\n");
267121992Sjhb		return (ENXIO);
268121992Sjhb	}
269121992Sjhb	if (bootverbose)
270122016Speter		printf("MADT: Found table at 0x%jx\n",
271122016Speter		    (uintmax_t)madt_physaddr);
272121992Sjhb
273129094Sjhb	/*
274129094Sjhb	 * Verify that we can map the full table and that its checksum is
275129094Sjhb	 * correct, etc.
276129094Sjhb	 */
277167814Sjkim	madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
278129094Sjhb	if (madt == NULL)
279129094Sjhb		return (ENXIO);
280129094Sjhb	madt_unmap_table(madt);
281129094Sjhb	madt = NULL;
282129094Sjhb
283121992Sjhb	return (0);
284121992Sjhb}
285121992Sjhb
286121992Sjhb/*
287121992Sjhb * See if a given ACPI table is the MADT.
288121992Sjhb */
289121992Sjhbstatic int
290121992Sjhbmadt_probe_table(vm_paddr_t address)
291121992Sjhb{
292121992Sjhb	ACPI_TABLE_HEADER *table;
293121992Sjhb
294121992Sjhb	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
295121992Sjhb	if (table == NULL) {
296121992Sjhb		if (bootverbose)
297122016Speter			printf("MADT: Failed to map table at 0x%jx\n",
298122016Speter			    (uintmax_t)address);
299121992Sjhb		return (0);
300121992Sjhb	}
301121992Sjhb	if (bootverbose)
302122016Speter		printf("Table '%.4s' at 0x%jx\n", table->Signature,
303122016Speter		    (uintmax_t)address);
304121992Sjhb
305167814Sjkim	if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) {
306121992Sjhb		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
307121992Sjhb		return (0);
308121992Sjhb	}
309121992Sjhb	madt_physaddr = address;
310121992Sjhb	madt_length = table->Length;
311121992Sjhb	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
312121992Sjhb	return (1);
313121992Sjhb}
314121992Sjhb
315121992Sjhb/*
316121992Sjhb * Run through the MP table enumerating CPUs.
317121992Sjhb */
318121992Sjhbstatic int
319121992Sjhbmadt_probe_cpus(void)
320121992Sjhb{
321121992Sjhb
322167814Sjkim	madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
323121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
324121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
325121992Sjhb	madt_unmap_table(madt);
326121992Sjhb	madt = NULL;
327121992Sjhb	return (0);
328121992Sjhb}
329121992Sjhb
330121992Sjhb/*
331121992Sjhb * Initialize the local APIC on the BSP.
332121992Sjhb */
333121992Sjhbstatic int
334121992Sjhbmadt_setup_local(void)
335121992Sjhb{
336121992Sjhb
337161223Sjhb	madt = pmap_mapbios(madt_physaddr, madt_length);
338167814Sjkim	lapic_init(madt->Address);
339121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
340167814Sjkim	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
341167814Sjkim	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
342121992Sjhb
343121992Sjhb	/*
344121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
345121992Sjhb	 * perhaps emit a warning here if we find one?
346121992Sjhb	 */
347121992Sjhb	return (0);
348121992Sjhb}
349121992Sjhb
350121992Sjhb/*
351125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
352121992Sjhb */
353121992Sjhbstatic int
354121992Sjhbmadt_setup_io(void)
355121992Sjhb{
356128930Sjhb	void *ioapic;
357128930Sjhb	u_int pin;
358121992Sjhb	int i;
359121992Sjhb
360125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
361125048Sjhb	i = acpi_Startup();
362125048Sjhb	if (ACPI_FAILURE(i)) {
363125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
364125048Sjhb		    AcpiFormatException(i));
365125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
366125048Sjhb		panic("Using MADT but ACPI doesn't work");
367125048Sjhb	}
368125048Sjhb
369121992Sjhb	/* First, we run through adding I/O APIC's. */
370121992Sjhb	madt_walk_table(madt_parse_apics, NULL);
371121992Sjhb
372121992Sjhb	/* Second, we run through the table tweaking interrupt sources. */
373121992Sjhb	madt_walk_table(madt_parse_ints, NULL);
374121992Sjhb
375128930Sjhb	/*
376128930Sjhb	 * If there was not an explicit override entry for the SCI,
377128930Sjhb	 * force it to use level trigger and active-low polarity.
378128930Sjhb	 */
379128930Sjhb	if (!madt_found_sci_override) {
380167814Sjkim		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
381167814Sjkim		    &pin) != 0)
382167814Sjkim			printf("MADT: Could not find APIC for SCI IRQ %u\n",
383167814Sjkim			    AcpiGbl_FADT.SciInterrupt);
384128930Sjhb		else {
385128930Sjhb			printf(
386128930Sjhb	"MADT: Forcing active-low polarity and level trigger for SCI\n");
387128930Sjhb			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
388128930Sjhb			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
389128930Sjhb		}
390128930Sjhb	}
391128930Sjhb
392121992Sjhb	/* Third, we register all the I/O APIC's. */
393169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++)
394121992Sjhb		if (ioapics[i].io_apic != NULL)
395121992Sjhb			ioapic_register(ioapics[i].io_apic);
396121992Sjhb
397121992Sjhb	/* Finally, we throw the switch to enable the I/O APIC's. */
398121992Sjhb	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
399121992Sjhb
400121992Sjhb	return (0);
401121992Sjhb}
402121992Sjhb
403121992Sjhbstatic void
404121992Sjhbmadt_register(void *dummy __unused)
405121992Sjhb{
406121992Sjhb
407121992Sjhb	apic_register_enumerator(&madt_enumerator);
408121992Sjhb}
409123133SjhbSYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
410121992Sjhb
411121992Sjhb/*
412121992Sjhb * Call the handler routine for each entry in the MADT table.
413121992Sjhb */
414121992Sjhbstatic void
415121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg)
416121992Sjhb{
417167814Sjkim	ACPI_SUBTABLE_HEADER *entry;
418121992Sjhb	u_char *p, *end;
419121992Sjhb
420167814Sjkim	end = (u_char *)(madt) + madt->Header.Length;
421121992Sjhb	for (p = (u_char *)(madt + 1); p < end; ) {
422167814Sjkim		entry = (ACPI_SUBTABLE_HEADER *)p;
423121992Sjhb		handler(entry, arg);
424121992Sjhb		p += entry->Length;
425121992Sjhb	}
426121992Sjhb}
427121992Sjhb
428121992Sjhbstatic void
429167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
430121992Sjhb{
431167814Sjkim	ACPI_MADT_LOCAL_APIC *proc;
432121992Sjhb	struct lapic_info *la;
433121992Sjhb
434121992Sjhb	switch (entry->Type) {
435167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC:
436121992Sjhb		/*
437121992Sjhb		 * The MADT does not include a BSP flag, so we have to
438121992Sjhb		 * let the MP code figure out which CPU is the BSP on
439121992Sjhb		 * its own.
440121992Sjhb		 */
441167814Sjkim		proc = (ACPI_MADT_LOCAL_APIC *)entry;
442121992Sjhb		if (bootverbose)
443167814Sjkim			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
444167814Sjkim			    proc->Id, proc->ProcessorId,
445167814Sjkim			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
446167814Sjkim			    "enabled" : "disabled");
447167814Sjkim		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
448130310Sjhb			break;
449169395Sjhb		if (proc->Id > MAX_APIC_ID)
450167814Sjkim			panic("%s: CPU ID %u too high", __func__, proc->Id);
451167814Sjkim		la = &lapics[proc->Id];
452130310Sjhb		KASSERT(la->la_enabled == 0,
453167814Sjkim		    ("Duplicate local APIC ID %u", proc->Id));
454130310Sjhb		la->la_enabled = 1;
455129960Sjhb		la->la_acpi_id = proc->ProcessorId;
456167814Sjkim		lapic_create(proc->Id, 0);
457121992Sjhb		break;
458121992Sjhb	}
459121992Sjhb}
460121992Sjhb
461121992Sjhb
462121992Sjhb/*
463121992Sjhb * Add an I/O APIC from an entry in the table.
464121992Sjhb */
465121992Sjhbstatic void
466167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
467121992Sjhb{
468167814Sjkim	ACPI_MADT_IO_APIC *apic;
469121992Sjhb
470121992Sjhb	switch (entry->Type) {
471167814Sjkim	case ACPI_MADT_TYPE_IO_APIC:
472167814Sjkim		apic = (ACPI_MADT_IO_APIC *)entry;
473121992Sjhb		if (bootverbose)
474167814Sjkim			printf(
475167814Sjkim			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
476167814Sjkim			    apic->Id, apic->GlobalIrqBase,
477123326Snjl			    (void *)(uintptr_t)apic->Address);
478169395Sjhb		if (apic->Id > MAX_APIC_ID)
479167814Sjkim			panic("%s: I/O APIC ID %u too high", __func__,
480167814Sjkim			    apic->Id);
481167814Sjkim		if (ioapics[apic->Id].io_apic != NULL)
482167814Sjkim			panic("%s: Double APIC ID %u", __func__, apic->Id);
483167814Sjkim		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
484167814Sjkim		    apic->Id, apic->GlobalIrqBase);
485167814Sjkim		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
486121992Sjhb		break;
487121992Sjhb	default:
488121992Sjhb		break;
489121992Sjhb	}
490121992Sjhb}
491121992Sjhb
492121992Sjhb/*
493129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
494129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
495128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
496129128Sjhb * SCI for which we use Active Lo, Level Triggered.
497121992Sjhb */
498128930Sjhbstatic enum intr_polarity
499167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source)
500121992Sjhb{
501121992Sjhb
502167814Sjkim	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
503167814Sjkim	case ACPI_MADT_POLARITY_CONFORMS:
504167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
505128930Sjhb			return (INTR_POLARITY_LOW);
506128930Sjhb		else
507128930Sjhb			return (INTR_POLARITY_HIGH);
508167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
509128930Sjhb		return (INTR_POLARITY_HIGH);
510167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_LOW:
511128930Sjhb		return (INTR_POLARITY_LOW);
512121992Sjhb	default:
513121992Sjhb		panic("Bogus Interrupt Polarity");
514121992Sjhb	}
515121992Sjhb}
516121992Sjhb
517128930Sjhbstatic enum intr_trigger
518167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source)
519121992Sjhb{
520121992Sjhb
521167814Sjkim	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
522167814Sjkim	case ACPI_MADT_TRIGGER_CONFORMS:
523167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
524128930Sjhb			return (INTR_TRIGGER_LEVEL);
525128930Sjhb		else
526128930Sjhb			return (INTR_TRIGGER_EDGE);
527167814Sjkim	case ACPI_MADT_TRIGGER_EDGE:
528128930Sjhb		return (INTR_TRIGGER_EDGE);
529167814Sjkim	case ACPI_MADT_TRIGGER_LEVEL:
530128930Sjhb		return (INTR_TRIGGER_LEVEL);
531121992Sjhb	default:
532121992Sjhb		panic("Bogus Interrupt Trigger Mode");
533121992Sjhb	}
534121992Sjhb}
535121992Sjhb
536121992Sjhb/*
537121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
538121992Sjhb */
539121992Sjhbstatic int
540121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
541121992Sjhb{
542129960Sjhb	int i;
543121992Sjhb
544169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
545130310Sjhb		if (!lapics[i].la_enabled)
546129960Sjhb			continue;
547129960Sjhb		if (lapics[i].la_acpi_id != acpi_id)
548129960Sjhb			continue;
549129960Sjhb		*apic_id = i;
550130310Sjhb		return (0);
551129960Sjhb	}
552129960Sjhb	return (ENOENT);
553121992Sjhb}
554121992Sjhb
555121992Sjhb/*
556121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
557121992Sjhb * interrupt.
558121992Sjhb */
559121992Sjhbstatic int
560121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
561121992Sjhb{
562121992Sjhb	int i, best;
563121992Sjhb
564121992Sjhb	best = -1;
565169395Sjhb	for (i = 0; i <= MAX_APIC_ID; i++) {
566121992Sjhb		if (ioapics[i].io_apic == NULL ||
567121992Sjhb		    ioapics[i].io_vector > intr)
568121992Sjhb			continue;
569121992Sjhb		if (best == -1 ||
570121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
571121992Sjhb			best = i;
572121992Sjhb	}
573121992Sjhb	if (best == -1)
574121992Sjhb		return (ENOENT);
575121992Sjhb	*apic = ioapics[best].io_apic;
576121992Sjhb	*pin = intr - ioapics[best].io_vector;
577121992Sjhb	if (*pin > 32)
578121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
579121992Sjhb		    intr);
580121992Sjhb	return (0);
581121992Sjhb}
582121992Sjhb
583121992Sjhb/*
584121992Sjhb * Parse an interrupt source override for an ISA interrupt.
585121992Sjhb */
586121992Sjhbstatic void
587167814Sjkimmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
588121992Sjhb{
589122149Sjhb	void *new_ioapic, *old_ioapic;
590122149Sjhb	u_int new_pin, old_pin;
591128930Sjhb	enum intr_trigger trig;
592128930Sjhb	enum intr_polarity pol;
593128930Sjhb	char buf[64];
594121992Sjhb
595167814Sjkim	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
596167814Sjkim	    intr->GlobalIrq == 2) {
597142257Sjhb		if (bootverbose)
598142257Sjhb			printf("MADT: Skipping timer override\n");
599142257Sjhb		return;
600142257Sjhb	}
601121992Sjhb	if (bootverbose)
602142257Sjhb		printf("MADT: Interrupt override: source %u, irq %u\n",
603167814Sjkim		    intr->SourceIrq, intr->GlobalIrq);
604121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
605167814Sjkim	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
606167814Sjkim		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
607167814Sjkim		    intr->GlobalIrq, intr->SourceIrq);
608121992Sjhb		return;
609121992Sjhb	}
610121992Sjhb
611125048Sjhb	/*
612128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
613128930Sjhb	 * entry.
614128930Sjhb	 */
615167814Sjkim	trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
616167814Sjkim	pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
617128930Sjhb
618128930Sjhb	/*
619125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
620128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
621128329Sjhb	 * force it to use level/lo.
622125048Sjhb	 */
623167814Sjkim	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
624128930Sjhb		madt_found_sci_override = 1;
625128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
626128930Sjhb			if (tolower(buf[0]) == 'e')
627128930Sjhb				trig = INTR_TRIGGER_EDGE;
628128930Sjhb			else if (tolower(buf[0]) == 'l')
629128930Sjhb				trig = INTR_TRIGGER_LEVEL;
630128930Sjhb			else
631128930Sjhb				panic(
632128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
633128930Sjhb				    buf);
634128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
635128930Sjhb			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
636128930Sjhb		}
637128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
638128930Sjhb			if (tolower(buf[0]) == 'h')
639128930Sjhb				pol = INTR_POLARITY_HIGH;
640128930Sjhb			else if (tolower(buf[0]) == 'l')
641128930Sjhb				pol = INTR_POLARITY_LOW;
642128930Sjhb			else
643128930Sjhb				panic(
644128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
645128930Sjhb				    buf);
646128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
647128930Sjhb			    pol == INTR_POLARITY_HIGH ? "high" : "low");
648128930Sjhb		}
649128930Sjhb	}
650125048Sjhb
651128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
652167814Sjkim	if (intr->SourceIrq != intr->GlobalIrq) {
653125048Sjhb		/*
654125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
655125048Sjhb		 * then override the vector we use to setup and allocate
656125048Sjhb		 * the interrupt.
657125048Sjhb		 */
658167814Sjkim		if (intr->GlobalIrq > 15 &&
659167814Sjkim		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
660167814Sjkim			acpi_OverrideInterruptLevel(intr->GlobalIrq);
661122502Sjhb		else
662167814Sjkim			ioapic_remap_vector(new_ioapic, new_pin,
663167814Sjkim			    intr->SourceIrq);
664167814Sjkim		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
665122149Sjhb		    &old_pin) != 0)
666167814Sjkim			printf("MADT: Could not find APIC for source IRQ %u\n",
667167814Sjkim			    intr->SourceIrq);
668122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
669167814Sjkim		    intr->SourceIrq)
670122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
671122149Sjhb	}
672128930Sjhb
673128930Sjhb	/* Program the polarity and trigger mode. */
674128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
675128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
676121992Sjhb}
677121992Sjhb
678121992Sjhb/*
679121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
680121992Sjhb */
681121992Sjhbstatic void
682167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
683121992Sjhb{
684121992Sjhb	void *ioapic;
685121992Sjhb	u_int pin;
686121992Sjhb
687167814Sjkim	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
688167814Sjkim		printf("MADT: Could not find APIC for vector %u\n",
689167814Sjkim		    nmi->GlobalIrq);
690121992Sjhb		return;
691121992Sjhb	}
692121992Sjhb
693121992Sjhb	ioapic_set_nmi(ioapic, pin);
694167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
695121992Sjhb		ioapic_set_triggermode(ioapic, pin,
696167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
697167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
698121992Sjhb		ioapic_set_polarity(ioapic, pin,
699167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
700121992Sjhb}
701121992Sjhb
702121992Sjhb/*
703121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
704121992Sjhb */
705121992Sjhbstatic void
706167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
707121992Sjhb{
708121992Sjhb	u_int apic_id, pin;
709121992Sjhb
710123326Snjl	if (nmi->ProcessorId == 0xff)
711121992Sjhb		apic_id = APIC_ID_ALL;
712123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
713121992Sjhb		if (bootverbose)
714167814Sjkim			printf("MADT: Ignoring local NMI routed to "
715167814Sjkim			    "ACPI CPU %u\n", nmi->ProcessorId);
716121992Sjhb		return;
717121992Sjhb	}
718123326Snjl	if (nmi->Lint == 0)
719121992Sjhb		pin = LVT_LINT0;
720121992Sjhb	else
721121992Sjhb		pin = LVT_LINT1;
722121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
723167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
724121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
725167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
726167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
727121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
728167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
729121992Sjhb}
730121992Sjhb
731121992Sjhb/*
732121992Sjhb * Parse interrupt entries.
733121992Sjhb */
734121992Sjhbstatic void
735167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
736121992Sjhb{
737121992Sjhb
738121992Sjhb	switch (entry->Type) {
739167814Sjkim	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
740121992Sjhb		madt_parse_interrupt_override(
741167814Sjkim			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
742121992Sjhb		break;
743167814Sjkim	case ACPI_MADT_TYPE_NMI_SOURCE:
744167814Sjkim		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
745121992Sjhb		break;
746167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
747167814Sjkim		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
748121992Sjhb		break;
749121992Sjhb	}
750121992Sjhb}
751121992Sjhb
752121992Sjhb/*
753121992Sjhb * Setup per-CPU ACPI IDs.
754121992Sjhb */
755121992Sjhbstatic void
756121992Sjhbmadt_set_ids(void *dummy)
757121992Sjhb{
758129960Sjhb	struct lapic_info *la;
759121992Sjhb	struct pcpu *pc;
760129960Sjhb	u_int i;
761121992Sjhb
762121992Sjhb	if (madt == NULL)
763121992Sjhb		return;
764123133Sjhb	for (i = 0; i <= mp_maxid; i++) {
765121992Sjhb		if (CPU_ABSENT(i))
766121992Sjhb			continue;
767121992Sjhb		pc = pcpu_find(i);
768167814Sjkim		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
769129960Sjhb		la = &lapics[pc->pc_apic_id];
770130310Sjhb		if (!la->la_enabled)
771129960Sjhb			panic("APIC: CPU with APIC ID %u is not enabled",
772129960Sjhb			    pc->pc_apic_id);
773129960Sjhb		pc->pc_acpi_id = la->la_acpi_id;
774129960Sjhb		if (bootverbose)
775129960Sjhb			printf("APIC: CPU %u has ACPI ID %u\n", i,
776129960Sjhb			    la->la_acpi_id);
777121992Sjhb	}
778121992Sjhb}
779121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
780