madt.c revision 167814
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 167814 2007-03-22 18:16:43Z jkim $");
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
56122434Sjhb#define	NIOAPICS		32	/* Max number of I/O APICs */
57122434Sjhb#define	NLAPICS			32	/* Max number of local APICs */
58121992Sjhb
59167814Sjkimtypedef	void madt_entry_handler(ACPI_SUBTABLE_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_enabled:1;
69129960Sjhb	u_int la_acpi_id:8;
70129960Sjhb} lapics[NLAPICS];
71121992Sjhb
72128930Sjhbstatic int madt_found_sci_override;
73167814Sjkimstatic ACPI_TABLE_MADT *madt;
74121992Sjhbstatic vm_paddr_t madt_physaddr;
75121992Sjhbstatic vm_offset_t madt_length;
76121992Sjhb
77151897SrwatsonMALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
78121992Sjhb
79167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
80167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
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);
85167814Sjkimstatic void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
86167814Sjkimstatic void	madt_parse_interrupt_override(
87167814Sjkim		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
88167814Sjkimstatic void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
89167814Sjkim		    void *arg __unused);
90167814Sjkimstatic void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
91167814Sjkimstatic void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
92121992Sjhbstatic int	madt_probe(void);
93121992Sjhbstatic int	madt_probe_cpus(void);
94167814Sjkimstatic void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
95167814Sjkim		    void *arg __unused);
96121992Sjhbstatic int	madt_probe_table(vm_paddr_t address);
97121992Sjhbstatic void	madt_register(void *dummy);
98121992Sjhbstatic int	madt_setup_local(void);
99121992Sjhbstatic int	madt_setup_io(void);
100121992Sjhbstatic void	madt_unmap(void *data, vm_offset_t length);
101121992Sjhbstatic void	madt_unmap_table(void *table);
102121992Sjhbstatic void	madt_walk_table(madt_entry_handler *handler, void *arg);
103121992Sjhb
104121992Sjhbstatic struct apic_enumerator madt_enumerator = {
105121992Sjhb	"MADT",
106121992Sjhb	madt_probe,
107121992Sjhb	madt_probe_cpus,
108121992Sjhb	madt_setup_local,
109121992Sjhb	madt_setup_io
110121992Sjhb};
111121992Sjhb
112121992Sjhb/*
113121992Sjhb * Code to abuse the crashdump map to map in the tables for the early
114121992Sjhb * probe.  We cheat and make the following assumptions about how we
115121992Sjhb * use this KVA: page 0 is used to map in the first page of each table
116121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the
117121992Sjhb * RSDT or XSDT.  The offset is in pages; the length is in bytes.
118121992Sjhb */
119121992Sjhbstatic void *
120121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length)
121121992Sjhb{
122121992Sjhb	vm_offset_t va, off;
123121992Sjhb	void *data;
124121992Sjhb
125121992Sjhb	off = pa & PAGE_MASK;
126121992Sjhb	length = roundup(length + off, PAGE_SIZE);
127121992Sjhb	pa = pa & PG_FRAME;
128121992Sjhb	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
129121992Sjhb	    (offset * PAGE_SIZE);
130121992Sjhb	data = (void *)(va + off);
131121992Sjhb	length -= PAGE_SIZE;
132121992Sjhb	while (length > 0) {
133121992Sjhb		va += PAGE_SIZE;
134121992Sjhb		pa += PAGE_SIZE;
135121992Sjhb		length -= PAGE_SIZE;
136121992Sjhb		pmap_kenter(va, pa);
137121992Sjhb		invlpg(va);
138121992Sjhb	}
139121992Sjhb	return (data);
140121992Sjhb}
141121992Sjhb
142121992Sjhbstatic void
143121992Sjhbmadt_unmap(void *data, vm_offset_t length)
144121992Sjhb{
145121992Sjhb	vm_offset_t va, off;
146121992Sjhb
147121992Sjhb	va = (vm_offset_t)data;
148121992Sjhb	off = va & PAGE_MASK;
149121992Sjhb	length = roundup(length + off, PAGE_SIZE);
150121992Sjhb	va &= ~PAGE_MASK;
151121992Sjhb	while (length > 0) {
152121992Sjhb		pmap_kremove(va);
153121992Sjhb		invlpg(va);
154121992Sjhb		va += PAGE_SIZE;
155121992Sjhb		length -= PAGE_SIZE;
156121992Sjhb	}
157121992Sjhb}
158121992Sjhb
159121992Sjhbstatic void *
160121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig)
161121992Sjhb{
162121992Sjhb	ACPI_TABLE_HEADER *header;
163121992Sjhb	vm_offset_t length;
164129094Sjhb	void *table;
165121992Sjhb
166121992Sjhb	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
167167814Sjkim	if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) {
168121992Sjhb		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
169121992Sjhb		return (NULL);
170121992Sjhb	}
171121992Sjhb	length = header->Length;
172121992Sjhb	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
173129094Sjhb	table = madt_map(pa, offset, length);
174167814Sjkim	if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
175129094Sjhb		if (bootverbose)
176129094Sjhb			printf("MADT: Failed checksum for table %s\n", sig);
177129094Sjhb		madt_unmap(table, length);
178129094Sjhb		return (NULL);
179129094Sjhb	}
180129094Sjhb	return (table);
181121992Sjhb}
182121992Sjhb
183121992Sjhbstatic void
184121992Sjhbmadt_unmap_table(void *table)
185121992Sjhb{
186121992Sjhb	ACPI_TABLE_HEADER *header;
187121992Sjhb
188121992Sjhb	header = (ACPI_TABLE_HEADER *)table;
189121992Sjhb	madt_unmap(table, header->Length);
190121992Sjhb}
191121992Sjhb
192121992Sjhb/*
193121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC")
194121992Sjhb */
195121992Sjhbstatic int
196121992Sjhbmadt_probe(void)
197121992Sjhb{
198167814Sjkim	ACPI_PHYSICAL_ADDRESS rsdp_ptr;
199167814Sjkim	ACPI_TABLE_RSDP *rsdp;
200167814Sjkim	ACPI_TABLE_RSDT *rsdt;
201167814Sjkim	ACPI_TABLE_XSDT *xsdt;
202121992Sjhb	int i, count;
203121992Sjhb
204121992Sjhb	if (resource_disabled("acpi", 0))
205121992Sjhb		return (ENXIO);
206121992Sjhb
207121992Sjhb	/*
208121992Sjhb	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
209161223Sjhb	 * calls pmap_mapbios() to find the RSDP, we assume that we can use
210161223Sjhb	 * pmap_mapbios() to map the RSDP.
211121992Sjhb	 */
212167814Sjkim	if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
213121992Sjhb		return (ENXIO);
214167814Sjkim	rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
215121992Sjhb	if (rsdp == NULL) {
216121992Sjhb		if (bootverbose)
217121992Sjhb			printf("MADT: Failed to map RSDP\n");
218121992Sjhb		return (ENXIO);
219121992Sjhb	}
220121992Sjhb
221121992Sjhb	/*
222157179Sjhb	 * For ACPI >= 2.0, use the XSDT if it is available.
223157179Sjhb	 * Otherwise, use the RSDT.  We map the XSDT or RSDT at page 1
224157179Sjhb	 * in the crashdump area.  Page 0 is used to map in the
225157179Sjhb	 * headers of candidate ACPI tables.
226121992Sjhb	 */
227157179Sjhb	if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
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		 */
233167814Sjkim		if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
234129094Sjhb			if (bootverbose)
235129094Sjhb				printf("MADT: RSDP failed extended checksum\n");
236129094Sjhb			return (ENXIO);
237129094Sjhb		}
238167814Sjkim		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1,
239167814Sjkim		    ACPI_SIG_XSDT);
240121992Sjhb		if (xsdt == NULL) {
241121992Sjhb			if (bootverbose)
242121992Sjhb				printf("MADT: Failed to map XSDT\n");
243121992Sjhb			return (ENXIO);
244121992Sjhb		}
245167814Sjkim		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
246121992Sjhb		    sizeof(UINT64);
247121992Sjhb		for (i = 0; i < count; i++)
248121992Sjhb			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
249121992Sjhb				break;
250121992Sjhb		madt_unmap_table(xsdt);
251121992Sjhb	} else {
252167814Sjkim		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1,
253167814Sjkim		    ACPI_SIG_RSDT);
254121992Sjhb		if (rsdt == NULL) {
255121992Sjhb			if (bootverbose)
256121992Sjhb				printf("MADT: Failed to map RSDT\n");
257121992Sjhb			return (ENXIO);
258121992Sjhb		}
259167814Sjkim		count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
260121992Sjhb		    sizeof(UINT32);
261121992Sjhb		for (i = 0; i < count; i++)
262121992Sjhb			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
263121992Sjhb				break;
264121992Sjhb		madt_unmap_table(rsdt);
265121992Sjhb	}
266167814Sjkim	pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));
267121992Sjhb	if (madt_physaddr == 0) {
268121992Sjhb		if (bootverbose)
269121992Sjhb			printf("MADT: No MADT table found\n");
270121992Sjhb		return (ENXIO);
271121992Sjhb	}
272121992Sjhb	if (bootverbose)
273122016Speter		printf("MADT: Found table at 0x%jx\n",
274122016Speter		    (uintmax_t)madt_physaddr);
275121992Sjhb
276129094Sjhb	/*
277129094Sjhb	 * Verify that we can map the full table and that its checksum is
278129094Sjhb	 * correct, etc.
279129094Sjhb	 */
280167814Sjkim	madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
281129094Sjhb	if (madt == NULL)
282129094Sjhb		return (ENXIO);
283129094Sjhb	madt_unmap_table(madt);
284129094Sjhb	madt = NULL;
285129094Sjhb
286121992Sjhb	return (0);
287121992Sjhb}
288121992Sjhb
289121992Sjhb/*
290121992Sjhb * See if a given ACPI table is the MADT.
291121992Sjhb */
292121992Sjhbstatic int
293121992Sjhbmadt_probe_table(vm_paddr_t address)
294121992Sjhb{
295121992Sjhb	ACPI_TABLE_HEADER *table;
296121992Sjhb
297121992Sjhb	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
298121992Sjhb	if (table == NULL) {
299121992Sjhb		if (bootverbose)
300122016Speter			printf("MADT: Failed to map table at 0x%jx\n",
301122016Speter			    (uintmax_t)address);
302121992Sjhb		return (0);
303121992Sjhb	}
304121992Sjhb	if (bootverbose)
305122016Speter		printf("Table '%.4s' at 0x%jx\n", table->Signature,
306122016Speter		    (uintmax_t)address);
307121992Sjhb
308167814Sjkim	if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) {
309121992Sjhb		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
310121992Sjhb		return (0);
311121992Sjhb	}
312121992Sjhb	madt_physaddr = address;
313121992Sjhb	madt_length = table->Length;
314121992Sjhb	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
315121992Sjhb	return (1);
316121992Sjhb}
317121992Sjhb
318121992Sjhb/*
319121992Sjhb * Run through the MP table enumerating CPUs.
320121992Sjhb */
321121992Sjhbstatic int
322121992Sjhbmadt_probe_cpus(void)
323121992Sjhb{
324121992Sjhb
325167814Sjkim	madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
326121992Sjhb	KASSERT(madt != NULL, ("Unable to re-map MADT"));
327121992Sjhb	madt_walk_table(madt_probe_cpus_handler, NULL);
328121992Sjhb	madt_unmap_table(madt);
329121992Sjhb	madt = NULL;
330121992Sjhb	return (0);
331121992Sjhb}
332121992Sjhb
333121992Sjhb/*
334121992Sjhb * Initialize the local APIC on the BSP.
335121992Sjhb */
336121992Sjhbstatic int
337121992Sjhbmadt_setup_local(void)
338121992Sjhb{
339121992Sjhb
340161223Sjhb	madt = pmap_mapbios(madt_physaddr, madt_length);
341167814Sjkim	lapic_init(madt->Address);
342121992Sjhb	printf("ACPI APIC Table: <%.*s %.*s>\n",
343167814Sjkim	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
344167814Sjkim	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
345121992Sjhb
346121992Sjhb	/*
347121992Sjhb	 * We ignore 64-bit local APIC override entries.  Should we
348121992Sjhb	 * perhaps emit a warning here if we find one?
349121992Sjhb	 */
350121992Sjhb	return (0);
351121992Sjhb}
352121992Sjhb
353121992Sjhb/*
354125048Sjhb * Enumerate I/O APICs and setup interrupt sources.
355121992Sjhb */
356121992Sjhbstatic int
357121992Sjhbmadt_setup_io(void)
358121992Sjhb{
359128930Sjhb	void *ioapic;
360128930Sjhb	u_int pin;
361121992Sjhb	int i;
362121992Sjhb
363125048Sjhb	/* Try to initialize ACPI so that we can access the FADT. */
364125048Sjhb	i = acpi_Startup();
365125048Sjhb	if (ACPI_FAILURE(i)) {
366125048Sjhb		printf("MADT: ACPI Startup failed with %s\n",
367125048Sjhb		    AcpiFormatException(i));
368125048Sjhb		printf("Try disabling either ACPI or apic support.\n");
369125048Sjhb		panic("Using MADT but ACPI doesn't work");
370125048Sjhb	}
371125048Sjhb
372121992Sjhb	/* First, we run through adding I/O APIC's. */
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) {
383167814Sjkim		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
384167814Sjkim		    &pin) != 0)
385167814Sjkim			printf("MADT: Could not find APIC for SCI IRQ %u\n",
386167814Sjkim			    AcpiGbl_FADT.SciInterrupt);
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{
420167814Sjkim	ACPI_SUBTABLE_HEADER *entry;
421121992Sjhb	u_char *p, *end;
422121992Sjhb
423167814Sjkim	end = (u_char *)(madt) + madt->Header.Length;
424121992Sjhb	for (p = (u_char *)(madt + 1); p < end; ) {
425167814Sjkim		entry = (ACPI_SUBTABLE_HEADER *)p;
426121992Sjhb		handler(entry, arg);
427121992Sjhb		p += entry->Length;
428121992Sjhb	}
429121992Sjhb}
430121992Sjhb
431121992Sjhbstatic void
432167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
433121992Sjhb{
434167814Sjkim	ACPI_MADT_LOCAL_APIC *proc;
435121992Sjhb	struct lapic_info *la;
436121992Sjhb
437121992Sjhb	switch (entry->Type) {
438167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC:
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		 */
444167814Sjkim		proc = (ACPI_MADT_LOCAL_APIC *)entry;
445121992Sjhb		if (bootverbose)
446167814Sjkim			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
447167814Sjkim			    proc->Id, proc->ProcessorId,
448167814Sjkim			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
449167814Sjkim			    "enabled" : "disabled");
450167814Sjkim		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
451130310Sjhb			break;
452167814Sjkim		if (proc->Id >= NLAPICS)
453167814Sjkim			panic("%s: CPU ID %u too high", __func__, proc->Id);
454167814Sjkim		la = &lapics[proc->Id];
455130310Sjhb		KASSERT(la->la_enabled == 0,
456167814Sjkim		    ("Duplicate local APIC ID %u", proc->Id));
457130310Sjhb		la->la_enabled = 1;
458129960Sjhb		la->la_acpi_id = proc->ProcessorId;
459167814Sjkim		lapic_create(proc->Id, 0);
460121992Sjhb		break;
461121992Sjhb	}
462121992Sjhb}
463121992Sjhb
464121992Sjhb
465121992Sjhb/*
466121992Sjhb * Add an I/O APIC from an entry in the table.
467121992Sjhb */
468121992Sjhbstatic void
469167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
470121992Sjhb{
471167814Sjkim	ACPI_MADT_IO_APIC *apic;
472121992Sjhb
473121992Sjhb	switch (entry->Type) {
474167814Sjkim	case ACPI_MADT_TYPE_IO_APIC:
475167814Sjkim		apic = (ACPI_MADT_IO_APIC *)entry;
476121992Sjhb		if (bootverbose)
477167814Sjkim			printf(
478167814Sjkim			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
479167814Sjkim			    apic->Id, apic->GlobalIrqBase,
480123326Snjl			    (void *)(uintptr_t)apic->Address);
481167814Sjkim		if (apic->Id >= NIOAPICS)
482167814Sjkim			panic("%s: I/O APIC ID %u too high", __func__,
483167814Sjkim			    apic->Id);
484167814Sjkim		if (ioapics[apic->Id].io_apic != NULL)
485167814Sjkim			panic("%s: Double APIC ID %u", __func__, apic->Id);
486167814Sjkim		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
487167814Sjkim		    apic->Id, apic->GlobalIrqBase);
488167814Sjkim		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
489121992Sjhb		break;
490121992Sjhb	default:
491121992Sjhb		break;
492121992Sjhb	}
493121992Sjhb}
494121992Sjhb
495121992Sjhb/*
496129128Sjhb * Determine properties of an interrupt source.  Note that for ACPI these
497129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values
498128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI
499129128Sjhb * SCI for which we use Active Lo, Level Triggered.
500121992Sjhb */
501128930Sjhbstatic enum intr_polarity
502167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source)
503121992Sjhb{
504121992Sjhb
505167814Sjkim	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
506167814Sjkim	case ACPI_MADT_POLARITY_CONFORMS:
507167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
508128930Sjhb			return (INTR_POLARITY_LOW);
509128930Sjhb		else
510128930Sjhb			return (INTR_POLARITY_HIGH);
511167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
512128930Sjhb		return (INTR_POLARITY_HIGH);
513167814Sjkim	case ACPI_MADT_POLARITY_ACTIVE_LOW:
514128930Sjhb		return (INTR_POLARITY_LOW);
515121992Sjhb	default:
516121992Sjhb		panic("Bogus Interrupt Polarity");
517121992Sjhb	}
518121992Sjhb}
519121992Sjhb
520128930Sjhbstatic enum intr_trigger
521167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source)
522121992Sjhb{
523121992Sjhb
524167814Sjkim	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
525167814Sjkim	case ACPI_MADT_TRIGGER_CONFORMS:
526167814Sjkim		if (Source == AcpiGbl_FADT.SciInterrupt)
527128930Sjhb			return (INTR_TRIGGER_LEVEL);
528128930Sjhb		else
529128930Sjhb			return (INTR_TRIGGER_EDGE);
530167814Sjkim	case ACPI_MADT_TRIGGER_EDGE:
531128930Sjhb		return (INTR_TRIGGER_EDGE);
532167814Sjkim	case ACPI_MADT_TRIGGER_LEVEL:
533128930Sjhb		return (INTR_TRIGGER_LEVEL);
534121992Sjhb	default:
535121992Sjhb		panic("Bogus Interrupt Trigger Mode");
536121992Sjhb	}
537121992Sjhb}
538121992Sjhb
539121992Sjhb/*
540121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID.
541121992Sjhb */
542121992Sjhbstatic int
543121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id)
544121992Sjhb{
545129960Sjhb	int i;
546121992Sjhb
547129960Sjhb	for (i = 0; i < NLAPICS; i++) {
548130310Sjhb		if (!lapics[i].la_enabled)
549129960Sjhb			continue;
550129960Sjhb		if (lapics[i].la_acpi_id != acpi_id)
551129960Sjhb			continue;
552129960Sjhb		*apic_id = i;
553130310Sjhb		return (0);
554129960Sjhb	}
555129960Sjhb	return (ENOENT);
556121992Sjhb}
557121992Sjhb
558121992Sjhb/*
559121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global
560121992Sjhb * interrupt.
561121992Sjhb */
562121992Sjhbstatic int
563121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin)
564121992Sjhb{
565121992Sjhb	int i, best;
566121992Sjhb
567121992Sjhb	best = -1;
568121992Sjhb	for (i = 0; i < NIOAPICS; i++) {
569121992Sjhb		if (ioapics[i].io_apic == NULL ||
570121992Sjhb		    ioapics[i].io_vector > intr)
571121992Sjhb			continue;
572121992Sjhb		if (best == -1 ||
573121992Sjhb		    ioapics[best].io_vector < ioapics[i].io_vector)
574121992Sjhb			best = i;
575121992Sjhb	}
576121992Sjhb	if (best == -1)
577121992Sjhb		return (ENOENT);
578121992Sjhb	*apic = ioapics[best].io_apic;
579121992Sjhb	*pin = intr - ioapics[best].io_vector;
580121992Sjhb	if (*pin > 32)
581121992Sjhb		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
582121992Sjhb		    intr);
583121992Sjhb	return (0);
584121992Sjhb}
585121992Sjhb
586121992Sjhb/*
587121992Sjhb * Parse an interrupt source override for an ISA interrupt.
588121992Sjhb */
589121992Sjhbstatic void
590167814Sjkimmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
591121992Sjhb{
592122149Sjhb	void *new_ioapic, *old_ioapic;
593122149Sjhb	u_int new_pin, old_pin;
594128930Sjhb	enum intr_trigger trig;
595128930Sjhb	enum intr_polarity pol;
596128930Sjhb	char buf[64];
597121992Sjhb
598167814Sjkim	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
599167814Sjkim	    intr->GlobalIrq == 2) {
600142257Sjhb		if (bootverbose)
601142257Sjhb			printf("MADT: Skipping timer override\n");
602142257Sjhb		return;
603142257Sjhb	}
604121992Sjhb	if (bootverbose)
605142257Sjhb		printf("MADT: Interrupt override: source %u, irq %u\n",
606167814Sjkim		    intr->SourceIrq, intr->GlobalIrq);
607121992Sjhb	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
608167814Sjkim	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
609167814Sjkim		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
610167814Sjkim		    intr->GlobalIrq, intr->SourceIrq);
611121992Sjhb		return;
612121992Sjhb	}
613121992Sjhb
614125048Sjhb	/*
615128930Sjhb	 * Lookup the appropriate trigger and polarity modes for this
616128930Sjhb	 * entry.
617128930Sjhb	 */
618167814Sjkim	trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
619167814Sjkim	pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
620128930Sjhb
621128930Sjhb	/*
622125048Sjhb	 * If the SCI is identity mapped but has edge trigger and
623128329Sjhb	 * active-hi polarity or the force_sci_lo tunable is set,
624128329Sjhb	 * force it to use level/lo.
625125048Sjhb	 */
626167814Sjkim	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
627128930Sjhb		madt_found_sci_override = 1;
628128930Sjhb		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
629128930Sjhb			if (tolower(buf[0]) == 'e')
630128930Sjhb				trig = INTR_TRIGGER_EDGE;
631128930Sjhb			else if (tolower(buf[0]) == 'l')
632128930Sjhb				trig = INTR_TRIGGER_LEVEL;
633128930Sjhb			else
634128930Sjhb				panic(
635128930Sjhb				"Invalid trigger %s: must be 'edge' or 'level'",
636128930Sjhb				    buf);
637128930Sjhb			printf("MADT: Forcing SCI to %s trigger\n",
638128930Sjhb			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
639128930Sjhb		}
640128930Sjhb		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
641128930Sjhb			if (tolower(buf[0]) == 'h')
642128930Sjhb				pol = INTR_POLARITY_HIGH;
643128930Sjhb			else if (tolower(buf[0]) == 'l')
644128930Sjhb				pol = INTR_POLARITY_LOW;
645128930Sjhb			else
646128930Sjhb				panic(
647128930Sjhb				"Invalid polarity %s: must be 'high' or 'low'",
648128930Sjhb				    buf);
649128930Sjhb			printf("MADT: Forcing SCI to active %s polarity\n",
650128930Sjhb			    pol == INTR_POLARITY_HIGH ? "high" : "low");
651128930Sjhb		}
652128930Sjhb	}
653125048Sjhb
654128930Sjhb	/* Remap the IRQ if it is mapped to a different interrupt vector. */
655167814Sjkim	if (intr->SourceIrq != intr->GlobalIrq) {
656125048Sjhb		/*
657125048Sjhb		 * If the SCI is remapped to a non-ISA global interrupt,
658125048Sjhb		 * then override the vector we use to setup and allocate
659125048Sjhb		 * the interrupt.
660125048Sjhb		 */
661167814Sjkim		if (intr->GlobalIrq > 15 &&
662167814Sjkim		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
663167814Sjkim			acpi_OverrideInterruptLevel(intr->GlobalIrq);
664122502Sjhb		else
665167814Sjkim			ioapic_remap_vector(new_ioapic, new_pin,
666167814Sjkim			    intr->SourceIrq);
667167814Sjkim		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
668122149Sjhb		    &old_pin) != 0)
669167814Sjkim			printf("MADT: Could not find APIC for source IRQ %u\n",
670167814Sjkim			    intr->SourceIrq);
671122172Sjhb		else if (ioapic_get_vector(old_ioapic, old_pin) ==
672167814Sjkim		    intr->SourceIrq)
673122149Sjhb			ioapic_disable_pin(old_ioapic, old_pin);
674122149Sjhb	}
675128930Sjhb
676128930Sjhb	/* Program the polarity and trigger mode. */
677128930Sjhb	ioapic_set_triggermode(new_ioapic, new_pin, trig);
678128930Sjhb	ioapic_set_polarity(new_ioapic, new_pin, pol);
679121992Sjhb}
680121992Sjhb
681121992Sjhb/*
682121992Sjhb * Parse an entry for an NMI routed to an IO APIC.
683121992Sjhb */
684121992Sjhbstatic void
685167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
686121992Sjhb{
687121992Sjhb	void *ioapic;
688121992Sjhb	u_int pin;
689121992Sjhb
690167814Sjkim	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
691167814Sjkim		printf("MADT: Could not find APIC for vector %u\n",
692167814Sjkim		    nmi->GlobalIrq);
693121992Sjhb		return;
694121992Sjhb	}
695121992Sjhb
696121992Sjhb	ioapic_set_nmi(ioapic, pin);
697167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
698121992Sjhb		ioapic_set_triggermode(ioapic, pin,
699167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
700167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
701121992Sjhb		ioapic_set_polarity(ioapic, pin,
702167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
703121992Sjhb}
704121992Sjhb
705121992Sjhb/*
706121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin.
707121992Sjhb */
708121992Sjhbstatic void
709167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
710121992Sjhb{
711121992Sjhb	u_int apic_id, pin;
712121992Sjhb
713123326Snjl	if (nmi->ProcessorId == 0xff)
714121992Sjhb		apic_id = APIC_ID_ALL;
715123326Snjl	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
716121992Sjhb		if (bootverbose)
717167814Sjkim			printf("MADT: Ignoring local NMI routed to "
718167814Sjkim			    "ACPI CPU %u\n", nmi->ProcessorId);
719121992Sjhb		return;
720121992Sjhb	}
721123326Snjl	if (nmi->Lint == 0)
722121992Sjhb		pin = LVT_LINT0;
723121992Sjhb	else
724121992Sjhb		pin = LVT_LINT1;
725121992Sjhb	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
726167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
727121992Sjhb		lapic_set_lvt_triggermode(apic_id, pin,
728167814Sjkim		    interrupt_trigger(nmi->IntiFlags, 0));
729167814Sjkim	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
730121992Sjhb		lapic_set_lvt_polarity(apic_id, pin,
731167814Sjkim		    interrupt_polarity(nmi->IntiFlags, 0));
732121992Sjhb}
733121992Sjhb
734121992Sjhb/*
735121992Sjhb * Parse interrupt entries.
736121992Sjhb */
737121992Sjhbstatic void
738167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
739121992Sjhb{
740121992Sjhb
741121992Sjhb	switch (entry->Type) {
742167814Sjkim	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
743121992Sjhb		madt_parse_interrupt_override(
744167814Sjkim			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
745121992Sjhb		break;
746167814Sjkim	case ACPI_MADT_TYPE_NMI_SOURCE:
747167814Sjkim		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
748121992Sjhb		break;
749167814Sjkim	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
750167814Sjkim		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
751121992Sjhb		break;
752121992Sjhb	}
753121992Sjhb}
754121992Sjhb
755121992Sjhb/*
756121992Sjhb * Setup per-CPU ACPI IDs.
757121992Sjhb */
758121992Sjhbstatic void
759121992Sjhbmadt_set_ids(void *dummy)
760121992Sjhb{
761129960Sjhb	struct lapic_info *la;
762121992Sjhb	struct pcpu *pc;
763129960Sjhb	u_int i;
764121992Sjhb
765121992Sjhb	if (madt == NULL)
766121992Sjhb		return;
767123133Sjhb	for (i = 0; i <= mp_maxid; i++) {
768121992Sjhb		if (CPU_ABSENT(i))
769121992Sjhb			continue;
770121992Sjhb		pc = pcpu_find(i);
771167814Sjkim		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
772129960Sjhb		la = &lapics[pc->pc_apic_id];
773130310Sjhb		if (!la->la_enabled)
774129960Sjhb			panic("APIC: CPU with APIC ID %u is not enabled",
775129960Sjhb			    pc->pc_apic_id);
776129960Sjhb		pc->pc_acpi_id = la->la_acpi_id;
777129960Sjhb		if (bootverbose)
778129960Sjhb			printf("APIC: CPU %u has ACPI ID %u\n", i,
779129960Sjhb			    la->la_acpi_id);
780121992Sjhb	}
781121992Sjhb}
782121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
783