madt.c revision 167814
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 167814 2007-03-22 18:16:43Z jkim $"); 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 56122434Sjhb#define NIOAPICS 32 /* Max number of I/O APICs */ 57122434Sjhb#define NLAPICS 32 /* Max number of local APICs */ 58121992Sjhb 59167814Sjkimtypedef void madt_entry_handler(ACPI_SUBTABLE_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_enabled:1; 69129960Sjhb u_int la_acpi_id:8; 70129960Sjhb} lapics[NLAPICS]; 71121992Sjhb 72128930Sjhbstatic int madt_found_sci_override; 73167814Sjkimstatic ACPI_TABLE_MADT *madt; 74121992Sjhbstatic vm_paddr_t madt_physaddr; 75121992Sjhbstatic vm_offset_t madt_length; 76121992Sjhb 77151897SrwatsonMALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items"); 78121992Sjhb 79167814Sjkimstatic enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source); 80167814Sjkimstatic enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source); 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); 85167814Sjkimstatic void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg); 86167814Sjkimstatic void madt_parse_interrupt_override( 87167814Sjkim ACPI_MADT_INTERRUPT_OVERRIDE *intr); 88167814Sjkimstatic void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, 89167814Sjkim void *arg __unused); 90167814Sjkimstatic void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi); 91167814Sjkimstatic void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi); 92121992Sjhbstatic int madt_probe(void); 93121992Sjhbstatic int madt_probe_cpus(void); 94167814Sjkimstatic void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, 95167814Sjkim void *arg __unused); 96121992Sjhbstatic int madt_probe_table(vm_paddr_t address); 97121992Sjhbstatic void madt_register(void *dummy); 98121992Sjhbstatic int madt_setup_local(void); 99121992Sjhbstatic int madt_setup_io(void); 100121992Sjhbstatic void madt_unmap(void *data, vm_offset_t length); 101121992Sjhbstatic void madt_unmap_table(void *table); 102121992Sjhbstatic void madt_walk_table(madt_entry_handler *handler, void *arg); 103121992Sjhb 104121992Sjhbstatic struct apic_enumerator madt_enumerator = { 105121992Sjhb "MADT", 106121992Sjhb madt_probe, 107121992Sjhb madt_probe_cpus, 108121992Sjhb madt_setup_local, 109121992Sjhb madt_setup_io 110121992Sjhb}; 111121992Sjhb 112121992Sjhb/* 113121992Sjhb * Code to abuse the crashdump map to map in the tables for the early 114121992Sjhb * probe. We cheat and make the following assumptions about how we 115121992Sjhb * use this KVA: page 0 is used to map in the first page of each table 116121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the 117121992Sjhb * RSDT or XSDT. The offset is in pages; the length is in bytes. 118121992Sjhb */ 119121992Sjhbstatic void * 120121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length) 121121992Sjhb{ 122121992Sjhb vm_offset_t va, off; 123121992Sjhb void *data; 124121992Sjhb 125121992Sjhb off = pa & PAGE_MASK; 126121992Sjhb length = roundup(length + off, PAGE_SIZE); 127121992Sjhb pa = pa & PG_FRAME; 128121992Sjhb va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 129121992Sjhb (offset * PAGE_SIZE); 130121992Sjhb data = (void *)(va + off); 131121992Sjhb length -= PAGE_SIZE; 132121992Sjhb while (length > 0) { 133121992Sjhb va += PAGE_SIZE; 134121992Sjhb pa += PAGE_SIZE; 135121992Sjhb length -= PAGE_SIZE; 136121992Sjhb pmap_kenter(va, pa); 137121992Sjhb invlpg(va); 138121992Sjhb } 139121992Sjhb return (data); 140121992Sjhb} 141121992Sjhb 142121992Sjhbstatic void 143121992Sjhbmadt_unmap(void *data, vm_offset_t length) 144121992Sjhb{ 145121992Sjhb vm_offset_t va, off; 146121992Sjhb 147121992Sjhb va = (vm_offset_t)data; 148121992Sjhb off = va & PAGE_MASK; 149121992Sjhb length = roundup(length + off, PAGE_SIZE); 150121992Sjhb va &= ~PAGE_MASK; 151121992Sjhb while (length > 0) { 152121992Sjhb pmap_kremove(va); 153121992Sjhb invlpg(va); 154121992Sjhb va += PAGE_SIZE; 155121992Sjhb length -= PAGE_SIZE; 156121992Sjhb } 157121992Sjhb} 158121992Sjhb 159121992Sjhbstatic void * 160121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig) 161121992Sjhb{ 162121992Sjhb ACPI_TABLE_HEADER *header; 163121992Sjhb vm_offset_t length; 164129094Sjhb void *table; 165121992Sjhb 166121992Sjhb header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 167167814Sjkim if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) { 168121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 169121992Sjhb return (NULL); 170121992Sjhb } 171121992Sjhb length = header->Length; 172121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 173129094Sjhb table = madt_map(pa, offset, length); 174167814Sjkim if (ACPI_FAILURE(AcpiTbChecksum(table, length))) { 175129094Sjhb if (bootverbose) 176129094Sjhb printf("MADT: Failed checksum for table %s\n", sig); 177129094Sjhb madt_unmap(table, length); 178129094Sjhb return (NULL); 179129094Sjhb } 180129094Sjhb return (table); 181121992Sjhb} 182121992Sjhb 183121992Sjhbstatic void 184121992Sjhbmadt_unmap_table(void *table) 185121992Sjhb{ 186121992Sjhb ACPI_TABLE_HEADER *header; 187121992Sjhb 188121992Sjhb header = (ACPI_TABLE_HEADER *)table; 189121992Sjhb madt_unmap(table, header->Length); 190121992Sjhb} 191121992Sjhb 192121992Sjhb/* 193121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 194121992Sjhb */ 195121992Sjhbstatic int 196121992Sjhbmadt_probe(void) 197121992Sjhb{ 198167814Sjkim ACPI_PHYSICAL_ADDRESS rsdp_ptr; 199167814Sjkim ACPI_TABLE_RSDP *rsdp; 200167814Sjkim ACPI_TABLE_RSDT *rsdt; 201167814Sjkim ACPI_TABLE_XSDT *xsdt; 202121992Sjhb int i, count; 203121992Sjhb 204121992Sjhb if (resource_disabled("acpi", 0)) 205121992Sjhb return (ENXIO); 206121992Sjhb 207121992Sjhb /* 208121992Sjhb * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 209161223Sjhb * calls pmap_mapbios() to find the RSDP, we assume that we can use 210161223Sjhb * pmap_mapbios() to map the RSDP. 211121992Sjhb */ 212167814Sjkim if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) 213121992Sjhb return (ENXIO); 214167814Sjkim rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP)); 215121992Sjhb if (rsdp == NULL) { 216121992Sjhb if (bootverbose) 217121992Sjhb printf("MADT: Failed to map RSDP\n"); 218121992Sjhb return (ENXIO); 219121992Sjhb } 220121992Sjhb 221121992Sjhb /* 222157179Sjhb * For ACPI >= 2.0, use the XSDT if it is available. 223157179Sjhb * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1 224157179Sjhb * in the crashdump area. Page 0 is used to map in the 225157179Sjhb * headers of candidate ACPI tables. 226121992Sjhb */ 227157179Sjhb if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { 228129094Sjhb /* 229129094Sjhb * AcpiOsGetRootPointer only verifies the checksum for 230129094Sjhb * the version 1.0 portion of the RSDP. Version 2.0 has 231129094Sjhb * an additional checksum that we verify first. 232129094Sjhb */ 233167814Sjkim if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) { 234129094Sjhb if (bootverbose) 235129094Sjhb printf("MADT: RSDP failed extended checksum\n"); 236129094Sjhb return (ENXIO); 237129094Sjhb } 238167814Sjkim xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, 239167814Sjkim ACPI_SIG_XSDT); 240121992Sjhb if (xsdt == NULL) { 241121992Sjhb if (bootverbose) 242121992Sjhb printf("MADT: Failed to map XSDT\n"); 243121992Sjhb return (ENXIO); 244121992Sjhb } 245167814Sjkim count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 246121992Sjhb sizeof(UINT64); 247121992Sjhb for (i = 0; i < count; i++) 248121992Sjhb if (madt_probe_table(xsdt->TableOffsetEntry[i])) 249121992Sjhb break; 250121992Sjhb madt_unmap_table(xsdt); 251121992Sjhb } else { 252167814Sjkim rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, 253167814Sjkim ACPI_SIG_RSDT); 254121992Sjhb if (rsdt == NULL) { 255121992Sjhb if (bootverbose) 256121992Sjhb printf("MADT: Failed to map RSDT\n"); 257121992Sjhb return (ENXIO); 258121992Sjhb } 259167814Sjkim count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) / 260121992Sjhb sizeof(UINT32); 261121992Sjhb for (i = 0; i < count; i++) 262121992Sjhb if (madt_probe_table(rsdt->TableOffsetEntry[i])) 263121992Sjhb break; 264121992Sjhb madt_unmap_table(rsdt); 265121992Sjhb } 266167814Sjkim pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP)); 267121992Sjhb if (madt_physaddr == 0) { 268121992Sjhb if (bootverbose) 269121992Sjhb printf("MADT: No MADT table found\n"); 270121992Sjhb return (ENXIO); 271121992Sjhb } 272121992Sjhb if (bootverbose) 273122016Speter printf("MADT: Found table at 0x%jx\n", 274122016Speter (uintmax_t)madt_physaddr); 275121992Sjhb 276129094Sjhb /* 277129094Sjhb * Verify that we can map the full table and that its checksum is 278129094Sjhb * correct, etc. 279129094Sjhb */ 280167814Sjkim madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); 281129094Sjhb if (madt == NULL) 282129094Sjhb return (ENXIO); 283129094Sjhb madt_unmap_table(madt); 284129094Sjhb madt = NULL; 285129094Sjhb 286121992Sjhb return (0); 287121992Sjhb} 288121992Sjhb 289121992Sjhb/* 290121992Sjhb * See if a given ACPI table is the MADT. 291121992Sjhb */ 292121992Sjhbstatic int 293121992Sjhbmadt_probe_table(vm_paddr_t address) 294121992Sjhb{ 295121992Sjhb ACPI_TABLE_HEADER *table; 296121992Sjhb 297121992Sjhb table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 298121992Sjhb if (table == NULL) { 299121992Sjhb if (bootverbose) 300122016Speter printf("MADT: Failed to map table at 0x%jx\n", 301122016Speter (uintmax_t)address); 302121992Sjhb return (0); 303121992Sjhb } 304121992Sjhb if (bootverbose) 305122016Speter printf("Table '%.4s' at 0x%jx\n", table->Signature, 306122016Speter (uintmax_t)address); 307121992Sjhb 308167814Sjkim if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) { 309121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 310121992Sjhb return (0); 311121992Sjhb } 312121992Sjhb madt_physaddr = address; 313121992Sjhb madt_length = table->Length; 314121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 315121992Sjhb return (1); 316121992Sjhb} 317121992Sjhb 318121992Sjhb/* 319121992Sjhb * Run through the MP table enumerating CPUs. 320121992Sjhb */ 321121992Sjhbstatic int 322121992Sjhbmadt_probe_cpus(void) 323121992Sjhb{ 324121992Sjhb 325167814Sjkim madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT); 326121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 327121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 328121992Sjhb madt_unmap_table(madt); 329121992Sjhb madt = NULL; 330121992Sjhb return (0); 331121992Sjhb} 332121992Sjhb 333121992Sjhb/* 334121992Sjhb * Initialize the local APIC on the BSP. 335121992Sjhb */ 336121992Sjhbstatic int 337121992Sjhbmadt_setup_local(void) 338121992Sjhb{ 339121992Sjhb 340161223Sjhb madt = pmap_mapbios(madt_physaddr, madt_length); 341167814Sjkim lapic_init(madt->Address); 342121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 343167814Sjkim (int)sizeof(madt->Header.OemId), madt->Header.OemId, 344167814Sjkim (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId); 345121992Sjhb 346121992Sjhb /* 347121992Sjhb * We ignore 64-bit local APIC override entries. Should we 348121992Sjhb * perhaps emit a warning here if we find one? 349121992Sjhb */ 350121992Sjhb return (0); 351121992Sjhb} 352121992Sjhb 353121992Sjhb/* 354125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 355121992Sjhb */ 356121992Sjhbstatic int 357121992Sjhbmadt_setup_io(void) 358121992Sjhb{ 359128930Sjhb void *ioapic; 360128930Sjhb u_int pin; 361121992Sjhb int i; 362121992Sjhb 363125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 364125048Sjhb i = acpi_Startup(); 365125048Sjhb if (ACPI_FAILURE(i)) { 366125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 367125048Sjhb AcpiFormatException(i)); 368125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 369125048Sjhb panic("Using MADT but ACPI doesn't work"); 370125048Sjhb } 371125048Sjhb 372121992Sjhb /* First, we run through adding I/O APIC's. */ 373121992Sjhb madt_walk_table(madt_parse_apics, NULL); 374121992Sjhb 375121992Sjhb /* Second, we run through the table tweaking interrupt sources. */ 376121992Sjhb madt_walk_table(madt_parse_ints, NULL); 377121992Sjhb 378128930Sjhb /* 379128930Sjhb * If there was not an explicit override entry for the SCI, 380128930Sjhb * force it to use level trigger and active-low polarity. 381128930Sjhb */ 382128930Sjhb if (!madt_found_sci_override) { 383167814Sjkim if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic, 384167814Sjkim &pin) != 0) 385167814Sjkim printf("MADT: Could not find APIC for SCI IRQ %u\n", 386167814Sjkim AcpiGbl_FADT.SciInterrupt); 387128930Sjhb else { 388128930Sjhb printf( 389128930Sjhb "MADT: Forcing active-low polarity and level trigger for SCI\n"); 390128930Sjhb ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW); 391128930Sjhb ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL); 392128930Sjhb } 393128930Sjhb } 394128930Sjhb 395121992Sjhb /* Third, we register all the I/O APIC's. */ 396121992Sjhb for (i = 0; i < NIOAPICS; i++) 397121992Sjhb if (ioapics[i].io_apic != NULL) 398121992Sjhb ioapic_register(ioapics[i].io_apic); 399121992Sjhb 400121992Sjhb /* Finally, we throw the switch to enable the I/O APIC's. */ 401121992Sjhb acpi_SetDefaultIntrModel(ACPI_INTR_APIC); 402121992Sjhb 403121992Sjhb return (0); 404121992Sjhb} 405121992Sjhb 406121992Sjhbstatic void 407121992Sjhbmadt_register(void *dummy __unused) 408121992Sjhb{ 409121992Sjhb 410121992Sjhb apic_register_enumerator(&madt_enumerator); 411121992Sjhb} 412123133SjhbSYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL) 413121992Sjhb 414121992Sjhb/* 415121992Sjhb * Call the handler routine for each entry in the MADT table. 416121992Sjhb */ 417121992Sjhbstatic void 418121992Sjhbmadt_walk_table(madt_entry_handler *handler, void *arg) 419121992Sjhb{ 420167814Sjkim ACPI_SUBTABLE_HEADER *entry; 421121992Sjhb u_char *p, *end; 422121992Sjhb 423167814Sjkim end = (u_char *)(madt) + madt->Header.Length; 424121992Sjhb for (p = (u_char *)(madt + 1); p < end; ) { 425167814Sjkim entry = (ACPI_SUBTABLE_HEADER *)p; 426121992Sjhb handler(entry, arg); 427121992Sjhb p += entry->Length; 428121992Sjhb } 429121992Sjhb} 430121992Sjhb 431121992Sjhbstatic void 432167814Sjkimmadt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) 433121992Sjhb{ 434167814Sjkim ACPI_MADT_LOCAL_APIC *proc; 435121992Sjhb struct lapic_info *la; 436121992Sjhb 437121992Sjhb switch (entry->Type) { 438167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC: 439121992Sjhb /* 440121992Sjhb * The MADT does not include a BSP flag, so we have to 441121992Sjhb * let the MP code figure out which CPU is the BSP on 442121992Sjhb * its own. 443121992Sjhb */ 444167814Sjkim proc = (ACPI_MADT_LOCAL_APIC *)entry; 445121992Sjhb if (bootverbose) 446167814Sjkim printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n", 447167814Sjkim proc->Id, proc->ProcessorId, 448167814Sjkim (proc->LapicFlags & ACPI_MADT_ENABLED) ? 449167814Sjkim "enabled" : "disabled"); 450167814Sjkim if (!(proc->LapicFlags & ACPI_MADT_ENABLED)) 451130310Sjhb break; 452167814Sjkim if (proc->Id >= NLAPICS) 453167814Sjkim panic("%s: CPU ID %u too high", __func__, proc->Id); 454167814Sjkim la = &lapics[proc->Id]; 455130310Sjhb KASSERT(la->la_enabled == 0, 456167814Sjkim ("Duplicate local APIC ID %u", proc->Id)); 457130310Sjhb la->la_enabled = 1; 458129960Sjhb la->la_acpi_id = proc->ProcessorId; 459167814Sjkim lapic_create(proc->Id, 0); 460121992Sjhb break; 461121992Sjhb } 462121992Sjhb} 463121992Sjhb 464121992Sjhb 465121992Sjhb/* 466121992Sjhb * Add an I/O APIC from an entry in the table. 467121992Sjhb */ 468121992Sjhbstatic void 469167814Sjkimmadt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 470121992Sjhb{ 471167814Sjkim ACPI_MADT_IO_APIC *apic; 472121992Sjhb 473121992Sjhb switch (entry->Type) { 474167814Sjkim case ACPI_MADT_TYPE_IO_APIC: 475167814Sjkim apic = (ACPI_MADT_IO_APIC *)entry; 476121992Sjhb if (bootverbose) 477167814Sjkim printf( 478167814Sjkim "MADT: Found IO APIC ID %u, Interrupt %u at %p\n", 479167814Sjkim apic->Id, apic->GlobalIrqBase, 480123326Snjl (void *)(uintptr_t)apic->Address); 481167814Sjkim if (apic->Id >= NIOAPICS) 482167814Sjkim panic("%s: I/O APIC ID %u too high", __func__, 483167814Sjkim apic->Id); 484167814Sjkim if (ioapics[apic->Id].io_apic != NULL) 485167814Sjkim panic("%s: Double APIC ID %u", __func__, apic->Id); 486167814Sjkim ioapics[apic->Id].io_apic = ioapic_create(apic->Address, 487167814Sjkim apic->Id, apic->GlobalIrqBase); 488167814Sjkim ioapics[apic->Id].io_vector = apic->GlobalIrqBase; 489121992Sjhb break; 490121992Sjhb default: 491121992Sjhb break; 492121992Sjhb } 493121992Sjhb} 494121992Sjhb 495121992Sjhb/* 496129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 497129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 498128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 499129128Sjhb * SCI for which we use Active Lo, Level Triggered. 500121992Sjhb */ 501128930Sjhbstatic enum intr_polarity 502167814Sjkiminterrupt_polarity(UINT16 IntiFlags, UINT8 Source) 503121992Sjhb{ 504121992Sjhb 505167814Sjkim switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { 506167814Sjkim case ACPI_MADT_POLARITY_CONFORMS: 507167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 508128930Sjhb return (INTR_POLARITY_LOW); 509128930Sjhb else 510128930Sjhb return (INTR_POLARITY_HIGH); 511167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_HIGH: 512128930Sjhb return (INTR_POLARITY_HIGH); 513167814Sjkim case ACPI_MADT_POLARITY_ACTIVE_LOW: 514128930Sjhb return (INTR_POLARITY_LOW); 515121992Sjhb default: 516121992Sjhb panic("Bogus Interrupt Polarity"); 517121992Sjhb } 518121992Sjhb} 519121992Sjhb 520128930Sjhbstatic enum intr_trigger 521167814Sjkiminterrupt_trigger(UINT16 IntiFlags, UINT8 Source) 522121992Sjhb{ 523121992Sjhb 524167814Sjkim switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { 525167814Sjkim case ACPI_MADT_TRIGGER_CONFORMS: 526167814Sjkim if (Source == AcpiGbl_FADT.SciInterrupt) 527128930Sjhb return (INTR_TRIGGER_LEVEL); 528128930Sjhb else 529128930Sjhb return (INTR_TRIGGER_EDGE); 530167814Sjkim case ACPI_MADT_TRIGGER_EDGE: 531128930Sjhb return (INTR_TRIGGER_EDGE); 532167814Sjkim case ACPI_MADT_TRIGGER_LEVEL: 533128930Sjhb return (INTR_TRIGGER_LEVEL); 534121992Sjhb default: 535121992Sjhb panic("Bogus Interrupt Trigger Mode"); 536121992Sjhb } 537121992Sjhb} 538121992Sjhb 539121992Sjhb/* 540121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 541121992Sjhb */ 542121992Sjhbstatic int 543121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 544121992Sjhb{ 545129960Sjhb int i; 546121992Sjhb 547129960Sjhb for (i = 0; i < NLAPICS; i++) { 548130310Sjhb if (!lapics[i].la_enabled) 549129960Sjhb continue; 550129960Sjhb if (lapics[i].la_acpi_id != acpi_id) 551129960Sjhb continue; 552129960Sjhb *apic_id = i; 553130310Sjhb return (0); 554129960Sjhb } 555129960Sjhb return (ENOENT); 556121992Sjhb} 557121992Sjhb 558121992Sjhb/* 559121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 560121992Sjhb * interrupt. 561121992Sjhb */ 562121992Sjhbstatic int 563121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 564121992Sjhb{ 565121992Sjhb int i, best; 566121992Sjhb 567121992Sjhb best = -1; 568121992Sjhb for (i = 0; i < NIOAPICS; i++) { 569121992Sjhb if (ioapics[i].io_apic == NULL || 570121992Sjhb ioapics[i].io_vector > intr) 571121992Sjhb continue; 572121992Sjhb if (best == -1 || 573121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 574121992Sjhb best = i; 575121992Sjhb } 576121992Sjhb if (best == -1) 577121992Sjhb return (ENOENT); 578121992Sjhb *apic = ioapics[best].io_apic; 579121992Sjhb *pin = intr - ioapics[best].io_vector; 580121992Sjhb if (*pin > 32) 581121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 582121992Sjhb intr); 583121992Sjhb return (0); 584121992Sjhb} 585121992Sjhb 586121992Sjhb/* 587121992Sjhb * Parse an interrupt source override for an ISA interrupt. 588121992Sjhb */ 589121992Sjhbstatic void 590167814Sjkimmadt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr) 591121992Sjhb{ 592122149Sjhb void *new_ioapic, *old_ioapic; 593122149Sjhb u_int new_pin, old_pin; 594128930Sjhb enum intr_trigger trig; 595128930Sjhb enum intr_polarity pol; 596128930Sjhb char buf[64]; 597121992Sjhb 598167814Sjkim if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 && 599167814Sjkim intr->GlobalIrq == 2) { 600142257Sjhb if (bootverbose) 601142257Sjhb printf("MADT: Skipping timer override\n"); 602142257Sjhb return; 603142257Sjhb } 604121992Sjhb if (bootverbose) 605142257Sjhb printf("MADT: Interrupt override: source %u, irq %u\n", 606167814Sjkim intr->SourceIrq, intr->GlobalIrq); 607121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 608167814Sjkim if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) { 609167814Sjkim printf("MADT: Could not find APIC for vector %u (IRQ %u)\n", 610167814Sjkim intr->GlobalIrq, intr->SourceIrq); 611121992Sjhb return; 612121992Sjhb } 613121992Sjhb 614125048Sjhb /* 615128930Sjhb * Lookup the appropriate trigger and polarity modes for this 616128930Sjhb * entry. 617128930Sjhb */ 618167814Sjkim trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq); 619167814Sjkim pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq); 620128930Sjhb 621128930Sjhb /* 622125048Sjhb * If the SCI is identity mapped but has edge trigger and 623128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 624128329Sjhb * force it to use level/lo. 625125048Sjhb */ 626167814Sjkim if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) { 627128930Sjhb madt_found_sci_override = 1; 628128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 629128930Sjhb if (tolower(buf[0]) == 'e') 630128930Sjhb trig = INTR_TRIGGER_EDGE; 631128930Sjhb else if (tolower(buf[0]) == 'l') 632128930Sjhb trig = INTR_TRIGGER_LEVEL; 633128930Sjhb else 634128930Sjhb panic( 635128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 636128930Sjhb buf); 637128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 638128930Sjhb trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 639128930Sjhb } 640128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 641128930Sjhb if (tolower(buf[0]) == 'h') 642128930Sjhb pol = INTR_POLARITY_HIGH; 643128930Sjhb else if (tolower(buf[0]) == 'l') 644128930Sjhb pol = INTR_POLARITY_LOW; 645128930Sjhb else 646128930Sjhb panic( 647128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 648128930Sjhb buf); 649128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 650128930Sjhb pol == INTR_POLARITY_HIGH ? "high" : "low"); 651128930Sjhb } 652128930Sjhb } 653125048Sjhb 654128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 655167814Sjkim if (intr->SourceIrq != intr->GlobalIrq) { 656125048Sjhb /* 657125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 658125048Sjhb * then override the vector we use to setup and allocate 659125048Sjhb * the interrupt. 660125048Sjhb */ 661167814Sjkim if (intr->GlobalIrq > 15 && 662167814Sjkim intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 663167814Sjkim acpi_OverrideInterruptLevel(intr->GlobalIrq); 664122502Sjhb else 665167814Sjkim ioapic_remap_vector(new_ioapic, new_pin, 666167814Sjkim intr->SourceIrq); 667167814Sjkim if (madt_find_interrupt(intr->SourceIrq, &old_ioapic, 668122149Sjhb &old_pin) != 0) 669167814Sjkim printf("MADT: Could not find APIC for source IRQ %u\n", 670167814Sjkim intr->SourceIrq); 671122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 672167814Sjkim intr->SourceIrq) 673122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 674122149Sjhb } 675128930Sjhb 676128930Sjhb /* Program the polarity and trigger mode. */ 677128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 678128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 679121992Sjhb} 680121992Sjhb 681121992Sjhb/* 682121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 683121992Sjhb */ 684121992Sjhbstatic void 685167814Sjkimmadt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi) 686121992Sjhb{ 687121992Sjhb void *ioapic; 688121992Sjhb u_int pin; 689121992Sjhb 690167814Sjkim if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) { 691167814Sjkim printf("MADT: Could not find APIC for vector %u\n", 692167814Sjkim nmi->GlobalIrq); 693121992Sjhb return; 694121992Sjhb } 695121992Sjhb 696121992Sjhb ioapic_set_nmi(ioapic, pin); 697167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 698121992Sjhb ioapic_set_triggermode(ioapic, pin, 699167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 700167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 701121992Sjhb ioapic_set_polarity(ioapic, pin, 702167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 703121992Sjhb} 704121992Sjhb 705121992Sjhb/* 706121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 707121992Sjhb */ 708121992Sjhbstatic void 709167814Sjkimmadt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi) 710121992Sjhb{ 711121992Sjhb u_int apic_id, pin; 712121992Sjhb 713123326Snjl if (nmi->ProcessorId == 0xff) 714121992Sjhb apic_id = APIC_ID_ALL; 715123326Snjl else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 716121992Sjhb if (bootverbose) 717167814Sjkim printf("MADT: Ignoring local NMI routed to " 718167814Sjkim "ACPI CPU %u\n", nmi->ProcessorId); 719121992Sjhb return; 720121992Sjhb } 721123326Snjl if (nmi->Lint == 0) 722121992Sjhb pin = LVT_LINT0; 723121992Sjhb else 724121992Sjhb pin = LVT_LINT1; 725121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 726167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS)) 727121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 728167814Sjkim interrupt_trigger(nmi->IntiFlags, 0)); 729167814Sjkim if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS)) 730121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 731167814Sjkim interrupt_polarity(nmi->IntiFlags, 0)); 732121992Sjhb} 733121992Sjhb 734121992Sjhb/* 735121992Sjhb * Parse interrupt entries. 736121992Sjhb */ 737121992Sjhbstatic void 738167814Sjkimmadt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused) 739121992Sjhb{ 740121992Sjhb 741121992Sjhb switch (entry->Type) { 742167814Sjkim case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 743121992Sjhb madt_parse_interrupt_override( 744167814Sjkim (ACPI_MADT_INTERRUPT_OVERRIDE *)entry); 745121992Sjhb break; 746167814Sjkim case ACPI_MADT_TYPE_NMI_SOURCE: 747167814Sjkim madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry); 748121992Sjhb break; 749167814Sjkim case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 750167814Sjkim madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry); 751121992Sjhb break; 752121992Sjhb } 753121992Sjhb} 754121992Sjhb 755121992Sjhb/* 756121992Sjhb * Setup per-CPU ACPI IDs. 757121992Sjhb */ 758121992Sjhbstatic void 759121992Sjhbmadt_set_ids(void *dummy) 760121992Sjhb{ 761129960Sjhb struct lapic_info *la; 762121992Sjhb struct pcpu *pc; 763129960Sjhb u_int i; 764121992Sjhb 765121992Sjhb if (madt == NULL) 766121992Sjhb return; 767123133Sjhb for (i = 0; i <= mp_maxid; i++) { 768121992Sjhb if (CPU_ABSENT(i)) 769121992Sjhb continue; 770121992Sjhb pc = pcpu_find(i); 771167814Sjkim KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); 772129960Sjhb la = &lapics[pc->pc_apic_id]; 773130310Sjhb if (!la->la_enabled) 774129960Sjhb panic("APIC: CPU with APIC ID %u is not enabled", 775129960Sjhb pc->pc_apic_id); 776129960Sjhb pc->pc_acpi_id = la->la_acpi_id; 777129960Sjhb if (bootverbose) 778129960Sjhb printf("APIC: CPU %u has ACPI ID %u\n", i, 779129960Sjhb la->la_acpi_id); 780121992Sjhb } 781121992Sjhb} 782121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 783