madt.c revision 316303
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/sys/x86/acpica/madt.c 316303 2017-03-30 20:18:34Z jkim $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/limits.h>
35#include <sys/malloc.h>
36#include <sys/smp.h>
37#include <vm/vm.h>
38#include <vm/pmap.h>
39
40#include <x86/apicreg.h>
41#include <machine/intr_machdep.h>
42#include <x86/apicvar.h>
43#include <machine/md_var.h>
44#include <x86/vmware.h>
45
46#include <contrib/dev/acpica/include/acpi.h>
47#include <contrib/dev/acpica/include/aclocal.h>
48#include <contrib/dev/acpica/include/actables.h>
49
50#include <dev/acpica/acpivar.h>
51#include <dev/pci/pcivar.h>
52
53/* These two arrays are indexed by APIC IDs. */
54static struct {
55	void *io_apic;
56	UINT32 io_vector;
57} *ioapics;
58
59static struct lapic_info {
60	u_int la_enabled;
61	u_int la_acpi_id;
62} lapics[MAX_APIC_ID + 1];
63
64int madt_found_sci_override;
65static ACPI_TABLE_MADT *madt;
66static vm_paddr_t madt_physaddr;
67static vm_offset_t madt_length;
68
69static MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
70
71static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
72static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
73static int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
74static int	madt_find_interrupt(int intr, void **apic, u_int *pin);
75static void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
76static void	madt_parse_interrupt_override(
77		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
78static void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
79		    void *arg __unused);
80static void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
81static void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
82static int	madt_probe(void);
83static int	madt_probe_cpus(void);
84static void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
85		    void *arg __unused);
86static void	madt_register(void *dummy);
87static int	madt_setup_local(void);
88static int	madt_setup_io(void);
89static void	madt_walk_table(acpi_subtable_handler *handler, void *arg);
90
91static struct apic_enumerator madt_enumerator = {
92	"MADT",
93	madt_probe,
94	madt_probe_cpus,
95	madt_setup_local,
96	madt_setup_io
97};
98
99/*
100 * Look for an ACPI Multiple APIC Description Table ("APIC")
101 */
102static int
103madt_probe(void)
104{
105
106	madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
107	if (madt_physaddr == 0)
108		return (ENXIO);
109	return (-50);
110}
111
112/*
113 * Run through the MP table enumerating CPUs.
114 */
115static int
116madt_probe_cpus(void)
117{
118
119	madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
120	madt_length = madt->Header.Length;
121	KASSERT(madt != NULL, ("Unable to re-map MADT"));
122	madt_walk_table(madt_probe_cpus_handler, NULL);
123	acpi_unmap_table(madt);
124	madt = NULL;
125	return (0);
126}
127
128/*
129 * Initialize the local APIC on the BSP.
130 */
131static int
132madt_setup_local(void)
133{
134	ACPI_TABLE_DMAR *dmartbl;
135	vm_paddr_t dmartbl_physaddr;
136	const char *reason;
137	char *hw_vendor;
138	u_int p[4];
139	int user_x2apic;
140	bool bios_x2apic;
141
142	madt = pmap_mapbios(madt_physaddr, madt_length);
143	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
144		reason = NULL;
145
146		/*
147		 * Automatically detect several configurations where
148		 * x2APIC mode is known to cause troubles.  User can
149		 * override the setting with hw.x2apic_enable tunable.
150		 */
151		dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
152		if (dmartbl_physaddr != 0) {
153			dmartbl = acpi_map_table(dmartbl_physaddr,
154			    ACPI_SIG_DMAR);
155			if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
156				reason = "by DMAR table";
157			acpi_unmap_table(dmartbl);
158		}
159		if (vm_guest == VM_GUEST_VMWARE) {
160			vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p);
161			if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 ||
162			    (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0)
163				reason =
164				    "inside VMWare without intr redirection";
165		} else if (vm_guest == VM_GUEST_XEN) {
166			reason = "due to running under XEN";
167		} else if (vm_guest == VM_GUEST_NO &&
168		    CPUID_TO_FAMILY(cpu_id) == 0x6 &&
169		    CPUID_TO_MODEL(cpu_id) == 0x2a) {
170			hw_vendor = kern_getenv("smbios.planar.maker");
171			/*
172			 * It seems that some Lenovo and ASUS
173			 * SandyBridge-based notebook BIOSes have a
174			 * bug which prevents booting AP in x2APIC
175			 * mode.  Since the only way to detect mobile
176			 * CPU is to check northbridge pci id, which
177			 * cannot be done that early, disable x2APIC
178			 * for all Lenovo and ASUS SandyBridge
179			 * machines.
180			 */
181			if (hw_vendor != NULL) {
182				if (!strcmp(hw_vendor, "LENOVO") ||
183				    !strcmp(hw_vendor,
184				    "ASUSTeK Computer Inc.")) {
185					reason =
186				    "for a suspected SandyBridge BIOS bug";
187				}
188				freeenv(hw_vendor);
189			}
190		}
191		bios_x2apic = lapic_is_x2apic();
192		if (reason != NULL && bios_x2apic) {
193			if (bootverbose)
194				printf("x2APIC should be disabled %s but "
195				    "already enabled by BIOS; enabling.\n",
196				     reason);
197			reason = NULL;
198		}
199		if (reason == NULL)
200			x2apic_mode = 1;
201		else if (bootverbose)
202			printf("x2APIC available but disabled %s\n", reason);
203		user_x2apic = x2apic_mode;
204		TUNABLE_INT_FETCH("hw.x2apic_enable", &user_x2apic);
205		if (user_x2apic != x2apic_mode) {
206			if (bios_x2apic && !user_x2apic)
207				printf("x2APIC disabled by tunable and "
208				    "enabled by BIOS; ignoring tunable.");
209			else
210				x2apic_mode = user_x2apic;
211		}
212	}
213
214	lapic_init(madt->Address);
215	printf("ACPI APIC Table: <%.*s %.*s>\n",
216	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
217	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
218
219	/*
220	 * We ignore 64-bit local APIC override entries.  Should we
221	 * perhaps emit a warning here if we find one?
222	 */
223	return (0);
224}
225
226/*
227 * Enumerate I/O APICs and setup interrupt sources.
228 */
229static int
230madt_setup_io(void)
231{
232	void *ioapic;
233	u_int pin;
234	int i;
235
236	/* Try to initialize ACPI so that we can access the FADT. */
237	i = acpi_Startup();
238	if (ACPI_FAILURE(i)) {
239		printf("MADT: ACPI Startup failed with %s\n",
240		    AcpiFormatException(i));
241		printf("Try disabling either ACPI or apic support.\n");
242		panic("Using MADT but ACPI doesn't work");
243	}
244
245	ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
246	    M_WAITOK | M_ZERO);
247
248	/* First, we run through adding I/O APIC's. */
249	madt_walk_table(madt_parse_apics, NULL);
250
251	/* Second, we run through the table tweaking interrupt sources. */
252	madt_walk_table(madt_parse_ints, NULL);
253
254	/*
255	 * If there was not an explicit override entry for the SCI,
256	 * force it to use level trigger and active-low polarity.
257	 */
258	if (!madt_found_sci_override) {
259		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
260		    &pin) != 0)
261			printf("MADT: Could not find APIC for SCI IRQ %u\n",
262			    AcpiGbl_FADT.SciInterrupt);
263		else {
264			printf(
265	"MADT: Forcing active-low polarity and level trigger for SCI\n");
266			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
267			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
268		}
269	}
270
271	/* Third, we register all the I/O APIC's. */
272	for (i = 0; i <= MAX_APIC_ID; i++)
273		if (ioapics[i].io_apic != NULL)
274			ioapic_register(ioapics[i].io_apic);
275
276	/* Finally, we throw the switch to enable the I/O APIC's. */
277	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
278
279	free(ioapics, M_MADT);
280	ioapics = NULL;
281
282	return (0);
283}
284
285static void
286madt_register(void *dummy __unused)
287{
288
289	apic_register_enumerator(&madt_enumerator);
290}
291SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
292
293/*
294 * Call the handler routine for each entry in the MADT table.
295 */
296static void
297madt_walk_table(acpi_subtable_handler *handler, void *arg)
298{
299
300	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
301	    handler, arg);
302}
303
304static void
305madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags)
306{
307	struct lapic_info *la;
308
309	/*
310	 * The MADT does not include a BSP flag, so we have to let the
311	 * MP code figure out which CPU is the BSP on its own.
312	 */
313	if (bootverbose)
314		printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
315		    apic_id, acpi_id, flags & ACPI_MADT_ENABLED ?
316		    "enabled" : "disabled");
317	if (!(flags & ACPI_MADT_ENABLED))
318		return;
319	if (apic_id > MAX_APIC_ID) {
320		printf("MADT: Ignoring local APIC ID %u (too high)\n",
321		    apic_id);
322		return;
323	}
324
325	la = &lapics[apic_id];
326	KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id));
327	la->la_enabled = 1;
328	la->la_acpi_id = acpi_id;
329	lapic_create(apic_id, 0);
330}
331
332static void
333madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
334{
335	ACPI_MADT_LOCAL_APIC *proc;
336	ACPI_MADT_LOCAL_X2APIC *x2apic;
337
338	switch (entry->Type) {
339	case ACPI_MADT_TYPE_LOCAL_APIC:
340		proc = (ACPI_MADT_LOCAL_APIC *)entry;
341		madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags);
342		break;
343	case ACPI_MADT_TYPE_LOCAL_X2APIC:
344		x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry;
345		madt_add_cpu(x2apic->Uid, x2apic->LocalApicId,
346		    x2apic->LapicFlags);
347		break;
348	}
349}
350
351
352/*
353 * Add an I/O APIC from an entry in the table.
354 */
355static void
356madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
357{
358	ACPI_MADT_IO_APIC *apic;
359
360	switch (entry->Type) {
361	case ACPI_MADT_TYPE_IO_APIC:
362		apic = (ACPI_MADT_IO_APIC *)entry;
363		if (bootverbose)
364			printf(
365			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
366			    apic->Id, apic->GlobalIrqBase,
367			    (void *)(uintptr_t)apic->Address);
368		if (apic->Id > MAX_APIC_ID)
369			panic("%s: I/O APIC ID %u too high", __func__,
370			    apic->Id);
371		if (ioapics[apic->Id].io_apic != NULL)
372			panic("%s: Double APIC ID %u", __func__, apic->Id);
373		if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
374			printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
375			break;
376		}
377		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
378		    apic->Id, apic->GlobalIrqBase);
379		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
380		break;
381	default:
382		break;
383	}
384}
385
386/*
387 * Determine properties of an interrupt source.  Note that for ACPI these
388 * functions are only used for ISA interrupts, so we assume ISA bus values
389 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
390 * SCI for which we use Active Lo, Level Triggered.
391 */
392static enum intr_polarity
393interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
394{
395
396	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
397	default:
398		printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
399		/* FALLTHROUGH*/
400	case ACPI_MADT_POLARITY_CONFORMS:
401		if (Source == AcpiGbl_FADT.SciInterrupt)
402			return (INTR_POLARITY_LOW);
403		else
404			return (INTR_POLARITY_HIGH);
405	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
406		return (INTR_POLARITY_HIGH);
407	case ACPI_MADT_POLARITY_ACTIVE_LOW:
408		return (INTR_POLARITY_LOW);
409	}
410}
411
412static enum intr_trigger
413interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
414{
415
416	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
417	default:
418		printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
419		/*FALLTHROUGH*/
420	case ACPI_MADT_TRIGGER_CONFORMS:
421		if (Source == AcpiGbl_FADT.SciInterrupt)
422			return (INTR_TRIGGER_LEVEL);
423		else
424			return (INTR_TRIGGER_EDGE);
425	case ACPI_MADT_TRIGGER_EDGE:
426		return (INTR_TRIGGER_EDGE);
427	case ACPI_MADT_TRIGGER_LEVEL:
428		return (INTR_TRIGGER_LEVEL);
429	}
430}
431
432/*
433 * Find the local APIC ID associated with a given ACPI Processor ID.
434 */
435static int
436madt_find_cpu(u_int acpi_id, u_int *apic_id)
437{
438	int i;
439
440	for (i = 0; i <= MAX_APIC_ID; i++) {
441		if (!lapics[i].la_enabled)
442			continue;
443		if (lapics[i].la_acpi_id != acpi_id)
444			continue;
445		*apic_id = i;
446		return (0);
447	}
448	return (ENOENT);
449}
450
451/*
452 * Find the IO APIC and pin on that APIC associated with a given global
453 * interrupt.
454 */
455static int
456madt_find_interrupt(int intr, void **apic, u_int *pin)
457{
458	int i, best;
459
460	best = -1;
461	for (i = 0; i <= MAX_APIC_ID; i++) {
462		if (ioapics[i].io_apic == NULL ||
463		    ioapics[i].io_vector > intr)
464			continue;
465		if (best == -1 ||
466		    ioapics[best].io_vector < ioapics[i].io_vector)
467			best = i;
468	}
469	if (best == -1)
470		return (ENOENT);
471	*apic = ioapics[best].io_apic;
472	*pin = intr - ioapics[best].io_vector;
473	if (*pin > 32)
474		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
475		    intr);
476	return (0);
477}
478
479void
480madt_parse_interrupt_values(void *entry,
481    enum intr_trigger *trig, enum intr_polarity *pol)
482{
483	ACPI_MADT_INTERRUPT_OVERRIDE *intr;
484	char buf[64];
485
486	intr = entry;
487
488	if (bootverbose)
489		printf("MADT: Interrupt override: source %u, irq %u\n",
490		    intr->SourceIrq, intr->GlobalIrq);
491	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
492
493	/*
494	 * Lookup the appropriate trigger and polarity modes for this
495	 * entry.
496	 */
497	*trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
498	*pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
499
500	/*
501	 * If the SCI is identity mapped but has edge trigger and
502	 * active-hi polarity or the force_sci_lo tunable is set,
503	 * force it to use level/lo.
504	 */
505	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
506		madt_found_sci_override = 1;
507		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
508			if (tolower(buf[0]) == 'e')
509				*trig = INTR_TRIGGER_EDGE;
510			else if (tolower(buf[0]) == 'l')
511				*trig = INTR_TRIGGER_LEVEL;
512			else
513				panic(
514				"Invalid trigger %s: must be 'edge' or 'level'",
515				    buf);
516			printf("MADT: Forcing SCI to %s trigger\n",
517			    *trig == INTR_TRIGGER_EDGE ? "edge" : "level");
518		}
519		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
520			if (tolower(buf[0]) == 'h')
521				*pol = INTR_POLARITY_HIGH;
522			else if (tolower(buf[0]) == 'l')
523				*pol = INTR_POLARITY_LOW;
524			else
525				panic(
526				"Invalid polarity %s: must be 'high' or 'low'",
527				    buf);
528			printf("MADT: Forcing SCI to active %s polarity\n",
529			    *pol == INTR_POLARITY_HIGH ? "high" : "low");
530		}
531	}
532}
533
534/*
535 * Parse an interrupt source override for an ISA interrupt.
536 */
537static void
538madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
539{
540	void *new_ioapic, *old_ioapic;
541	u_int new_pin, old_pin;
542	enum intr_trigger trig;
543	enum intr_polarity pol;
544
545	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
546	    intr->GlobalIrq == 2) {
547		if (bootverbose)
548			printf("MADT: Skipping timer override\n");
549		return;
550	}
551
552	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
553		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
554		    intr->GlobalIrq, intr->SourceIrq);
555		return;
556	}
557
558	madt_parse_interrupt_values(intr, &trig, &pol);
559
560	/* Remap the IRQ if it is mapped to a different interrupt vector. */
561	if (intr->SourceIrq != intr->GlobalIrq) {
562		/*
563		 * If the SCI is remapped to a non-ISA global interrupt,
564		 * then override the vector we use to setup and allocate
565		 * the interrupt.
566		 */
567		if (intr->GlobalIrq > 15 &&
568		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
569			acpi_OverrideInterruptLevel(intr->GlobalIrq);
570		else
571			ioapic_remap_vector(new_ioapic, new_pin,
572			    intr->SourceIrq);
573		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
574		    &old_pin) != 0)
575			printf("MADT: Could not find APIC for source IRQ %u\n",
576			    intr->SourceIrq);
577		else if (ioapic_get_vector(old_ioapic, old_pin) ==
578		    intr->SourceIrq)
579			ioapic_disable_pin(old_ioapic, old_pin);
580	}
581
582	/* Program the polarity and trigger mode. */
583	ioapic_set_triggermode(new_ioapic, new_pin, trig);
584	ioapic_set_polarity(new_ioapic, new_pin, pol);
585}
586
587/*
588 * Parse an entry for an NMI routed to an IO APIC.
589 */
590static void
591madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
592{
593	void *ioapic;
594	u_int pin;
595
596	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
597		printf("MADT: Could not find APIC for vector %u\n",
598		    nmi->GlobalIrq);
599		return;
600	}
601
602	ioapic_set_nmi(ioapic, pin);
603	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
604		ioapic_set_triggermode(ioapic, pin,
605		    interrupt_trigger(nmi->IntiFlags, 0));
606	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
607		ioapic_set_polarity(ioapic, pin,
608		    interrupt_polarity(nmi->IntiFlags, 0));
609}
610
611/*
612 * Parse an entry for an NMI routed to a local APIC LVT pin.
613 */
614static void
615madt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags)
616{
617	u_int apic_id, pin;
618
619	if (acpi_id == 0xffffffff)
620		apic_id = APIC_ID_ALL;
621	else if (madt_find_cpu(acpi_id, &apic_id) != 0) {
622		if (bootverbose)
623			printf("MADT: Ignoring local NMI routed to "
624			    "ACPI CPU %u\n", acpi_id);
625		return;
626	}
627	if (Lint == 0)
628		pin = APIC_LVT_LINT0;
629	else
630		pin = APIC_LVT_LINT1;
631	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
632	if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
633		lapic_set_lvt_triggermode(apic_id, pin,
634		    interrupt_trigger(IntiFlags, 0));
635	if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
636		lapic_set_lvt_polarity(apic_id, pin,
637		    interrupt_polarity(IntiFlags, 0));
638}
639
640static void
641madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
642{
643
644	madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff :
645	    nmi->ProcessorId, nmi->Lint, nmi->IntiFlags);
646}
647
648static void
649madt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi)
650{
651
652	madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags);
653}
654
655/*
656 * Parse interrupt entries.
657 */
658static void
659madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
660{
661
662	switch (entry->Type) {
663	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
664		madt_parse_interrupt_override(
665			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
666		break;
667	case ACPI_MADT_TYPE_NMI_SOURCE:
668		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
669		break;
670	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
671		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
672		break;
673	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
674		madt_parse_local_x2apic_nmi(
675		    (ACPI_MADT_LOCAL_X2APIC_NMI *)entry);
676		break;
677	}
678}
679
680/*
681 * Setup per-CPU ACPI IDs.
682 */
683static void
684madt_set_ids(void *dummy)
685{
686	struct lapic_info *la;
687	struct pcpu *pc;
688	u_int i;
689
690	if (madt == NULL)
691		return;
692	CPU_FOREACH(i) {
693		pc = pcpu_find(i);
694		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
695		la = &lapics[pc->pc_apic_id];
696		if (!la->la_enabled)
697			panic("APIC: CPU with APIC ID %u is not enabled",
698			    pc->pc_apic_id);
699		pc->pc_acpi_id = la->la_acpi_id;
700		if (bootverbose)
701			printf("APIC: CPU %u has ACPI ID %u\n", i,
702			    la->la_acpi_id);
703	}
704}
705SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
706