madt.c revision 169395
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 169395 2007-05-08 22:01:04Z 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 51150003Sobrien#include <contrib/dev/acpica/acpi.h> 52129094Sjhb#include <contrib/dev/acpica/actables.h> 53121992Sjhb#include <dev/acpica/acpivar.h> 54121992Sjhb#include <dev/pci/pcivar.h> 55121992Sjhb 56167814Sjkimtypedef void madt_entry_handler(ACPI_SUBTABLE_HEADER *entry, void *arg); 57121992Sjhb 58121992Sjhb/* These two arrays are indexed by APIC IDs. */ 59121992Sjhbstruct ioapic_info { 60121992Sjhb void *io_apic; 61121992Sjhb UINT32 io_vector; 62169395Sjhb} ioapics[MAX_APIC_ID + 1]; 63121992Sjhb 64121992Sjhbstruct lapic_info { 65121992Sjhb u_int la_enabled:1; 66129960Sjhb u_int la_acpi_id:8; 67169395Sjhb} lapics[MAX_APIC_ID + 1]; 68121992Sjhb 69128930Sjhbstatic int madt_found_sci_override; 70167814Sjkimstatic ACPI_TABLE_MADT *madt; 71121992Sjhbstatic vm_paddr_t madt_physaddr; 72121992Sjhbstatic vm_offset_t madt_length; 73121992Sjhb 74151897SrwatsonMALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 75121992Sjhb 76167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 77167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 78121992Sjhbstatic int madt_find_cpu(u_int acpi_id, u_int *apic_id); 79121992Sjhbstatic int madt_find_interrupt(int intr, void **apic, u_int *pin); 80121992Sjhbstatic void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); 81121992Sjhbstatic void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); 82167814Sjkimstatic void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 83167814Sjkimstatic void madt_parse_interrupt_override( 84167814Sjkim ACPI_MADT_INTERRUPT_OVERRIDE *intr); 85167814Sjkimstatic void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 86167814Sjkim void *arg __unused); 87167814Sjkimstatic void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 88167814Sjkimstatic void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 89121992Sjhbstatic int madt_probe(void); 90121992Sjhbstatic int madt_probe_cpus(void); 91167814Sjkimstatic void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 92167814Sjkim 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; 161129094Sjhb void *table; 162121992Sjhb 163121992Sjhb header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 164167814Sjkim if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { 165121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 166121992Sjhb return (NULL); 167121992Sjhb } 168121992Sjhb length = header->Length; 169121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 170129094Sjhb table = madt_map(pa, offset, length); 171167814Sjkim if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { 172129094Sjhb if (bootverbose) 173129094Sjhb printf("MADT: Failed checksum for table %s\n", sig); 174129094Sjhb madt_unmap(table, length); 175129094Sjhb return (NULL); 176129094Sjhb } 177129094Sjhb return (table); 178121992Sjhb} 179121992Sjhb 180121992Sjhbstatic void 181121992Sjhbmadt_unmap_table(void *table) 182121992Sjhb{ 183121992Sjhb ACPI_TABLE_HEADER *header; 184121992Sjhb 185121992Sjhb header = (ACPI_TABLE_HEADER *)table; 186121992Sjhb madt_unmap(table, header->Length); 187121992Sjhb} 188121992Sjhb 189121992Sjhb/* 190121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 191121992Sjhb */ 192121992Sjhbstatic int 193121992Sjhbmadt_probe(void) 194121992Sjhb{ 195167814Sjkim ACPI_PHYSICAL_ADDRESS rsdp_ptr; 196167814Sjkim ACPI_TABLE_RSDP *rsdp; 197167814Sjkim ACPI_TABLE_RSDT *rsdt; 198167814Sjkim ACPI_TABLE_XSDT *xsdt; 199121992Sjhb int i, count; 200121992Sjhb 201121992Sjhb if (resource_disabled("acpi", 0)) 202121992Sjhb return (ENXIO); 203121992Sjhb 204121992Sjhb /* 205121992Sjhb * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 206161223Sjhb * calls pmap_mapbios() to find the RSDP, we assume that we can use 207161223Sjhb * pmap_mapbios() to map the RSDP. 208121992Sjhb */ 209167814Sjkim if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) 210121992Sjhb return (ENXIO); 211167814Sjkim rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); 212121992Sjhb if (rsdp == NULL) { 213121992Sjhb if (bootverbose) 214121992Sjhb printf("MADT: Failed to map RSDP\n"); 215121992Sjhb return (ENXIO); 216121992Sjhb } 217121992Sjhb 218121992Sjhb /* 219157179Sjhb * For ACPI >= 2.0, use the XSDT if it is available. 220157179Sjhb * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1 221157179Sjhb * in the crashdump area. Page 0 is used to map in the 222157179Sjhb * headers of candidate ACPI tables. 223121992Sjhb */ 224157179Sjhb if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { 225129094Sjhb /* 226129094Sjhb * AcpiOsGetRootPointer only verifies the checksum for 227129094Sjhb * the version 1.0 portion of the RSDP. Version 2.0 has 228129094Sjhb * an additional checksum that we verify first. 229129094Sjhb */ 230167814Sjkim if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { 231129094Sjhb if (bootverbose) 232129094Sjhb printf("MADT: RSDP failed extended checksum\n"); 233129094Sjhb return (ENXIO); 234129094Sjhb } 235167814Sjkim xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, 236167814Sjkim ACPI_SIG_XSDT); 237121992Sjhb if (xsdt == NULL) { 238121992Sjhb if (bootverbose) 239121992Sjhb printf("MADT: Failed to map XSDT\n"); 240121992Sjhb return (ENXIO); 241121992Sjhb } 242167814Sjkim count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 243121992Sjhb sizeof(UINT64); 244121992Sjhb for (i = 0; i < count; i++) 245121992Sjhb if (madt_probe_table(xsdt->TableOffsetEntry[i])) 246121992Sjhb break; 247121992Sjhb madt_unmap_table(xsdt); 248121992Sjhb } else { 249167814Sjkim rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, 250167814Sjkim ACPI_SIG_RSDT); 251121992Sjhb if (rsdt == NULL) { 252121992Sjhb if (bootverbose) 253121992Sjhb printf("MADT: Failed to map RSDT\n"); 254121992Sjhb return (ENXIO); 255121992Sjhb } 256167814Sjkim count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 257121992Sjhb sizeof(UINT32); 258121992Sjhb for (i = 0; i < count; i++) 259121992Sjhb if (madt_probe_table(rsdt->TableOffsetEntry[i])) 260121992Sjhb break; 261121992Sjhb madt_unmap_table(rsdt); 262121992Sjhb } 263167814Sjkim pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); 264121992Sjhb if (madt_physaddr == 0) { 265121992Sjhb if (bootverbose) 266121992Sjhb printf("MADT: No MADT table found\n"); 267121992Sjhb return (ENXIO); 268121992Sjhb } 269121992Sjhb if (bootverbose) 270122016Speter printf("MADT: Found table at 0x%jx\n", 271122016Speter (uintmax_t)madt_physaddr); 272121992Sjhb 273129094Sjhb /* 274129094Sjhb * Verify that we can map the full table and that its checksum is 275129094Sjhb * correct, etc. 276129094Sjhb */ 277167814Sjkim madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); 278129094Sjhb if (madt == NULL) 279129094Sjhb return (ENXIO); 280129094Sjhb madt_unmap_table(madt); 281129094Sjhb madt = NULL; 282129094Sjhb 283121992Sjhb return (0); 284121992Sjhb} 285121992Sjhb 286121992Sjhb/* 287121992Sjhb * See if a given ACPI table is the MADT. 288121992Sjhb */ 289121992Sjhbstatic int 290121992Sjhbmadt_probe_table(vm_paddr_t address) 291121992Sjhb{ 292121992Sjhb ACPI_TABLE_HEADER *table; 293121992Sjhb 294121992Sjhb table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 295121992Sjhb if (table == NULL) { 296121992Sjhb if (bootverbose) 297122016Speter printf("MADT: Failed to map table at 0x%jx\n", 298122016Speter (uintmax_t)address); 299121992Sjhb return (0); 300121992Sjhb } 301121992Sjhb if (bootverbose) 302122016Speter printf("Table '%.4s' at 0x%jx\n", table->Signature, 303122016Speter (uintmax_t)address); 304121992Sjhb 305167814Sjkim if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) { 306121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 307121992Sjhb return (0); 308121992Sjhb } 309121992Sjhb madt_physaddr = address; 310121992Sjhb madt_length = table->Length; 311121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 312121992Sjhb return (1); 313121992Sjhb} 314121992Sjhb 315121992Sjhb/* 316121992Sjhb * Run through the MP table enumerating CPUs. 317121992Sjhb */ 318121992Sjhbstatic int 319121992Sjhbmadt_probe_cpus(void) 320121992Sjhb{ 321121992Sjhb 322167814Sjkim madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); 323121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 324121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 325121992Sjhb madt_unmap_table(madt); 326121992Sjhb madt = NULL; 327121992Sjhb return (0); 328121992Sjhb} 329121992Sjhb 330121992Sjhb/* 331121992Sjhb * Initialize the local APIC on the BSP. 332121992Sjhb */ 333121992Sjhbstatic int 334121992Sjhbmadt_setup_local(void) 335121992Sjhb{ 336121992Sjhb 337161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 338167814Sjkim lapic_init(madt->Address); 339121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 340167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 341167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 342121992Sjhb 343121992Sjhb /* 344121992Sjhb * We ignore 64-bit local APIC override entries. Should we 345121992Sjhb * perhaps emit a warning here if we find one? 346121992Sjhb */ 347121992Sjhb return (0); 348121992Sjhb} 349121992Sjhb 350121992Sjhb/* 351125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 352121992Sjhb */ 353121992Sjhbstatic int 354121992Sjhbmadt_setup_io(void) 355121992Sjhb{ 356128930Sjhb void *ioapic; 357128930Sjhb u_int pin; 358121992Sjhb int i; 359121992Sjhb 360125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 361125048Sjhb i = acpi_Startup(); 362125048Sjhb if (ACPI_FAILURE(i)) { 363125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 364125048Sjhb AcpiFormatException(i)); 365125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 366125048Sjhb panic("Using MADT but ACPI doesn't work"); 367125048Sjhb } 368125048Sjhb 369121992Sjhb /* First, we run through adding I/O APIC's. */ 370121992Sjhb madt_walk_table(madt_parse_apics, NULL); 371121992Sjhb 372121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 373121992Sjhb madt_walk_table(madt_parse_ints, NULL); 374121992Sjhb 375128930Sjhb /* 376128930Sjhb * If there was not an explicit override entry for the SCI, 377128930Sjhb * force it to use level trigger and active-low polarity. 378128930Sjhb */ 379128930Sjhb if (!madt_found_sci_override) { 380167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 381167814Sjkim &pin) != 0) 382167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 383167814Sjkim AcpiGbl_FADT.SciInterrupt); 384128930Sjhb else { 385128930Sjhb printf( 386128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 387128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 388128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 389128930Sjhb } 390128930Sjhb } 391128930Sjhb 392121992Sjhb /* Third, we register all the I/O APIC's. */ 393169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) 394121992Sjhb if (ioapics[i].io_apic != NULL) 395121992Sjhb ioapic_register(ioapics[i].io_apic); 396121992Sjhb 397121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 398121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 399121992Sjhb 400121992Sjhb return (0); 401121992Sjhb} 402121992Sjhb 403121992Sjhbstatic void 404121992Sjhbmadt_register(void *dummy __unused) 405121992Sjhb{ 406121992Sjhb 407121992Sjhb apic_register_enumerator(&madt_enumerator); 408121992Sjhb} 409123133SjhbSYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL) 410121992Sjhb 411121992Sjhb/* 412121992Sjhb * Call the handler routine for each entry in the MADT table. 413121992Sjhb */ 414121992Sjhbstatic void 415121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg) 416121992Sjhb{ 417167814Sjkim ACPI_SUBTABLE_HEADER *entry; 418121992Sjhb u_char *p, *end; 419121992Sjhb 420167814Sjkim end = (u_char *)(madt) + madt->Header.Length; 421121992Sjhb for (p = (u_char *)(madt + 1); p < end; ) { 422167814Sjkim entry = (ACPI_SUBTABLE_HEADER *)p; 423121992Sjhb handler(entry, arg); 424121992Sjhb p += entry->Length; 425121992Sjhb } 426121992Sjhb} 427121992Sjhb 428121992Sjhbstatic void 429167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 430121992Sjhb{ 431167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 432121992Sjhb struct lapic_info *la; 433121992Sjhb 434121992Sjhb switch (entry->Type) { 435167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 436121992Sjhb /* 437121992Sjhb * The MADT does not include a BSP flag, so we have to 438121992Sjhb * let the MP code figure out which CPU is the BSP on 439121992Sjhb * its own. 440121992Sjhb */ 441167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 442121992Sjhb if (bootverbose) 443167814Sjkim printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 444167814Sjkim proc->Id, proc->ProcessorId, 445167814Sjkim (proc->LapicFlags & ACPI_MADT_ENABLED) ? 446167814Sjkim "enabled" : "disabled"); 447167814Sjkim if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 448130310Sjhb break; 449169395Sjhb if (proc->Id > MAX_APIC_ID) 450167814Sjkim panic("%s: CPU ID %u too high", __func__, proc->Id); 451167814Sjkim la = &lapics[proc->Id]; 452130310Sjhb KASSERT(la->la_enabled == 0, 453167814Sjkim ("Duplicate local APIC ID %u", proc->Id)); 454130310Sjhb la->la_enabled = 1; 455129960Sjhb la->la_acpi_id = proc->ProcessorId; 456167814Sjkim lapic_create(proc->Id, 0); 457121992Sjhb break; 458121992Sjhb } 459121992Sjhb} 460121992Sjhb 461121992Sjhb 462121992Sjhb/* 463121992Sjhb * Add an I/O APIC from an entry in the table. 464121992Sjhb */ 465121992Sjhbstatic void 466167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 467121992Sjhb{ 468167814Sjkim ACPI_MADT_IO_APIC *apic; 469121992Sjhb 470121992Sjhb switch (entry->Type) { 471167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 472167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 473121992Sjhb if (bootverbose) 474167814Sjkim printf( 475167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 476167814Sjkim apic->Id, apic->GlobalIrqBase, 477123326Snjl (void *)(uintptr_t)apic->Address); 478169395Sjhb if (apic->Id > MAX_APIC_ID) 479167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 480167814Sjkim apic->Id); 481167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 482167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 483167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 484167814Sjkim apic->Id, apic->GlobalIrqBase); 485167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 486121992Sjhb break; 487121992Sjhb default: 488121992Sjhb break; 489121992Sjhb } 490121992Sjhb} 491121992Sjhb 492121992Sjhb/* 493129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 494129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 495128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 496129128Sjhb * SCI for which we use Active Lo, Level Triggered. 497121992Sjhb */ 498128930Sjhbstatic enum intr_polarity 499167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 500121992Sjhb{ 501121992Sjhb 502167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 503167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 504167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 505128930Sjhb return (INTR_POLARITY_LOW); 506128930Sjhb else 507128930Sjhb return (INTR_POLARITY_HIGH); 508167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 509128930Sjhb return (INTR_POLARITY_HIGH); 510167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 511128930Sjhb return (INTR_POLARITY_LOW); 512121992Sjhb default: 513121992Sjhb panic("Bogus Interrupt Polarity"); 514121992Sjhb } 515121992Sjhb} 516121992Sjhb 517128930Sjhbstatic enum intr_trigger 518167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 519121992Sjhb{ 520121992Sjhb 521167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 522167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 523167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 524128930Sjhb return (INTR_TRIGGER_LEVEL); 525128930Sjhb else 526128930Sjhb return (INTR_TRIGGER_EDGE); 527167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 528128930Sjhb return (INTR_TRIGGER_EDGE); 529167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 530128930Sjhb return (INTR_TRIGGER_LEVEL); 531121992Sjhb default: 532121992Sjhb panic("Bogus Interrupt Trigger Mode"); 533121992Sjhb } 534121992Sjhb} 535121992Sjhb 536121992Sjhb/* 537121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 538121992Sjhb */ 539121992Sjhbstatic int 540121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 541121992Sjhb{ 542129960Sjhb int i; 543121992Sjhb 544169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 545130310Sjhb if (!lapics[i].la_enabled) 546129960Sjhb continue; 547129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 548129960Sjhb continue; 549129960Sjhb *apic_id = i; 550130310Sjhb return (0); 551129960Sjhb } 552129960Sjhb return (ENOENT); 553121992Sjhb} 554121992Sjhb 555121992Sjhb/* 556121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 557121992Sjhb * interrupt. 558121992Sjhb */ 559121992Sjhbstatic int 560121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 561121992Sjhb{ 562121992Sjhb int i, best; 563121992Sjhb 564121992Sjhb best = -1; 565169395Sjhb for (i = 0; i <= MAX_APIC_ID; i++) { 566121992Sjhb if (ioapics[i].io_apic == NULL || 567121992Sjhb ioapics[i].io_vector > intr) 568121992Sjhb continue; 569121992Sjhb if (best == -1 || 570121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 571121992Sjhb best = i; 572121992Sjhb } 573121992Sjhb if (best == -1) 574121992Sjhb return (ENOENT); 575121992Sjhb *apic = ioapics[best].io_apic; 576121992Sjhb *pin = intr - ioapics[best].io_vector; 577121992Sjhb if (*pin > 32) 578121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 579121992Sjhb intr); 580121992Sjhb return (0); 581121992Sjhb} 582121992Sjhb 583121992Sjhb/* 584121992Sjhb * Parse an interrupt source override for an ISA interrupt. 585121992Sjhb */ 586121992Sjhbstatic void 587167814Sjkimmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 588121992Sjhb{ 589122149Sjhb void *new_ioapic, *old_ioapic; 590122149Sjhb u_int new_pin, old_pin; 591128930Sjhb enum intr_trigger trig; 592128930Sjhb enum intr_polarity pol; 593128930Sjhb char buf[64]; 594121992Sjhb 595167814Sjkim if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 596167814Sjkim intr->GlobalIrq == 2) { 597142257Sjhb if (bootverbose) 598142257Sjhb printf("MADT: Skipping timer override\n"); 599142257Sjhb return; 600142257Sjhb } 601121992Sjhb if (bootverbose) 602142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 603167814Sjkim intr->SourceIrq, intr->GlobalIrq); 604121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 605167814Sjkim if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 606167814Sjkim printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 607167814Sjkim intr->GlobalIrq, intr->SourceIrq); 608121992Sjhb return; 609121992Sjhb } 610121992Sjhb 611125048Sjhb /* 612128930Sjhb * Lookup the appropriate trigger and polarity modes for this 613128930Sjhb * entry. 614128930Sjhb */ 615167814Sjkim trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 616167814Sjkim pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 617128930Sjhb 618128930Sjhb /* 619125048Sjhb * If the SCI is identity mapped but has edge trigger and 620128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 621128329Sjhb * force it to use level/lo. 622125048Sjhb */ 623167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 624128930Sjhb madt_found_sci_override = 1; 625128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 626128930Sjhb if (tolower(buf[0]) == 'e') 627128930Sjhb trig = INTR_TRIGGER_EDGE; 628128930Sjhb else if (tolower(buf[0]) == 'l') 629128930Sjhb trig = INTR_TRIGGER_LEVEL; 630128930Sjhb else 631128930Sjhb panic( 632128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 633128930Sjhb buf); 634128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 635128930Sjhb trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 636128930Sjhb } 637128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 638128930Sjhb if (tolower(buf[0]) == 'h') 639128930Sjhb pol = INTR_POLARITY_HIGH; 640128930Sjhb else if (tolower(buf[0]) == 'l') 641128930Sjhb pol = INTR_POLARITY_LOW; 642128930Sjhb else 643128930Sjhb panic( 644128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 645128930Sjhb buf); 646128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 647128930Sjhb pol == INTR_POLARITY_HIGH ? "high" : "low"); 648128930Sjhb } 649128930Sjhb } 650125048Sjhb 651128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 652167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 653125048Sjhb /* 654125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 655125048Sjhb * then override the vector we use to setup and allocate 656125048Sjhb * the interrupt. 657125048Sjhb */ 658167814Sjkim if (intr->GlobalIrq > 15 && 659167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 660167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 661122502Sjhb else 662167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 663167814Sjkim intr->SourceIrq); 664167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 665122149Sjhb &old_pin) != 0) 666167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 667167814Sjkim intr->SourceIrq); 668122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 669167814Sjkim intr->SourceIrq) 670122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 671122149Sjhb } 672128930Sjhb 673128930Sjhb /* Program the polarity and trigger mode. */ 674128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 675128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 676121992Sjhb} 677121992Sjhb 678121992Sjhb/* 679121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 680121992Sjhb */ 681121992Sjhbstatic void 682167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 683121992Sjhb{ 684121992Sjhb void *ioapic; 685121992Sjhb u_int pin; 686121992Sjhb 687167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 688167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 689167814Sjkim nmi->GlobalIrq); 690121992Sjhb return; 691121992Sjhb } 692121992Sjhb 693121992Sjhb ioapic_set_nmi(ioapic, pin); 694167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 695121992Sjhb ioapic_set_triggermode(ioapic, pin, 696167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 697167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 698121992Sjhb ioapic_set_polarity(ioapic, pin, 699167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 700121992Sjhb} 701121992Sjhb 702121992Sjhb/* 703121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 704121992Sjhb */ 705121992Sjhbstatic void 706167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 707121992Sjhb{ 708121992Sjhb u_int apic_id, pin; 709121992Sjhb 710123326Snjl if (nmi->ProcessorId == 0xff) 711121992Sjhb apic_id = APIC_ID_ALL; 712123326Snjl else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 713121992Sjhb if (bootverbose) 714167814Sjkim printf("MADT: Ignoring local NMI routed to " 715167814Sjkim "ACPI CPU %u\n", nmi->ProcessorId); 716121992Sjhb return; 717121992Sjhb } 718123326Snjl if (nmi->Lint == 0) 719121992Sjhb pin = LVT_LINT0; 720121992Sjhb else 721121992Sjhb pin = LVT_LINT1; 722121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 723167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 724121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 725167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 726167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 727121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 728167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 729121992Sjhb} 730121992Sjhb 731121992Sjhb/* 732121992Sjhb * Parse interrupt entries. 733121992Sjhb */ 734121992Sjhbstatic void 735167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 736121992Sjhb{ 737121992Sjhb 738121992Sjhb switch (entry->Type) { 739167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 740121992Sjhb madt_parse_interrupt_override( 741167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 742121992Sjhb break; 743167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 744167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 745121992Sjhb break; 746167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 747167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 748121992Sjhb break; 749121992Sjhb } 750121992Sjhb} 751121992Sjhb 752121992Sjhb/* 753121992Sjhb * Setup per-CPU ACPI IDs. 754121992Sjhb */ 755121992Sjhbstatic void 756121992Sjhbmadt_set_ids(void *dummy) 757121992Sjhb{ 758129960Sjhb struct lapic_info *la; 759121992Sjhb struct pcpu *pc; 760129960Sjhb u_int i; 761121992Sjhb 762121992Sjhb if (madt == NULL) 763121992Sjhb return; 764123133Sjhb for (i = 0; i <= mp_maxid; i++) { 765121992Sjhb if (CPU_ABSENT(i)) 766121992Sjhb continue; 767121992Sjhb pc = pcpu_find(i); 768167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 769129960Sjhb la = &lapics[pc->pc_apic_id]; 770130310Sjhb if (!la->la_enabled) 771129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 772129960Sjhb pc->pc_apic_id); 773129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 774129960Sjhb if (bootverbose) 775129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 776129960Sjhb la->la_acpi_id); 777121992Sjhb } 778121992Sjhb} 779121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 780