madt.c revision 128930
1/*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/i386/acpica/madt.c 128930 2004-05-04 20:39:24Z jhb $");
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/bus.h>
36#include <sys/kernel.h>
37#include <sys/malloc.h>
38#include <sys/smp.h>
39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <machine/apicreg.h>
45#include <machine/frame.h>
46#include <machine/intr_machdep.h>
47#include <machine/apicvar.h>
48#include <machine/md_var.h>
49#include <machine/specialreg.h>
50
51#include "acpi.h"
52#include <dev/acpica/acpivar.h>
53#include <dev/pci/pcivar.h>
54
55#define	NIOAPICS		32	/* Max number of I/O APICs */
56#define	NLAPICS			32	/* Max number of local APICs */
57
58typedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
59
60/* These two arrays are indexed by APIC IDs. */
61struct ioapic_info {
62	void *io_apic;
63	UINT32 io_vector;
64} ioapics[NIOAPICS];
65
66struct lapic_info {
67	u_int la_present:1;
68	u_int la_enabled:1;
69	u_int la_apic_id:8;
70} lapics[NLAPICS + 1];
71
72static int madt_found_sci_override;
73static MULTIPLE_APIC_TABLE *madt;
74static vm_paddr_t madt_physaddr;
75static vm_offset_t madt_length;
76
77MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
78
79static enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
80static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
81static int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
82static int	madt_find_interrupt(int intr, void **apic, u_int *pin);
83static void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
84static void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
85static void	madt_parse_apics(APIC_HEADER *entry, void *arg);
86static void	madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
87static void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
88static void	madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
89static void	madt_parse_nmi(MADT_NMI_SOURCE *nmi);
90static int	madt_probe(void);
91static int	madt_probe_cpus(void);
92static void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
93static int	madt_probe_table(vm_paddr_t address);
94static void	madt_register(void *dummy);
95static int	madt_setup_local(void);
96static int	madt_setup_io(void);
97static void	madt_unmap(void *data, vm_offset_t length);
98static void	madt_unmap_table(void *table);
99static void	madt_walk_table(madt_entry_handler *handler, void *arg);
100
101static struct apic_enumerator madt_enumerator = {
102	"MADT",
103	madt_probe,
104	madt_probe_cpus,
105	madt_setup_local,
106	madt_setup_io
107};
108
109/*
110 * Code to abuse the crashdump map to map in the tables for the early
111 * probe.  We cheat and make the following assumptions about how we
112 * use this KVA: page 0 is used to map in the first page of each table
113 * found via the RSDT or XSDT and pages 1 to n are used to map in the
114 * RSDT or XSDT.  The offset is in pages; the length is in bytes.
115 */
116static void *
117madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
118{
119	vm_offset_t va, off;
120	void *data;
121
122	off = pa & PAGE_MASK;
123	length = roundup(length + off, PAGE_SIZE);
124	pa = pa & PG_FRAME;
125	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
126	    (offset * PAGE_SIZE);
127	data = (void *)(va + off);
128	length -= PAGE_SIZE;
129	while (length > 0) {
130		va += PAGE_SIZE;
131		pa += PAGE_SIZE;
132		length -= PAGE_SIZE;
133		pmap_kenter(va, pa);
134		invlpg(va);
135	}
136	return (data);
137}
138
139static void
140madt_unmap(void *data, vm_offset_t length)
141{
142	vm_offset_t va, off;
143
144	va = (vm_offset_t)data;
145	off = va & PAGE_MASK;
146	length = roundup(length + off, PAGE_SIZE);
147	va &= ~PAGE_MASK;
148	while (length > 0) {
149		pmap_kremove(va);
150		invlpg(va);
151		va += PAGE_SIZE;
152		length -= PAGE_SIZE;
153	}
154}
155
156static void *
157madt_map_table(vm_paddr_t pa, int offset, const char *sig)
158{
159	ACPI_TABLE_HEADER *header;
160	vm_offset_t length;
161
162	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
163	if (strncmp(header->Signature, sig, 4) != 0) {
164		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
165		return (NULL);
166	}
167	length = header->Length;
168	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
169	return (madt_map(pa, offset, length));
170}
171
172static void
173madt_unmap_table(void *table)
174{
175	ACPI_TABLE_HEADER *header;
176
177	header = (ACPI_TABLE_HEADER *)table;
178	madt_unmap(table, header->Length);
179}
180
181/*
182 * Look for an ACPI Multiple APIC Description Table ("APIC")
183 */
184static int
185madt_probe(void)
186{
187	ACPI_POINTER rsdp_ptr;
188	RSDP_DESCRIPTOR *rsdp;
189	RSDT_DESCRIPTOR *rsdt;
190	XSDT_DESCRIPTOR *xsdt;
191	int i, count;
192
193	if (resource_disabled("acpi", 0))
194		return (ENXIO);
195
196	/*
197	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
198	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
199	 * pmap_mapdev() to map the RSDP.
200	 */
201	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
202		return (ENXIO);
203#ifdef __i386__
204	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
205#endif
206	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
207	if (rsdp == NULL) {
208		if (bootverbose)
209			printf("MADT: Failed to map RSDP\n");
210		return (ENXIO);
211	}
212
213	/*
214	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
215	 * We map the XSDT and RSDT at page 1 in the crashdump area.
216	 * Page 0 is used to map in the headers of candidate ACPI tables.
217	 */
218	if (rsdp->Revision >= 2) {
219		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
220		if (xsdt == NULL) {
221			if (bootverbose)
222				printf("MADT: Failed to map XSDT\n");
223			return (ENXIO);
224		}
225		count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
226		    sizeof(UINT64);
227		for (i = 0; i < count; i++)
228			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
229				break;
230		madt_unmap_table(xsdt);
231	} else {
232		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
233		if (rsdt == NULL) {
234			if (bootverbose)
235				printf("MADT: Failed to map RSDT\n");
236			return (ENXIO);
237		}
238		count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
239		    sizeof(UINT32);
240		for (i = 0; i < count; i++)
241			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
242				break;
243		madt_unmap_table(rsdt);
244	}
245	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
246	if (madt_physaddr == 0) {
247		if (bootverbose)
248			printf("MADT: No MADT table found\n");
249		return (ENXIO);
250	}
251	if (bootverbose)
252		printf("MADT: Found table at 0x%jx\n",
253		    (uintmax_t)madt_physaddr);
254
255	return (0);
256}
257
258/*
259 * See if a given ACPI table is the MADT.
260 */
261static int
262madt_probe_table(vm_paddr_t address)
263{
264	ACPI_TABLE_HEADER *table;
265
266	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
267	if (table == NULL) {
268		if (bootverbose)
269			printf("MADT: Failed to map table at 0x%jx\n",
270			    (uintmax_t)address);
271		return (0);
272	}
273	if (bootverbose)
274		printf("Table '%.4s' at 0x%jx\n", table->Signature,
275		    (uintmax_t)address);
276
277	/* XXX: Verify checksum? */
278	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
279		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
280		return (0);
281	}
282	madt_physaddr = address;
283	madt_length = table->Length;
284	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
285	return (1);
286}
287
288/*
289 * Run through the MP table enumerating CPUs.
290 */
291static int
292madt_probe_cpus(void)
293{
294
295	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
296	KASSERT(madt != NULL, ("Unable to re-map MADT"));
297	madt_walk_table(madt_probe_cpus_handler, NULL);
298	madt_unmap_table(madt);
299	madt = NULL;
300	return (0);
301}
302
303/*
304 * Initialize the local APIC on the BSP.
305 */
306static int
307madt_setup_local(void)
308{
309
310	madt = pmap_mapdev(madt_physaddr, madt_length);
311	lapic_init((uintptr_t)madt->LocalApicAddress);
312	printf("ACPI APIC Table: <%.*s %.*s>\n",
313	    (int)sizeof(madt->OemId), madt->OemId,
314	    (int)sizeof(madt->OemTableId), madt->OemTableId);
315
316	/*
317	 * We ignore 64-bit local APIC override entries.  Should we
318	 * perhaps emit a warning here if we find one?
319	 */
320	return (0);
321}
322
323/*
324 * Enumerate I/O APICs and setup interrupt sources.
325 */
326static int
327madt_setup_io(void)
328{
329	void *ioapic;
330	u_int pin;
331	int i;
332
333	/* Try to initialize ACPI so that we can access the FADT. */
334	i = acpi_Startup();
335	if (ACPI_FAILURE(i)) {
336		printf("MADT: ACPI Startup failed with %s\n",
337		    AcpiFormatException(i));
338		printf("Try disabling either ACPI or apic support.\n");
339		panic("Using MADT but ACPI doesn't work");
340	}
341
342	/* First, we run through adding I/O APIC's. */
343	madt_walk_table(madt_parse_apics, NULL);
344
345	/* Second, we run through the table tweaking interrupt sources. */
346	madt_walk_table(madt_parse_ints, NULL);
347
348	/*
349	 * If there was not an explicit override entry for the SCI,
350	 * force it to use level trigger and active-low polarity.
351	 */
352	if (!madt_found_sci_override) {
353		if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
354		    != 0)
355			printf("MADT: Could not find APIC for SCI IRQ %d\n",
356			    AcpiGbl_FADT->SciInt);
357		else {
358			printf(
359	"MADT: Forcing active-low polarity and level trigger for SCI\n");
360			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
361			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
362		}
363	}
364
365	/* Third, we register all the I/O APIC's. */
366	for (i = 0; i < NIOAPICS; i++)
367		if (ioapics[i].io_apic != NULL)
368			ioapic_register(ioapics[i].io_apic);
369
370	/* Finally, we throw the switch to enable the I/O APIC's. */
371	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
372
373	return (0);
374}
375
376static void
377madt_register(void *dummy __unused)
378{
379
380	apic_register_enumerator(&madt_enumerator);
381}
382SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
383
384/*
385 * Call the handler routine for each entry in the MADT table.
386 */
387static void
388madt_walk_table(madt_entry_handler *handler, void *arg)
389{
390	APIC_HEADER *entry;
391	u_char *p, *end;
392
393	end = (u_char *)(madt) + madt->Length;
394	for (p = (u_char *)(madt + 1); p < end; ) {
395		entry = (APIC_HEADER *)p;
396		handler(entry, arg);
397		p += entry->Length;
398	}
399}
400
401static void
402madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
403{
404	MADT_PROCESSOR_APIC *proc;
405	struct lapic_info *la;
406
407	switch (entry->Type) {
408	case APIC_PROCESSOR:
409		/*
410		 * The MADT does not include a BSP flag, so we have to
411		 * let the MP code figure out which CPU is the BSP on
412		 * its own.
413		 */
414		proc = (MADT_PROCESSOR_APIC *)entry;
415		if (bootverbose)
416			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
417			    proc->LocalApicId, proc->ProcessorId,
418			    proc->ProcessorEnabled ? "enabled" : "disabled");
419		if (proc->ProcessorId > NLAPICS)
420			panic("%s: CPU ID %d too high", __func__,
421			    proc->ProcessorId);
422		la = &lapics[proc->ProcessorId];
423		KASSERT(la->la_present == 0,
424		    ("Duplicate local ACPI ID %d", proc->ProcessorId));
425		la->la_present = 1;
426		la->la_apic_id = proc->LocalApicId;
427		if (proc->ProcessorEnabled) {
428			la->la_enabled = 1;
429			lapic_create(proc->LocalApicId, 0);
430		}
431		break;
432	}
433}
434
435
436/*
437 * Add an I/O APIC from an entry in the table.
438 */
439static void
440madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
441{
442	MADT_IO_APIC *apic;
443
444	switch (entry->Type) {
445	case APIC_IO:
446		apic = (MADT_IO_APIC *)entry;
447		if (bootverbose)
448			printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
449			    apic->IoApicId, apic->Interrupt,
450			    (void *)(uintptr_t)apic->Address);
451		if (apic->IoApicId >= NIOAPICS)
452			panic("%s: I/O APIC ID %d too high", __func__,
453			    apic->IoApicId);
454		if (ioapics[apic->IoApicId].io_apic != NULL)
455			panic("%s: Double APIC ID %d", __func__,
456			    apic->IoApicId);
457		ioapics[apic->IoApicId].io_apic = ioapic_create(
458			(uintptr_t)apic->Address, apic->IoApicId,
459			    apic->Interrupt);
460		ioapics[apic->IoApicId].io_vector = apic->Interrupt;
461		break;
462	default:
463		break;
464	}
465}
466
467/*
468 * Determine properties of an interrupt source.  Note that for ACPI,
469 * these are only used for ISA interrupts, so we assume ISA bus values
470 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
471 * SCI for which we use Active Lo, Level Triggered..
472 */
473static enum intr_polarity
474interrupt_polarity(UINT16 Polarity, UINT8 Source)
475{
476
477	switch (Polarity) {
478	case POLARITY_CONFORMS:
479		if (Source == AcpiGbl_FADT->SciInt)
480			return (INTR_POLARITY_LOW);
481		else
482			return (INTR_POLARITY_HIGH);
483	case POLARITY_ACTIVE_HIGH:
484		return (INTR_POLARITY_HIGH);
485	case POLARITY_ACTIVE_LOW:
486		return (INTR_POLARITY_LOW);
487	default:
488		panic("Bogus Interrupt Polarity");
489	}
490}
491
492static enum intr_trigger
493interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
494{
495
496	switch (TriggerMode) {
497	case TRIGGER_CONFORMS:
498		if (Source == AcpiGbl_FADT->SciInt)
499			return (INTR_TRIGGER_LEVEL);
500		else
501			return (INTR_TRIGGER_EDGE);
502	case TRIGGER_EDGE:
503		return (INTR_TRIGGER_EDGE);
504	case TRIGGER_LEVEL:
505		return (INTR_TRIGGER_LEVEL);
506	default:
507		panic("Bogus Interrupt Trigger Mode");
508	}
509}
510
511/*
512 * Find the local APIC ID associated with a given ACPI Processor ID.
513 */
514static int
515madt_find_cpu(u_int acpi_id, u_int *apic_id)
516{
517
518	if (!lapics[acpi_id].la_present)
519		return (ENOENT);
520	*apic_id = lapics[acpi_id].la_apic_id;
521	if (lapics[acpi_id].la_enabled)
522		return (0);
523	else
524		return (ENXIO);
525}
526
527/*
528 * Find the IO APIC and pin on that APIC associated with a given global
529 * interrupt.
530 */
531static int
532madt_find_interrupt(int intr, void **apic, u_int *pin)
533{
534	int i, best;
535
536	best = -1;
537	for (i = 0; i < NIOAPICS; i++) {
538		if (ioapics[i].io_apic == NULL ||
539		    ioapics[i].io_vector > intr)
540			continue;
541		if (best == -1 ||
542		    ioapics[best].io_vector < ioapics[i].io_vector)
543			best = i;
544	}
545	if (best == -1)
546		return (ENOENT);
547	*apic = ioapics[best].io_apic;
548	*pin = intr - ioapics[best].io_vector;
549	if (*pin > 32)
550		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
551		    intr);
552	return (0);
553}
554
555/*
556 * Parse an interrupt source override for an ISA interrupt.
557 */
558static void
559madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
560{
561	void *new_ioapic, *old_ioapic;
562	u_int new_pin, old_pin;
563	enum intr_trigger trig;
564	enum intr_polarity pol;
565	char buf[64];
566
567	if (bootverbose)
568		printf("MADT: intr override: source %u, irq %u\n",
569		    intr->Source, intr->Interrupt);
570	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
571	if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
572	    &new_pin) != 0) {
573		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
574		    intr->Interrupt, intr->Source);
575		return;
576	}
577
578	/*
579	 * Lookup the appropriate trigger and polarity modes for this
580	 * entry.
581	 */
582	trig = interrupt_trigger(intr->TriggerMode, intr->Source);
583	pol = interrupt_polarity(intr->Polarity, intr->Source);
584
585	/*
586	 * If the SCI is identity mapped but has edge trigger and
587	 * active-hi polarity or the force_sci_lo tunable is set,
588	 * force it to use level/lo.
589	 */
590	if (intr->Source == AcpiGbl_FADT->SciInt) {
591		madt_found_sci_override = 1;
592		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
593			if (tolower(buf[0]) == 'e')
594				trig = INTR_TRIGGER_EDGE;
595			else if (tolower(buf[0]) == 'l')
596				trig = INTR_TRIGGER_LEVEL;
597			else
598				panic(
599				"Invalid trigger %s: must be 'edge' or 'level'",
600				    buf);
601			printf("MADT: Forcing SCI to %s trigger\n",
602			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
603		}
604		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
605			if (tolower(buf[0]) == 'h')
606				pol = INTR_POLARITY_HIGH;
607			else if (tolower(buf[0]) == 'l')
608				pol = INTR_POLARITY_LOW;
609			else
610				panic(
611				"Invalid polarity %s: must be 'high' or 'low'",
612				    buf);
613			printf("MADT: Forcing SCI to active %s polarity\n",
614			    pol == INTR_POLARITY_HIGH ? "high" : "low");
615		}
616	}
617
618	/* Remap the IRQ if it is mapped to a different interrupt vector. */
619	if (intr->Source != intr->Interrupt) {
620		/*
621		 * If the SCI is remapped to a non-ISA global interrupt,
622		 * then override the vector we use to setup and allocate
623		 * the interrupt.
624		 */
625		if (intr->Interrupt > 15 &&
626		    intr->Source == AcpiGbl_FADT->SciInt)
627			acpi_OverrideInterruptLevel(intr->Interrupt);
628		else
629			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
630		if (madt_find_interrupt(intr->Source, &old_ioapic,
631		    &old_pin) != 0)
632			printf("MADT: Could not find APIC for source IRQ %d\n",
633			    intr->Source);
634		else if (ioapic_get_vector(old_ioapic, old_pin) ==
635		    intr->Source)
636			ioapic_disable_pin(old_ioapic, old_pin);
637	}
638
639	/* Program the polarity and trigger mode. */
640	ioapic_set_triggermode(new_ioapic, new_pin, trig);
641	ioapic_set_polarity(new_ioapic, new_pin, pol);
642}
643
644/*
645 * Parse an entry for an NMI routed to an IO APIC.
646 */
647static void
648madt_parse_nmi(MADT_NMI_SOURCE *nmi)
649{
650	void *ioapic;
651	u_int pin;
652
653	if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
654		printf("MADT: Could not find APIC for vector %d\n",
655		    nmi->Interrupt);
656		return;
657	}
658
659	ioapic_set_nmi(ioapic, pin);
660	if (nmi->TriggerMode != TRIGGER_CONFORMS)
661		ioapic_set_triggermode(ioapic, pin,
662		    interrupt_trigger(nmi->TriggerMode, 0));
663	if (nmi->Polarity != TRIGGER_CONFORMS)
664		ioapic_set_polarity(ioapic, pin,
665		    interrupt_polarity(nmi->Polarity, 0));
666}
667
668/*
669 * Parse an entry for an NMI routed to a local APIC LVT pin.
670 */
671static void
672madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
673{
674	u_int apic_id, pin;
675
676	if (nmi->ProcessorId == 0xff)
677		apic_id = APIC_ID_ALL;
678	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
679		if (bootverbose)
680			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
681			    nmi->ProcessorId);
682		return;
683	}
684	if (nmi->Lint == 0)
685		pin = LVT_LINT0;
686	else
687		pin = LVT_LINT1;
688	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
689	if (nmi->TriggerMode != TRIGGER_CONFORMS)
690		lapic_set_lvt_triggermode(apic_id, pin,
691		    interrupt_trigger(nmi->TriggerMode, 0));
692	if (nmi->Polarity != POLARITY_CONFORMS)
693		lapic_set_lvt_polarity(apic_id, pin,
694		    interrupt_polarity(nmi->Polarity, 0));
695}
696
697/*
698 * Parse interrupt entries.
699 */
700static void
701madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
702{
703
704	switch (entry->Type) {
705	case APIC_XRUPT_OVERRIDE:
706		madt_parse_interrupt_override(
707			(MADT_INTERRUPT_OVERRIDE *)entry);
708		break;
709	case APIC_NMI:
710		madt_parse_nmi((MADT_NMI_SOURCE *)entry);
711		break;
712	case APIC_LOCAL_NMI:
713		madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
714		break;
715	}
716}
717
718/*
719 * Setup per-CPU ACPI IDs.
720 */
721static void
722madt_set_ids(void *dummy)
723{
724	struct pcpu *pc;
725	u_int i, j;
726
727	if (madt == NULL)
728		return;
729	for (i = 0; i <= mp_maxid; i++) {
730		if (CPU_ABSENT(i))
731			continue;
732		pc = pcpu_find(i);
733		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
734		for (j = 0; j < NLAPICS + 1; j++) {
735			if (!lapics[j].la_present || !lapics[j].la_enabled)
736				continue;
737			if (lapics[j].la_apic_id == pc->pc_apic_id) {
738				pc->pc_acpi_id = j;
739				if (bootverbose)
740					printf("APIC: CPU %u has ACPI ID %u\n",
741					    i, j);
742				break;
743			}
744		}
745		if (j == NLAPICS + 1)
746			panic("Unable to find ACPI ID for CPU %d", i);
747	}
748}
749SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
750