madt.c revision 122502
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 122502 2003-11-11 18:20:10Z jhb $"); 32121992Sjhb 33121992Sjhb#include <sys/param.h> 34121992Sjhb#include <sys/systm.h> 35121992Sjhb#include <sys/bus.h> 36121992Sjhb#include <sys/kernel.h> 37121992Sjhb#include <sys/malloc.h> 38121992Sjhb#include <sys/smp.h> 39121992Sjhb 40121992Sjhb#include <vm/vm.h> 41121992Sjhb#include <vm/vm_param.h> 42121992Sjhb#include <vm/pmap.h> 43121992Sjhb 44121992Sjhb#include <machine/apicreg.h> 45121992Sjhb#include <machine/frame.h> 46121992Sjhb#include <machine/intr_machdep.h> 47121992Sjhb#include <machine/apicvar.h> 48121992Sjhb#include <machine/md_var.h> 49121992Sjhb#include <machine/specialreg.h> 50121992Sjhb 51121992Sjhb#include "acpi.h" 52121992Sjhb#include <dev/acpica/acpivar.h> 53121992Sjhb#include <dev/acpica/madt.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 59121992Sjhbtypedef void madt_entry_handler(APIC_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_present:1; 69121992Sjhb u_int la_enabled:1; 70121992Sjhb u_int la_apic_id:8; 71121992Sjhb} lapics[NLAPICS + 1]; 72121992Sjhb 73121992Sjhbstatic APIC_TABLE *madt; 74121992Sjhbstatic vm_paddr_t madt_physaddr; 75121992Sjhbstatic vm_offset_t madt_length; 76121992Sjhb 77121992SjhbMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items"); 78121992Sjhb 79121992Sjhbstatic u_char interrupt_polarity(UINT16 Polarity); 80121992Sjhbstatic u_char interrupt_trigger(UINT16 TriggerMode); 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); 85121992Sjhbstatic void madt_parse_apics(APIC_HEADER *entry, void *arg); 86121992Sjhbstatic void madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr); 87121992Sjhbstatic void madt_parse_ints(APIC_HEADER *entry, void *arg __unused); 88121992Sjhbstatic void madt_parse_local_nmi(LAPIC_NMI *nmi); 89121992Sjhbstatic void madt_parse_nmi(NMI *nmi); 90121992Sjhbstatic int madt_probe(void); 91121992Sjhbstatic int madt_probe_cpus(void); 92121992Sjhbstatic void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused); 93121992Sjhbstatic int madt_probe_table(vm_paddr_t address); 94121992Sjhbstatic void madt_register(void *dummy); 95121992Sjhbstatic int madt_setup_local(void); 96121992Sjhbstatic int madt_setup_io(void); 97121992Sjhbstatic void madt_unmap(void *data, vm_offset_t length); 98121992Sjhbstatic void madt_unmap_table(void *table); 99121992Sjhbstatic void madt_walk_table(madt_entry_handler *handler, void *arg); 100121992Sjhb 101121992Sjhbstatic struct apic_enumerator madt_enumerator = { 102121992Sjhb "MADT", 103121992Sjhb madt_probe, 104121992Sjhb madt_probe_cpus, 105121992Sjhb madt_setup_local, 106121992Sjhb madt_setup_io 107121992Sjhb}; 108121992Sjhb 109121992Sjhb/* 110121992Sjhb * Code to abuse the crashdump map to map in the tables for the early 111121992Sjhb * probe. We cheat and make the following assumptions about how we 112121992Sjhb * use this KVA: page 0 is used to map in the first page of each table 113121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the 114121992Sjhb * RSDT or XSDT. The offset is in pages; the length is in bytes. 115121992Sjhb */ 116121992Sjhbstatic void * 117121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length) 118121992Sjhb{ 119121992Sjhb vm_offset_t va, off; 120121992Sjhb void *data; 121121992Sjhb 122121992Sjhb off = pa & PAGE_MASK; 123121992Sjhb length = roundup(length + off, PAGE_SIZE); 124121992Sjhb pa = pa & PG_FRAME; 125121992Sjhb va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 126121992Sjhb (offset * PAGE_SIZE); 127121992Sjhb data = (void *)(va + off); 128121992Sjhb length -= PAGE_SIZE; 129121992Sjhb while (length > 0) { 130121992Sjhb va += PAGE_SIZE; 131121992Sjhb pa += PAGE_SIZE; 132121992Sjhb length -= PAGE_SIZE; 133121992Sjhb pmap_kenter(va, pa); 134121992Sjhb invlpg(va); 135121992Sjhb } 136121992Sjhb return (data); 137121992Sjhb} 138121992Sjhb 139121992Sjhbstatic void 140121992Sjhbmadt_unmap(void *data, vm_offset_t length) 141121992Sjhb{ 142121992Sjhb vm_offset_t va, off; 143121992Sjhb 144121992Sjhb va = (vm_offset_t)data; 145121992Sjhb off = va & PAGE_MASK; 146121992Sjhb length = roundup(length + off, PAGE_SIZE); 147121992Sjhb va &= ~PAGE_MASK; 148121992Sjhb while (length > 0) { 149121992Sjhb pmap_kremove(va); 150121992Sjhb invlpg(va); 151121992Sjhb va += PAGE_SIZE; 152121992Sjhb length -= PAGE_SIZE; 153121992Sjhb } 154121992Sjhb} 155121992Sjhb 156121992Sjhbstatic void * 157121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig) 158121992Sjhb{ 159121992Sjhb ACPI_TABLE_HEADER *header; 160121992Sjhb vm_offset_t length; 161121992Sjhb 162121992Sjhb header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 163121992Sjhb if (strncmp(header->Signature, sig, 4) != 0) { 164121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 165121992Sjhb return (NULL); 166121992Sjhb } 167121992Sjhb length = header->Length; 168121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 169121992Sjhb return (madt_map(pa, offset, length)); 170121992Sjhb} 171121992Sjhb 172121992Sjhbstatic void 173121992Sjhbmadt_unmap_table(void *table) 174121992Sjhb{ 175121992Sjhb ACPI_TABLE_HEADER *header; 176121992Sjhb 177121992Sjhb header = (ACPI_TABLE_HEADER *)table; 178121992Sjhb madt_unmap(table, header->Length); 179121992Sjhb} 180121992Sjhb 181121992Sjhb/* 182121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 183121992Sjhb */ 184121992Sjhbstatic int 185121992Sjhbmadt_probe(void) 186121992Sjhb{ 187121992Sjhb ACPI_POINTER rsdp_ptr; 188121992Sjhb RSDP_DESCRIPTOR *rsdp; 189121992Sjhb RSDT_DESCRIPTOR *rsdt; 190121992Sjhb XSDT_DESCRIPTOR *xsdt; 191121992Sjhb int i, count; 192121992Sjhb 193121992Sjhb if (resource_disabled("acpi", 0)) 194121992Sjhb return (ENXIO); 195121992Sjhb 196121992Sjhb /* 197121992Sjhb * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 198121992Sjhb * calls pmap_mapdev() to find the RSDP, we assume that we can use 199121992Sjhb * pmap_mapdev() to map the RSDP. 200121992Sjhb */ 201121992Sjhb if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 202121992Sjhb return (ENXIO); 203121992Sjhb KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high")); 204121992Sjhb rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR)); 205121992Sjhb if (rsdp == NULL) { 206121992Sjhb if (bootverbose) 207121992Sjhb printf("MADT: Failed to map RSDP\n"); 208121992Sjhb return (ENXIO); 209121992Sjhb } 210121992Sjhb 211121992Sjhb /* 212121992Sjhb * For ACPI < 2.0, use the RSDT. For ACPI >= 2.0, use the XSDT. 213121992Sjhb * We map the XSDT and RSDT at page 1 in the crashdump area. 214121992Sjhb * Page 0 is used to map in the headers of candidate ACPI tables. 215121992Sjhb */ 216121992Sjhb if (rsdp->Revision >= 2) { 217121992Sjhb xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG); 218121992Sjhb if (xsdt == NULL) { 219121992Sjhb if (bootverbose) 220121992Sjhb printf("MADT: Failed to map XSDT\n"); 221121992Sjhb return (ENXIO); 222121992Sjhb } 223121992Sjhb count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 224121992Sjhb sizeof(UINT64); 225121992Sjhb for (i = 0; i < count; i++) 226121992Sjhb if (madt_probe_table(xsdt->TableOffsetEntry[i])) 227121992Sjhb break; 228121992Sjhb madt_unmap_table(xsdt); 229121992Sjhb } else { 230121992Sjhb rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG); 231121992Sjhb if (rsdt == NULL) { 232121992Sjhb if (bootverbose) 233121992Sjhb printf("MADT: Failed to map RSDT\n"); 234121992Sjhb return (ENXIO); 235121992Sjhb } 236121992Sjhb count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 237121992Sjhb sizeof(UINT32); 238121992Sjhb for (i = 0; i < count; i++) 239121992Sjhb if (madt_probe_table(rsdt->TableOffsetEntry[i])) 240121992Sjhb break; 241121992Sjhb madt_unmap_table(rsdt); 242121992Sjhb } 243121992Sjhb pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR)); 244121992Sjhb if (madt_physaddr == 0) { 245121992Sjhb if (bootverbose) 246121992Sjhb printf("MADT: No MADT table found\n"); 247121992Sjhb return (ENXIO); 248121992Sjhb } 249121992Sjhb if (bootverbose) 250122016Speter printf("MADT: Found table at 0x%jx\n", 251122016Speter (uintmax_t)madt_physaddr); 252121992Sjhb 253121992Sjhb return (0); 254121992Sjhb} 255121992Sjhb 256121992Sjhb/* 257121992Sjhb * See if a given ACPI table is the MADT. 258121992Sjhb */ 259121992Sjhbstatic int 260121992Sjhbmadt_probe_table(vm_paddr_t address) 261121992Sjhb{ 262121992Sjhb ACPI_TABLE_HEADER *table; 263121992Sjhb 264121992Sjhb table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 265121992Sjhb if (table == NULL) { 266121992Sjhb if (bootverbose) 267122016Speter printf("MADT: Failed to map table at 0x%jx\n", 268122016Speter (uintmax_t)address); 269121992Sjhb return (0); 270121992Sjhb } 271121992Sjhb if (bootverbose) 272122016Speter printf("Table '%.4s' at 0x%jx\n", table->Signature, 273122016Speter (uintmax_t)address); 274121992Sjhb 275121992Sjhb /* XXX: Verify checksum? */ 276121992Sjhb if (strncmp(table->Signature, APIC_SIG, 4) != 0) { 277121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 278121992Sjhb return (0); 279121992Sjhb } 280121992Sjhb madt_physaddr = address; 281121992Sjhb madt_length = table->Length; 282121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 283121992Sjhb return (1); 284121992Sjhb} 285121992Sjhb 286121992Sjhb/* 287121992Sjhb * Run through the MP table enumerating CPUs. 288121992Sjhb */ 289121992Sjhbstatic int 290121992Sjhbmadt_probe_cpus(void) 291121992Sjhb{ 292121992Sjhb 293121992Sjhb madt = madt_map_table(madt_physaddr, 0, APIC_SIG); 294121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 295121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 296121992Sjhb madt_unmap_table(madt); 297121992Sjhb madt = NULL; 298121992Sjhb return (0); 299121992Sjhb} 300121992Sjhb 301121992Sjhb/* 302121992Sjhb * Initialize the local APIC on the BSP. 303121992Sjhb */ 304121992Sjhbstatic int 305121992Sjhbmadt_setup_local(void) 306121992Sjhb{ 307121992Sjhb 308121992Sjhb madt = pmap_mapdev(madt_physaddr, madt_length); 309121992Sjhb lapic_init((uintptr_t)madt->LocalApicAddress); 310121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 311121992Sjhb sizeof(madt->Header.OemId), madt->Header.OemId, 312121992Sjhb sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 313121992Sjhb 314121992Sjhb /* 315121992Sjhb * We ignore 64-bit local APIC override entries. Should we 316121992Sjhb * perhaps emit a warning here if we find one? 317121992Sjhb */ 318121992Sjhb return (0); 319121992Sjhb} 320121992Sjhb 321121992Sjhb/* 322121992Sjhb * Run through the MP table enumerating I/O APICs. 323121992Sjhb */ 324121992Sjhbstatic int 325121992Sjhbmadt_setup_io(void) 326121992Sjhb{ 327121992Sjhb int i; 328121992Sjhb 329121992Sjhb /* First, we run through adding I/O APIC's. */ 330121992Sjhb madt_walk_table(madt_parse_apics, NULL); 331121992Sjhb 332121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 333121992Sjhb madt_walk_table(madt_parse_ints, NULL); 334121992Sjhb 335121992Sjhb /* Third, we register all the I/O APIC's. */ 336121992Sjhb for (i = 0; i < NIOAPICS; i++) 337121992Sjhb if (ioapics[i].io_apic != NULL) 338121992Sjhb ioapic_register(ioapics[i].io_apic); 339121992Sjhb 340121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 341121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 342121992Sjhb 343121992Sjhb return (0); 344121992Sjhb} 345121992Sjhb 346121992Sjhbstatic void 347121992Sjhbmadt_register(void *dummy __unused) 348121992Sjhb{ 349121992Sjhb 350121992Sjhb apic_register_enumerator(&madt_enumerator); 351121992Sjhb} 352121992SjhbSYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, 353121992Sjhb madt_register, NULL) 354121992Sjhb 355121992Sjhb/* 356121992Sjhb * Call the handler routine for each entry in the MADT table. 357121992Sjhb */ 358121992Sjhbstatic void 359121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg) 360121992Sjhb{ 361121992Sjhb APIC_HEADER *entry; 362121992Sjhb u_char *p, *end; 363121992Sjhb 364121992Sjhb end = (u_char *)(madt) + madt->Header.Length; 365121992Sjhb for (p = (u_char *)(madt + 1); p < end; ) { 366121992Sjhb entry = (APIC_HEADER *)p; 367121992Sjhb handler(entry, arg); 368121992Sjhb p += entry->Length; 369121992Sjhb } 370121992Sjhb} 371121992Sjhb 372121992Sjhbstatic void 373121992Sjhbmadt_probe_cpus_handler(APIC_HEADER *entry, void *arg) 374121992Sjhb{ 375121992Sjhb PROCESSOR_APIC *proc; 376121992Sjhb struct lapic_info *la; 377121992Sjhb 378121992Sjhb switch (entry->Type) { 379121992Sjhb case APIC_PROC: 380121992Sjhb /* 381121992Sjhb * The MADT does not include a BSP flag, so we have to 382121992Sjhb * let the MP code figure out which CPU is the BSP on 383121992Sjhb * its own. 384121992Sjhb */ 385121992Sjhb proc = (PROCESSOR_APIC *)entry; 386121992Sjhb if (bootverbose) 387121992Sjhb printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", 388121992Sjhb proc->LocalApicId, proc->ProcessorApicId, 389121992Sjhb proc->ProcessorEnabled ? "enabled" : "disabled"); 390121992Sjhb if (proc->ProcessorApicId > NLAPICS) 391121992Sjhb panic("%s: CPU ID %d too high", __func__, 392121992Sjhb proc->ProcessorApicId); 393121992Sjhb la = &lapics[proc->ProcessorApicId]; 394121992Sjhb KASSERT(la->la_present == 0, 395121992Sjhb ("Duplicate local ACPI ID %d", proc->ProcessorApicId)); 396121992Sjhb la->la_present = 1; 397121992Sjhb la->la_apic_id = proc->LocalApicId; 398121992Sjhb if (proc->ProcessorEnabled) { 399121992Sjhb la->la_enabled = 1; 400121992Sjhb lapic_create(proc->LocalApicId, 0); 401121992Sjhb } 402121992Sjhb break; 403121992Sjhb } 404121992Sjhb} 405121992Sjhb 406121992Sjhb 407121992Sjhb/* 408121992Sjhb * Add an I/O APIC from an entry in the table. 409121992Sjhb */ 410121992Sjhbstatic void 411121992Sjhbmadt_parse_apics(APIC_HEADER *entry, void *arg __unused) 412121992Sjhb{ 413121992Sjhb IO_APIC *apic; 414121992Sjhb 415121992Sjhb 416121992Sjhb switch (entry->Type) { 417121992Sjhb case APIC_IO: 418121992Sjhb apic = (IO_APIC *)entry; 419121992Sjhb if (bootverbose) 420121992Sjhb printf("MADT: Found IO APIC ID %d, Vector %d at %p\n", 421121992Sjhb apic->IoApicId, apic->Vector, 422121992Sjhb (void *)apic->IoApicAddress); 423121992Sjhb if (apic->IoApicId >= NIOAPICS) 424121992Sjhb panic("%s: I/O APIC ID %d too high", __func__, 425121992Sjhb apic->IoApicId); 426121992Sjhb if (ioapics[apic->IoApicId].io_apic != NULL) 427121992Sjhb panic("%s: Double APIC ID %d", __func__, 428121992Sjhb apic->IoApicId); 429121992Sjhb ioapics[apic->IoApicId].io_apic = ioapic_create( 430121992Sjhb (uintptr_t)apic->IoApicAddress, apic->IoApicId, 431121992Sjhb apic->Vector); 432121992Sjhb ioapics[apic->IoApicId].io_vector = apic->Vector; 433121992Sjhb break; 434121992Sjhb default: 435121992Sjhb break; 436121992Sjhb } 437121992Sjhb} 438121992Sjhb 439121992Sjhb/* 440121992Sjhb * Determine properties of an interrupt source. Note that for ACPI, 441121992Sjhb * these are only used for ISA interrupts, so we assume ISA bus values 442121992Sjhb * (Active Hi, Edge Triggered) for conforming values. 443121992Sjhb */ 444121992Sjhbstatic u_char 445121992Sjhbinterrupt_polarity(UINT16 Polarity) 446121992Sjhb{ 447121992Sjhb 448121992Sjhb switch (Polarity) { 449121992Sjhb case APIC_POLARITY_CONFORM: 450121992Sjhb case APIC_POLARITY_ACTIVEHI: 451121992Sjhb return (1); 452121992Sjhb case APIC_POLARITY_ACTIVELO: 453121992Sjhb return (0); 454121992Sjhb default: 455121992Sjhb panic("Bogus Interrupt Polarity"); 456121992Sjhb } 457121992Sjhb} 458121992Sjhb 459121992Sjhbstatic u_char 460121992Sjhbinterrupt_trigger(UINT16 TriggerMode) 461121992Sjhb{ 462121992Sjhb 463121992Sjhb switch (TriggerMode) { 464121992Sjhb case APIC_TRIGGER_CONFORM: 465121992Sjhb case APIC_TRIGGER_EDGE: 466121992Sjhb return (1); 467121992Sjhb case APIC_TRIGGER_LEVEL: 468121992Sjhb return (0); 469121992Sjhb default: 470121992Sjhb panic("Bogus Interrupt Trigger Mode"); 471121992Sjhb } 472121992Sjhb} 473121992Sjhb 474121992Sjhb/* 475121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 476121992Sjhb */ 477121992Sjhbstatic int 478121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 479121992Sjhb{ 480121992Sjhb 481121992Sjhb if (!lapics[acpi_id].la_present) 482121992Sjhb return (ENOENT); 483121992Sjhb *apic_id = lapics[acpi_id].la_apic_id; 484121992Sjhb if (lapics[acpi_id].la_enabled) 485121992Sjhb return (0); 486121992Sjhb else 487121992Sjhb return (ENXIO); 488121992Sjhb} 489121992Sjhb 490121992Sjhb/* 491121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 492121992Sjhb * interrupt. 493121992Sjhb */ 494121992Sjhbstatic int 495121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 496121992Sjhb{ 497121992Sjhb int i, best; 498121992Sjhb 499121992Sjhb best = -1; 500121992Sjhb for (i = 0; i < NIOAPICS; i++) { 501121992Sjhb if (ioapics[i].io_apic == NULL || 502121992Sjhb ioapics[i].io_vector > intr) 503121992Sjhb continue; 504121992Sjhb if (best == -1 || 505121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 506121992Sjhb best = i; 507121992Sjhb } 508121992Sjhb if (best == -1) 509121992Sjhb return (ENOENT); 510121992Sjhb *apic = ioapics[best].io_apic; 511121992Sjhb *pin = intr - ioapics[best].io_vector; 512121992Sjhb if (*pin > 32) 513121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 514121992Sjhb intr); 515121992Sjhb return (0); 516121992Sjhb} 517121992Sjhb 518121992Sjhb/* 519121992Sjhb * Parse an interrupt source override for an ISA interrupt. 520121992Sjhb */ 521121992Sjhbstatic void 522121992Sjhbmadt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr) 523121992Sjhb{ 524122149Sjhb void *new_ioapic, *old_ioapic; 525122149Sjhb u_int new_pin, old_pin; 526121992Sjhb 527121992Sjhb if (bootverbose) 528121992Sjhb printf("MADT: intr override: source %u, irq %u\n", 529121992Sjhb intr->Source, intr->GlobalSystemInterrupt); 530121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 531122149Sjhb if (madt_find_interrupt(intr->GlobalSystemInterrupt, &new_ioapic, 532122149Sjhb &new_pin) != 0) { 533121992Sjhb printf("MADT: Could not find APIC for vector %d (IRQ %d)\n", 534121992Sjhb intr->GlobalSystemInterrupt, intr->Source); 535121992Sjhb return; 536121992Sjhb } 537121992Sjhb 538122149Sjhb if (intr->Source != intr->GlobalSystemInterrupt) { 539122502Sjhb /* XXX: This assumes that the SCI uses IRQ 9. */ 540122502Sjhb if (intr->GlobalSystemInterrupt > 15 && intr->Source == 9) 541122502Sjhb acpi_OverrideInterruptLevel( 542122502Sjhb intr->GlobalSystemInterrupt); 543122502Sjhb else 544122502Sjhb ioapic_remap_vector(new_ioapic, new_pin, intr->Source); 545122149Sjhb if (madt_find_interrupt(intr->Source, &old_ioapic, 546122149Sjhb &old_pin) != 0) 547122149Sjhb printf("MADT: Could not find APIC for source IRQ %d\n", 548122149Sjhb intr->Source); 549122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 550122172Sjhb intr->Source) 551122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 552122149Sjhb } 553122149Sjhb ioapic_set_triggermode(new_ioapic, new_pin, 554121992Sjhb interrupt_trigger(intr->TriggerMode)); 555122149Sjhb ioapic_set_polarity(new_ioapic, new_pin, 556122149Sjhb interrupt_polarity(intr->Polarity)); 557121992Sjhb} 558121992Sjhb 559121992Sjhb/* 560121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 561121992Sjhb */ 562121992Sjhbstatic void 563121992Sjhbmadt_parse_nmi(NMI *nmi) 564121992Sjhb{ 565121992Sjhb void *ioapic; 566121992Sjhb u_int pin; 567121992Sjhb 568121992Sjhb if (madt_find_interrupt(nmi->GlobalSystemInterrupt, 569121992Sjhb &ioapic, &pin) != 0) { 570121992Sjhb printf("MADT: Could not find APIC for vector %d\n", 571121992Sjhb nmi->GlobalSystemInterrupt); 572121992Sjhb return; 573121992Sjhb } 574121992Sjhb 575121992Sjhb ioapic_set_nmi(ioapic, pin); 576121992Sjhb if (nmi->TriggerMode != APIC_TRIGGER_CONFORM) 577121992Sjhb ioapic_set_triggermode(ioapic, pin, 578121992Sjhb interrupt_trigger(nmi->TriggerMode)); 579121992Sjhb if (nmi->Polarity != APIC_TRIGGER_CONFORM) 580121992Sjhb ioapic_set_polarity(ioapic, pin, 581121992Sjhb interrupt_polarity(nmi->Polarity)); 582121992Sjhb} 583121992Sjhb 584121992Sjhb/* 585121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 586121992Sjhb */ 587121992Sjhbstatic void 588121992Sjhbmadt_parse_local_nmi(LAPIC_NMI *nmi) 589121992Sjhb{ 590121992Sjhb u_int apic_id, pin; 591121992Sjhb 592121992Sjhb if (nmi->ProcessorApicId == 0xff) 593121992Sjhb apic_id = APIC_ID_ALL; 594121992Sjhb else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) != 0) { 595121992Sjhb if (bootverbose) 596121992Sjhb printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", 597121992Sjhb nmi->ProcessorApicId); 598121992Sjhb return; 599121992Sjhb } 600121992Sjhb if (nmi->LINTPin == 0) 601121992Sjhb pin = LVT_LINT0; 602121992Sjhb else 603121992Sjhb pin = LVT_LINT1; 604121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 605121992Sjhb if (nmi->TriggerMode != APIC_TRIGGER_CONFORM) 606121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 607121992Sjhb interrupt_trigger(nmi->TriggerMode)); 608121992Sjhb if (nmi->Polarity != APIC_POLARITY_CONFORM) 609121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 610121992Sjhb interrupt_polarity(nmi->Polarity)); 611121992Sjhb} 612121992Sjhb 613121992Sjhb/* 614121992Sjhb * Parse interrupt entries. 615121992Sjhb */ 616121992Sjhbstatic void 617121992Sjhbmadt_parse_ints(APIC_HEADER *entry, void *arg __unused) 618121992Sjhb{ 619121992Sjhb 620121992Sjhb switch (entry->Type) { 621121992Sjhb case APIC_INTERRUPT_SOURCE_OVERRIDE: 622121992Sjhb madt_parse_interrupt_override( 623121992Sjhb (INTERRUPT_SOURCE_OVERRIDE *)entry); 624121992Sjhb break; 625121992Sjhb case APIC_NMI: 626121992Sjhb madt_parse_nmi((NMI *)entry); 627121992Sjhb break; 628121992Sjhb case APIC_LOCAL_APIC_NMI: 629121992Sjhb madt_parse_local_nmi((LAPIC_NMI *)entry); 630121992Sjhb break; 631121992Sjhb } 632121992Sjhb} 633121992Sjhb 634121992Sjhb/* 635121992Sjhb * Setup per-CPU ACPI IDs. 636121992Sjhb */ 637121992Sjhbstatic void 638121992Sjhbmadt_set_ids(void *dummy) 639121992Sjhb{ 640121992Sjhb struct pcpu *pc; 641121992Sjhb u_int i, j; 642121992Sjhb 643121992Sjhb if (madt == NULL) 644121992Sjhb return; 645121992Sjhb for (i = 0; i < MAXCPU; i++) { 646121992Sjhb if (CPU_ABSENT(i)) 647121992Sjhb continue; 648121992Sjhb pc = pcpu_find(i); 649121992Sjhb KASSERT(pc != NULL, ("no pcpu data for CPU %d", i)); 650121992Sjhb for (j = 0; j < NLAPICS + 1; j++) { 651121992Sjhb if (!lapics[j].la_present || !lapics[j].la_enabled) 652121992Sjhb continue; 653121992Sjhb if (lapics[j].la_apic_id == pc->pc_apic_id) { 654121992Sjhb pc->pc_acpi_id = j; 655121992Sjhb if (bootverbose) 656121992Sjhb printf("APIC: CPU %u has ACPI ID %u\n", 657121992Sjhb i, j); 658121992Sjhb break; 659121992Sjhb } 660121992Sjhb } 661121992Sjhb if (j == NLAPICS + 1) 662121992Sjhb panic("Unable to find ACPI ID for CPU %d", i); 663121992Sjhb } 664121992Sjhb} 665121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 666