madt.c revision 129960
126522Sbde/*-
21664Sphk * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
33023Srgrimes * All rights reserved.
43023Srgrimes *
53023Srgrimes * Redistribution and use in source and binary forms, with or without
61664Sphk * modification, are permitted provided that the following conditions
73023Srgrimes * are met:
83023Srgrimes * 1. Redistributions of source code must retain the above copyright
91664Sphk *    notice, this list of conditions and the following disclaimer.
101664Sphk * 2. Redistributions in binary form must reproduce the above copyright
111664Sphk *    notice, this list of conditions and the following disclaimer in the
121664Sphk *    documentation and/or other materials provided with the distribution.
131664Sphk * 3. Neither the name of the author nor the names of any co-contributors
1413261Sache *    may be used to endorse or promote products derived from this software
151664Sphk *    without specific prior written permission.
163023Srgrimes *
171664Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
189509Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191664Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201664Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2116668Snate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2216668Snate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2316668Snate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2416668Snate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258024Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261684Scsgr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278024Sjkh * SUCH DAMAGE.
288024Sjkh */
297210Sphk
301684Scsgr#include <sys/cdefs.h>
317210Sphk__FBSDID("$FreeBSD: head/sys/i386/acpica/madt.c 129960 2004-06-01 19:49:38Z jhb $");
321684Scsgr
331684Scsgr#include <sys/param.h>
341684Scsgr#include <sys/systm.h>
351684Scsgr#include <sys/bus.h>
369509Srgrimes#include <sys/kernel.h>
371697Sache#include <sys/malloc.h>
381697Sache#include <sys/smp.h>
3920847Speter
4020847Speter#include <vm/vm.h>
4120847Speter#include <vm/vm_param.h>
4220847Speter#include <vm/pmap.h>
4320847Speter
4420847Speter#include <machine/apicreg.h>
4520847Speter#include <machine/frame.h>
4620847Speter#include <machine/intr_machdep.h>
4714403Sasami#include <machine/apicvar.h>
4814403Sasami#include <machine/md_var.h>
4914403Sasami#include <machine/specialreg.h>
5014403Sasami
5114403Sasami#include "acpi.h"
5214403Sasami#include <contrib/dev/acpica/actables.h>
531697Sache#include <dev/acpica/acpivar.h>
541697Sache#include <dev/pci/pcivar.h>
551697Sache
5625424Sandreas#define	NIOAPICS		32	/* Max number of I/O APICs */
571733Sadam#define	NLAPICS			32	/* Max number of local APICs */
581733Sadam
5914102Sadamtypedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
6014102Sadam
6114102Sadam/* These two arrays are indexed by APIC IDs. */
6214102Sadamstruct ioapic_info {
631733Sadam	void *io_apic;
641740Sadam	UINT32 io_vector;
653023Srgrimes} ioapics[NIOAPICS];
661733Sadam
6718927Spststruct lapic_info {
6826522Sbde	u_int la_present:1;
6926522Sbde	u_int la_enabled:1;
701733Sadam	u_int la_acpi_id:8;
7118927Spst} lapics[NLAPICS];
7218927Spst
7318927Spststatic int madt_found_sci_override;
7418928Spststatic MULTIPLE_APIC_TABLE *madt;
7518927Spststatic vm_paddr_t madt_physaddr;
7626522Sbdestatic vm_offset_t madt_length;
7726522Sbde
7818927SpstMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
7926522Sbde
8018927Spststatic enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
8118927Spststatic enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
824224Sphkstatic int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
8315334Sasamistatic int	madt_find_interrupt(int intr, void **apic, u_int *pin);
8415334Sasamistatic void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
853023Srgrimesstatic void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
864224Sphkstatic void	madt_parse_apics(APIC_HEADER *entry, void *arg);
873023Srgrimesstatic void	madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
883023Srgrimesstatic void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
8915212Sasamistatic void	madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
9015212Sasamistatic void	madt_parse_nmi(MADT_NMI_SOURCE *nmi);
9115212Sasamistatic int	madt_probe(void);
9215212Sasamistatic int	madt_probe_cpus(void);
9315334Sasamistatic void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
9415334Sasamistatic int	madt_probe_table(vm_paddr_t address);
9515334Sasamistatic void	madt_register(void *dummy);
9615212Sasamistatic int	madt_setup_local(void);
9715334Sasamistatic int	madt_setup_io(void);
9815212Sasamistatic void	madt_unmap(void *data, vm_offset_t length);
9915212Sasamistatic void	madt_unmap_table(void *table);
10022638Sjkhstatic void	madt_walk_table(madt_entry_handler *handler, void *arg);
10122638Sjkh
10222638Sjkhstatic struct apic_enumerator madt_enumerator = {
10322638Sjkh	"MADT",
10422638Sjkh	madt_probe,
10522638Sjkh	madt_probe_cpus,
10624951Sasami	madt_setup_local,
10724951Sasami	madt_setup_io
10824951Sasami};
10924951Sasami
11024951Sasami/*
11124951Sasami * Code to abuse the crashdump map to map in the tables for the early
11224951Sasami * probe.  We cheat and make the following assumptions about how we
11324951Sasami * use this KVA: page 0 is used to map in the first page of each table
11424951Sasami * found via the RSDT or XSDT and pages 1 to n are used to map in the
11524951Sasami * RSDT or XSDT.  The offset is in pages; the length is in bytes.
11624951Sasami */
11724951Sasamistatic void *
11824951Sasamimadt_map(vm_paddr_t pa, int offset, vm_offset_t length)
11924951Sasami{
12024951Sasami	vm_offset_t va, off;
12124951Sasami	void *data;
12224951Sasami
12324951Sasami	off = pa & PAGE_MASK;
12424951Sasami	length = roundup(length + off, PAGE_SIZE);
12524951Sasami	pa = pa & PG_FRAME;
12624951Sasami	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
12724951Sasami	    (offset * PAGE_SIZE);
12824951Sasami	data = (void *)(va + off);
12924951Sasami	length -= PAGE_SIZE;
13024951Sasami	while (length > 0) {
13124951Sasami		va += PAGE_SIZE;
13224951Sasami		pa += PAGE_SIZE;
13324951Sasami		length -= PAGE_SIZE;
13424951Sasami		pmap_kenter(va, pa);
13524951Sasami		invlpg(va);
13624951Sasami	}
13724951Sasami	return (data);
13824951Sasami}
1393241Scsgr
1407198Sjkhstatic void
1413241Scsgrmadt_unmap(void *data, vm_offset_t length)
1423241Scsgr{
14310758Sache	vm_offset_t va, off;
14410758Sache
14518716Sache	va = (vm_offset_t)data;
14610758Sache	off = va & PAGE_MASK;
14710758Sache	length = roundup(length + off, PAGE_SIZE);
14818716Sache	va &= ~PAGE_MASK;
14918716Sache	while (length > 0) {
15018716Sache		pmap_kremove(va);
15118716Sache		invlpg(va);
15218716Sache		va += PAGE_SIZE;
15311095Sache		length -= PAGE_SIZE;
15411095Sache	}
15511095Sache}
15618716Sache
15718716Sachestatic void *
15818716Sachemadt_map_table(vm_paddr_t pa, int offset, const char *sig)
15920545Sache{
16019316Sache	ACPI_TABLE_HEADER *header;
16118716Sache	vm_offset_t length;
16218716Sache	void *table;
16318716Sache
16424225Sjoerg	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
16524225Sjoerg	if (strncmp(header->Signature, sig, 4) != 0) {
16624225Sjoerg		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
16724225Sjoerg		return (NULL);
16824225Sjoerg	}
16924225Sjoerg	length = header->Length;
17024225Sjoerg	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
17124225Sjoerg	table = madt_map(pa, offset, length);
172	if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
173		if (bootverbose)
174			printf("MADT: Failed checksum for table %s\n", sig);
175		madt_unmap(table, length);
176		return (NULL);
177	}
178	return (table);
179}
180
181static void
182madt_unmap_table(void *table)
183{
184	ACPI_TABLE_HEADER *header;
185
186	header = (ACPI_TABLE_HEADER *)table;
187	madt_unmap(table, header->Length);
188}
189
190/*
191 * Look for an ACPI Multiple APIC Description Table ("APIC")
192 */
193static int
194madt_probe(void)
195{
196	ACPI_POINTER rsdp_ptr;
197	RSDP_DESCRIPTOR *rsdp;
198	RSDT_DESCRIPTOR *rsdt;
199	XSDT_DESCRIPTOR *xsdt;
200	int i, count;
201
202	if (resource_disabled("acpi", 0))
203		return (ENXIO);
204
205	/*
206	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
207	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
208	 * pmap_mapdev() to map the RSDP.
209	 */
210	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
211		return (ENXIO);
212#ifdef __i386__
213	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
214#endif
215	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
216	if (rsdp == NULL) {
217		if (bootverbose)
218			printf("MADT: Failed to map RSDP\n");
219		return (ENXIO);
220	}
221
222	/*
223	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
224	 * We map the XSDT and RSDT at page 1 in the crashdump area.
225	 * Page 0 is used to map in the headers of candidate ACPI tables.
226	 */
227	if (rsdp->Revision >= 2) {
228		/*
229		 * AcpiOsGetRootPointer only verifies the checksum for
230		 * the version 1.0 portion of the RSDP.  Version 2.0 has
231		 * an additional checksum that we verify first.
232		 */
233		if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
234			if (bootverbose)
235				printf("MADT: RSDP failed extended checksum\n");
236			return (ENXIO);
237		}
238		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
239		if (xsdt == NULL) {
240			if (bootverbose)
241				printf("MADT: Failed to map XSDT\n");
242			return (ENXIO);
243		}
244		count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
245		    sizeof(UINT64);
246		for (i = 0; i < count; i++)
247			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
248				break;
249		madt_unmap_table(xsdt);
250	} else {
251		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
252		if (rsdt == NULL) {
253			if (bootverbose)
254				printf("MADT: Failed to map RSDT\n");
255			return (ENXIO);
256		}
257		count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
258		    sizeof(UINT32);
259		for (i = 0; i < count; i++)
260			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
261				break;
262		madt_unmap_table(rsdt);
263	}
264	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
265	if (madt_physaddr == 0) {
266		if (bootverbose)
267			printf("MADT: No MADT table found\n");
268		return (ENXIO);
269	}
270	if (bootverbose)
271		printf("MADT: Found table at 0x%jx\n",
272		    (uintmax_t)madt_physaddr);
273
274	/*
275	 * Verify that we can map the full table and that its checksum is
276	 * correct, etc.
277	 */
278	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
279	if (madt == NULL)
280		return (ENXIO);
281	madt_unmap_table(madt);
282	madt = NULL;
283
284	return (0);
285}
286
287/*
288 * See if a given ACPI table is the MADT.
289 */
290static int
291madt_probe_table(vm_paddr_t address)
292{
293	ACPI_TABLE_HEADER *table;
294
295	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
296	if (table == NULL) {
297		if (bootverbose)
298			printf("MADT: Failed to map table at 0x%jx\n",
299			    (uintmax_t)address);
300		return (0);
301	}
302	if (bootverbose)
303		printf("Table '%.4s' at 0x%jx\n", table->Signature,
304		    (uintmax_t)address);
305
306	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
307		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
308		return (0);
309	}
310	madt_physaddr = address;
311	madt_length = table->Length;
312	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
313	return (1);
314}
315
316/*
317 * Run through the MP table enumerating CPUs.
318 */
319static int
320madt_probe_cpus(void)
321{
322
323	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
324	KASSERT(madt != NULL, ("Unable to re-map MADT"));
325	madt_walk_table(madt_probe_cpus_handler, NULL);
326	madt_unmap_table(madt);
327	madt = NULL;
328	return (0);
329}
330
331/*
332 * Initialize the local APIC on the BSP.
333 */
334static int
335madt_setup_local(void)
336{
337
338	madt = pmap_mapdev(madt_physaddr, madt_length);
339	lapic_init((uintptr_t)madt->LocalApicAddress);
340	printf("ACPI APIC Table: <%.*s %.*s>\n",
341	    (int)sizeof(madt->OemId), madt->OemId,
342	    (int)sizeof(madt->OemTableId), madt->OemTableId);
343
344	/*
345	 * We ignore 64-bit local APIC override entries.  Should we
346	 * perhaps emit a warning here if we find one?
347	 */
348	return (0);
349}
350
351/*
352 * Enumerate I/O APICs and setup interrupt sources.
353 */
354static int
355madt_setup_io(void)
356{
357	void *ioapic;
358	u_int pin;
359	int i;
360
361	/* Try to initialize ACPI so that we can access the FADT. */
362	i = acpi_Startup();
363	if (ACPI_FAILURE(i)) {
364		printf("MADT: ACPI Startup failed with %s\n",
365		    AcpiFormatException(i));
366		printf("Try disabling either ACPI or apic support.\n");
367		panic("Using MADT but ACPI doesn't work");
368	}
369
370	/* First, we run through adding I/O APIC's. */
371	if (madt->PCATCompat)
372		ioapic_enable_mixed_mode();
373	madt_walk_table(madt_parse_apics, NULL);
374
375	/* Second, we run through the table tweaking interrupt sources. */
376	madt_walk_table(madt_parse_ints, NULL);
377
378	/*
379	 * If there was not an explicit override entry for the SCI,
380	 * force it to use level trigger and active-low polarity.
381	 */
382	if (!madt_found_sci_override) {
383		if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
384		    != 0)
385			printf("MADT: Could not find APIC for SCI IRQ %d\n",
386			    AcpiGbl_FADT->SciInt);
387		else {
388			printf(
389	"MADT: Forcing active-low polarity and level trigger for SCI\n");
390			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
391			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
392		}
393	}
394
395	/* Third, we register all the I/O APIC's. */
396	for (i = 0; i < NIOAPICS; i++)
397		if (ioapics[i].io_apic != NULL)
398			ioapic_register(ioapics[i].io_apic);
399
400	/* Finally, we throw the switch to enable the I/O APIC's. */
401	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
402
403	return (0);
404}
405
406static void
407madt_register(void *dummy __unused)
408{
409
410	apic_register_enumerator(&madt_enumerator);
411}
412SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
413
414/*
415 * Call the handler routine for each entry in the MADT table.
416 */
417static void
418madt_walk_table(madt_entry_handler *handler, void *arg)
419{
420	APIC_HEADER *entry;
421	u_char *p, *end;
422
423	end = (u_char *)(madt) + madt->Length;
424	for (p = (u_char *)(madt + 1); p < end; ) {
425		entry = (APIC_HEADER *)p;
426		handler(entry, arg);
427		p += entry->Length;
428	}
429}
430
431static void
432madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
433{
434	MADT_PROCESSOR_APIC *proc;
435	struct lapic_info *la;
436
437	switch (entry->Type) {
438	case APIC_PROCESSOR:
439		/*
440		 * The MADT does not include a BSP flag, so we have to
441		 * let the MP code figure out which CPU is the BSP on
442		 * its own.
443		 */
444		proc = (MADT_PROCESSOR_APIC *)entry;
445		if (bootverbose)
446			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
447			    proc->LocalApicId, proc->ProcessorId,
448			    proc->ProcessorEnabled ? "enabled" : "disabled");
449		if (proc->LocalApicId >= NLAPICS)
450			panic("%s: CPU ID %d too high", __func__,
451			    proc->LocalApicId);
452		la = &lapics[proc->LocalApicId];
453		KASSERT(la->la_present == 0,
454		    ("Duplicate local APIC ID %d", proc->LocalApicId));
455		la->la_present = 1;
456		la->la_acpi_id = proc->ProcessorId;
457		if (proc->ProcessorEnabled) {
458			la->la_enabled = 1;
459			lapic_create(proc->LocalApicId, 0);
460		}
461		break;
462	}
463}
464
465
466/*
467 * Add an I/O APIC from an entry in the table.
468 */
469static void
470madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
471{
472	MADT_IO_APIC *apic;
473
474	switch (entry->Type) {
475	case APIC_IO:
476		apic = (MADT_IO_APIC *)entry;
477		if (bootverbose)
478			printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
479			    apic->IoApicId, apic->Interrupt,
480			    (void *)(uintptr_t)apic->Address);
481		if (apic->IoApicId >= NIOAPICS)
482			panic("%s: I/O APIC ID %d too high", __func__,
483			    apic->IoApicId);
484		if (ioapics[apic->IoApicId].io_apic != NULL)
485			panic("%s: Double APIC ID %d", __func__,
486			    apic->IoApicId);
487		ioapics[apic->IoApicId].io_apic = ioapic_create(
488			(uintptr_t)apic->Address, apic->IoApicId,
489			    apic->Interrupt);
490		ioapics[apic->IoApicId].io_vector = apic->Interrupt;
491		break;
492	default:
493		break;
494	}
495}
496
497/*
498 * Determine properties of an interrupt source.  Note that for ACPI these
499 * functions are only used for ISA interrupts, so we assume ISA bus values
500 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
501 * SCI for which we use Active Lo, Level Triggered.
502 */
503static enum intr_polarity
504interrupt_polarity(UINT16 Polarity, UINT8 Source)
505{
506
507	switch (Polarity) {
508	case POLARITY_CONFORMS:
509		if (Source == AcpiGbl_FADT->SciInt)
510			return (INTR_POLARITY_LOW);
511		else
512			return (INTR_POLARITY_HIGH);
513	case POLARITY_ACTIVE_HIGH:
514		return (INTR_POLARITY_HIGH);
515	case POLARITY_ACTIVE_LOW:
516		return (INTR_POLARITY_LOW);
517	default:
518		panic("Bogus Interrupt Polarity");
519	}
520}
521
522static enum intr_trigger
523interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
524{
525
526	switch (TriggerMode) {
527	case TRIGGER_CONFORMS:
528		if (Source == AcpiGbl_FADT->SciInt)
529			return (INTR_TRIGGER_LEVEL);
530		else
531			return (INTR_TRIGGER_EDGE);
532	case TRIGGER_EDGE:
533		return (INTR_TRIGGER_EDGE);
534	case TRIGGER_LEVEL:
535		return (INTR_TRIGGER_LEVEL);
536	default:
537		panic("Bogus Interrupt Trigger Mode");
538	}
539}
540
541/*
542 * Find the local APIC ID associated with a given ACPI Processor ID.
543 */
544static int
545madt_find_cpu(u_int acpi_id, u_int *apic_id)
546{
547	int i;
548
549	for (i = 0; i < NLAPICS; i++) {
550		if (!lapics[i].la_present)
551			continue;
552		if (lapics[i].la_acpi_id != acpi_id)
553			continue;
554		*apic_id = i;
555		if (lapics[i].la_enabled)
556			return (0);
557		else
558			return (ENXIO);
559	}
560	return (ENOENT);
561}
562
563/*
564 * Find the IO APIC and pin on that APIC associated with a given global
565 * interrupt.
566 */
567static int
568madt_find_interrupt(int intr, void **apic, u_int *pin)
569{
570	int i, best;
571
572	best = -1;
573	for (i = 0; i < NIOAPICS; i++) {
574		if (ioapics[i].io_apic == NULL ||
575		    ioapics[i].io_vector > intr)
576			continue;
577		if (best == -1 ||
578		    ioapics[best].io_vector < ioapics[i].io_vector)
579			best = i;
580	}
581	if (best == -1)
582		return (ENOENT);
583	*apic = ioapics[best].io_apic;
584	*pin = intr - ioapics[best].io_vector;
585	if (*pin > 32)
586		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
587		    intr);
588	return (0);
589}
590
591/*
592 * Parse an interrupt source override for an ISA interrupt.
593 */
594static void
595madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
596{
597	void *new_ioapic, *old_ioapic;
598	u_int new_pin, old_pin;
599	enum intr_trigger trig;
600	enum intr_polarity pol;
601	char buf[64];
602
603	if (bootverbose)
604		printf("MADT: intr override: source %u, irq %u\n",
605		    intr->Source, intr->Interrupt);
606	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
607	if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
608	    &new_pin) != 0) {
609		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
610		    intr->Interrupt, intr->Source);
611		return;
612	}
613
614	/*
615	 * Lookup the appropriate trigger and polarity modes for this
616	 * entry.
617	 */
618	trig = interrupt_trigger(intr->TriggerMode, intr->Source);
619	pol = interrupt_polarity(intr->Polarity, intr->Source);
620
621	/*
622	 * If the SCI is identity mapped but has edge trigger and
623	 * active-hi polarity or the force_sci_lo tunable is set,
624	 * force it to use level/lo.
625	 */
626	if (intr->Source == AcpiGbl_FADT->SciInt) {
627		madt_found_sci_override = 1;
628		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
629			if (tolower(buf[0]) == 'e')
630				trig = INTR_TRIGGER_EDGE;
631			else if (tolower(buf[0]) == 'l')
632				trig = INTR_TRIGGER_LEVEL;
633			else
634				panic(
635				"Invalid trigger %s: must be 'edge' or 'level'",
636				    buf);
637			printf("MADT: Forcing SCI to %s trigger\n",
638			    trig == INTR_TRIGGER_EDGE ? "edge" : "level");
639		}
640		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
641			if (tolower(buf[0]) == 'h')
642				pol = INTR_POLARITY_HIGH;
643			else if (tolower(buf[0]) == 'l')
644				pol = INTR_POLARITY_LOW;
645			else
646				panic(
647				"Invalid polarity %s: must be 'high' or 'low'",
648				    buf);
649			printf("MADT: Forcing SCI to active %s polarity\n",
650			    pol == INTR_POLARITY_HIGH ? "high" : "low");
651		}
652	}
653
654	/* Remap the IRQ if it is mapped to a different interrupt vector. */
655	if (intr->Source != intr->Interrupt) {
656		/*
657		 * If the SCI is remapped to a non-ISA global interrupt,
658		 * then override the vector we use to setup and allocate
659		 * the interrupt.
660		 */
661		if (intr->Interrupt > 15 &&
662		    intr->Source == AcpiGbl_FADT->SciInt)
663			acpi_OverrideInterruptLevel(intr->Interrupt);
664		else
665			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
666		if (madt_find_interrupt(intr->Source, &old_ioapic,
667		    &old_pin) != 0)
668			printf("MADT: Could not find APIC for source IRQ %d\n",
669			    intr->Source);
670		else if (ioapic_get_vector(old_ioapic, old_pin) ==
671		    intr->Source)
672			ioapic_disable_pin(old_ioapic, old_pin);
673	}
674
675	/* Program the polarity and trigger mode. */
676	ioapic_set_triggermode(new_ioapic, new_pin, trig);
677	ioapic_set_polarity(new_ioapic, new_pin, pol);
678}
679
680/*
681 * Parse an entry for an NMI routed to an IO APIC.
682 */
683static void
684madt_parse_nmi(MADT_NMI_SOURCE *nmi)
685{
686	void *ioapic;
687	u_int pin;
688
689	if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
690		printf("MADT: Could not find APIC for vector %d\n",
691		    nmi->Interrupt);
692		return;
693	}
694
695	ioapic_set_nmi(ioapic, pin);
696	if (nmi->TriggerMode != TRIGGER_CONFORMS)
697		ioapic_set_triggermode(ioapic, pin,
698		    interrupt_trigger(nmi->TriggerMode, 0));
699	if (nmi->Polarity != TRIGGER_CONFORMS)
700		ioapic_set_polarity(ioapic, pin,
701		    interrupt_polarity(nmi->Polarity, 0));
702}
703
704/*
705 * Parse an entry for an NMI routed to a local APIC LVT pin.
706 */
707static void
708madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
709{
710	u_int apic_id, pin;
711
712	if (nmi->ProcessorId == 0xff)
713		apic_id = APIC_ID_ALL;
714	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
715		if (bootverbose)
716			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
717			    nmi->ProcessorId);
718		return;
719	}
720	if (nmi->Lint == 0)
721		pin = LVT_LINT0;
722	else
723		pin = LVT_LINT1;
724	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
725	if (nmi->TriggerMode != TRIGGER_CONFORMS)
726		lapic_set_lvt_triggermode(apic_id, pin,
727		    interrupt_trigger(nmi->TriggerMode, 0));
728	if (nmi->Polarity != POLARITY_CONFORMS)
729		lapic_set_lvt_polarity(apic_id, pin,
730		    interrupt_polarity(nmi->Polarity, 0));
731}
732
733/*
734 * Parse interrupt entries.
735 */
736static void
737madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
738{
739
740	switch (entry->Type) {
741	case APIC_XRUPT_OVERRIDE:
742		madt_parse_interrupt_override(
743			(MADT_INTERRUPT_OVERRIDE *)entry);
744		break;
745	case APIC_NMI:
746		madt_parse_nmi((MADT_NMI_SOURCE *)entry);
747		break;
748	case APIC_LOCAL_NMI:
749		madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
750		break;
751	}
752}
753
754/*
755 * Setup per-CPU ACPI IDs.
756 */
757static void
758madt_set_ids(void *dummy)
759{
760	struct lapic_info *la;
761	struct pcpu *pc;
762	u_int i;
763
764	if (madt == NULL)
765		return;
766	for (i = 0; i <= mp_maxid; i++) {
767		if (CPU_ABSENT(i))
768			continue;
769		pc = pcpu_find(i);
770		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
771		la = &lapics[pc->pc_apic_id];
772		if (!la->la_present || !la->la_enabled)
773			panic("APIC: CPU with APIC ID %u is not enabled",
774			    pc->pc_apic_id);
775		pc->pc_acpi_id = la->la_acpi_id;
776		if (bootverbose)
777			printf("APIC: CPU %u has ACPI ID %u\n", i,
778			    la->la_acpi_id);
779	}
780}
781SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
782