madt.c revision 129128
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 129128 2004-05-11 20:06:32Z 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" 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 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 73128930Sjhbstatic int madt_found_sci_override; 74123326Snjlstatic MULTIPLE_APIC_TABLE *madt; 75121992Sjhbstatic vm_paddr_t madt_physaddr; 76121992Sjhbstatic vm_offset_t madt_length; 77121992Sjhb 78121992SjhbMALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items"); 79121992Sjhb 80128930Sjhbstatic enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source); 81128930Sjhbstatic enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source); 82121992Sjhbstatic int madt_find_cpu(u_int acpi_id, u_int *apic_id); 83121992Sjhbstatic int madt_find_interrupt(int intr, void **apic, u_int *pin); 84121992Sjhbstatic void *madt_map(vm_paddr_t pa, int offset, vm_offset_t length); 85121992Sjhbstatic void *madt_map_table(vm_paddr_t pa, int offset, const char *sig); 86121992Sjhbstatic void madt_parse_apics(APIC_HEADER *entry, void *arg); 87123326Snjlstatic void madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr); 88121992Sjhbstatic void madt_parse_ints(APIC_HEADER *entry, void *arg __unused); 89123326Snjlstatic void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi); 90123326Snjlstatic void madt_parse_nmi(MADT_NMI_SOURCE *nmi); 91121992Sjhbstatic int madt_probe(void); 92121992Sjhbstatic int madt_probe_cpus(void); 93121992Sjhbstatic void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused); 94121992Sjhbstatic int madt_probe_table(vm_paddr_t address); 95121992Sjhbstatic void madt_register(void *dummy); 96121992Sjhbstatic int madt_setup_local(void); 97121992Sjhbstatic int madt_setup_io(void); 98121992Sjhbstatic void madt_unmap(void *data, vm_offset_t length); 99121992Sjhbstatic void madt_unmap_table(void *table); 100121992Sjhbstatic void madt_walk_table(madt_entry_handler *handler, void *arg); 101121992Sjhb 102121992Sjhbstatic struct apic_enumerator madt_enumerator = { 103121992Sjhb "MADT", 104121992Sjhb madt_probe, 105121992Sjhb madt_probe_cpus, 106121992Sjhb madt_setup_local, 107121992Sjhb madt_setup_io 108121992Sjhb}; 109121992Sjhb 110121992Sjhb/* 111121992Sjhb * Code to abuse the crashdump map to map in the tables for the early 112121992Sjhb * probe. We cheat and make the following assumptions about how we 113121992Sjhb * use this KVA: page 0 is used to map in the first page of each table 114121992Sjhb * found via the RSDT or XSDT and pages 1 to n are used to map in the 115121992Sjhb * RSDT or XSDT. The offset is in pages; the length is in bytes. 116121992Sjhb */ 117121992Sjhbstatic void * 118121992Sjhbmadt_map(vm_paddr_t pa, int offset, vm_offset_t length) 119121992Sjhb{ 120121992Sjhb vm_offset_t va, off; 121121992Sjhb void *data; 122121992Sjhb 123121992Sjhb off = pa & PAGE_MASK; 124121992Sjhb length = roundup(length + off, PAGE_SIZE); 125121992Sjhb pa = pa & PG_FRAME; 126121992Sjhb va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + 127121992Sjhb (offset * PAGE_SIZE); 128121992Sjhb data = (void *)(va + off); 129121992Sjhb length -= PAGE_SIZE; 130121992Sjhb while (length > 0) { 131121992Sjhb va += PAGE_SIZE; 132121992Sjhb pa += PAGE_SIZE; 133121992Sjhb length -= PAGE_SIZE; 134121992Sjhb pmap_kenter(va, pa); 135121992Sjhb invlpg(va); 136121992Sjhb } 137121992Sjhb return (data); 138121992Sjhb} 139121992Sjhb 140121992Sjhbstatic void 141121992Sjhbmadt_unmap(void *data, vm_offset_t length) 142121992Sjhb{ 143121992Sjhb vm_offset_t va, off; 144121992Sjhb 145121992Sjhb va = (vm_offset_t)data; 146121992Sjhb off = va & PAGE_MASK; 147121992Sjhb length = roundup(length + off, PAGE_SIZE); 148121992Sjhb va &= ~PAGE_MASK; 149121992Sjhb while (length > 0) { 150121992Sjhb pmap_kremove(va); 151121992Sjhb invlpg(va); 152121992Sjhb va += PAGE_SIZE; 153121992Sjhb length -= PAGE_SIZE; 154121992Sjhb } 155121992Sjhb} 156121992Sjhb 157121992Sjhbstatic void * 158121992Sjhbmadt_map_table(vm_paddr_t pa, int offset, const char *sig) 159121992Sjhb{ 160121992Sjhb ACPI_TABLE_HEADER *header; 161121992Sjhb vm_offset_t length; 162129094Sjhb void *table; 163121992Sjhb 164121992Sjhb header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER)); 165121992Sjhb if (strncmp(header->Signature, sig, 4) != 0) { 166121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 167121992Sjhb return (NULL); 168121992Sjhb } 169121992Sjhb length = header->Length; 170121992Sjhb madt_unmap(header, sizeof(ACPI_TABLE_HEADER)); 171129094Sjhb table = madt_map(pa, offset, length); 172129094Sjhb if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) { 173129094Sjhb if (bootverbose) 174129094Sjhb printf("MADT: Failed checksum for table %s\n", sig); 175129094Sjhb madt_unmap(table, length); 176129094Sjhb return (NULL); 177129094Sjhb } 178129094Sjhb return (table); 179121992Sjhb} 180121992Sjhb 181121992Sjhbstatic void 182121992Sjhbmadt_unmap_table(void *table) 183121992Sjhb{ 184121992Sjhb ACPI_TABLE_HEADER *header; 185121992Sjhb 186121992Sjhb header = (ACPI_TABLE_HEADER *)table; 187121992Sjhb madt_unmap(table, header->Length); 188121992Sjhb} 189121992Sjhb 190121992Sjhb/* 191121992Sjhb * Look for an ACPI Multiple APIC Description Table ("APIC") 192121992Sjhb */ 193121992Sjhbstatic int 194121992Sjhbmadt_probe(void) 195121992Sjhb{ 196121992Sjhb ACPI_POINTER rsdp_ptr; 197121992Sjhb RSDP_DESCRIPTOR *rsdp; 198121992Sjhb RSDT_DESCRIPTOR *rsdt; 199121992Sjhb XSDT_DESCRIPTOR *xsdt; 200121992Sjhb int i, count; 201121992Sjhb 202121992Sjhb if (resource_disabled("acpi", 0)) 203121992Sjhb return (ENXIO); 204121992Sjhb 205121992Sjhb /* 206121992Sjhb * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn 207121992Sjhb * calls pmap_mapdev() to find the RSDP, we assume that we can use 208121992Sjhb * pmap_mapdev() to map the RSDP. 209121992Sjhb */ 210121992Sjhb if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 211121992Sjhb return (ENXIO); 212122712Speter#ifdef __i386__ 213121992Sjhb KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high")); 214122712Speter#endif 215121992Sjhb rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR)); 216121992Sjhb if (rsdp == NULL) { 217121992Sjhb if (bootverbose) 218121992Sjhb printf("MADT: Failed to map RSDP\n"); 219121992Sjhb return (ENXIO); 220121992Sjhb } 221121992Sjhb 222121992Sjhb /* 223121992Sjhb * For ACPI < 2.0, use the RSDT. For ACPI >= 2.0, use the XSDT. 224121992Sjhb * We map the XSDT and RSDT at page 1 in the crashdump area. 225121992Sjhb * Page 0 is used to map in the headers of candidate ACPI tables. 226121992Sjhb */ 227121992Sjhb if (rsdp->Revision >= 2) { 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 */ 233129094Sjhb if (AcpiTbChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) { 234129094Sjhb if (bootverbose) 235129094Sjhb printf("MADT: RSDP failed extended checksum\n"); 236129094Sjhb return (ENXIO); 237129094Sjhb } 238121992Sjhb xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG); 239121992Sjhb if (xsdt == NULL) { 240121992Sjhb if (bootverbose) 241121992Sjhb printf("MADT: Failed to map XSDT\n"); 242121992Sjhb return (ENXIO); 243121992Sjhb } 244123326Snjl count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 245121992Sjhb sizeof(UINT64); 246121992Sjhb for (i = 0; i < count; i++) 247121992Sjhb if (madt_probe_table(xsdt->TableOffsetEntry[i])) 248121992Sjhb break; 249121992Sjhb madt_unmap_table(xsdt); 250121992Sjhb } else { 251121992Sjhb rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG); 252121992Sjhb if (rsdt == NULL) { 253121992Sjhb if (bootverbose) 254121992Sjhb printf("MADT: Failed to map RSDT\n"); 255121992Sjhb return (ENXIO); 256121992Sjhb } 257123326Snjl count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) / 258121992Sjhb sizeof(UINT32); 259121992Sjhb for (i = 0; i < count; i++) 260121992Sjhb if (madt_probe_table(rsdt->TableOffsetEntry[i])) 261121992Sjhb break; 262121992Sjhb madt_unmap_table(rsdt); 263121992Sjhb } 264121992Sjhb pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR)); 265121992Sjhb if (madt_physaddr == 0) { 266121992Sjhb if (bootverbose) 267121992Sjhb printf("MADT: No MADT table found\n"); 268121992Sjhb return (ENXIO); 269121992Sjhb } 270121992Sjhb if (bootverbose) 271122016Speter printf("MADT: Found table at 0x%jx\n", 272122016Speter (uintmax_t)madt_physaddr); 273121992Sjhb 274129094Sjhb /* 275129094Sjhb * Verify that we can map the full table and that its checksum is 276129094Sjhb * correct, etc. 277129094Sjhb */ 278129094Sjhb madt = madt_map_table(madt_physaddr, 0, APIC_SIG); 279129094Sjhb if (madt == NULL) 280129094Sjhb return (ENXIO); 281129094Sjhb madt_unmap_table(madt); 282129094Sjhb madt = NULL; 283129094Sjhb 284121992Sjhb return (0); 285121992Sjhb} 286121992Sjhb 287121992Sjhb/* 288121992Sjhb * See if a given ACPI table is the MADT. 289121992Sjhb */ 290121992Sjhbstatic int 291121992Sjhbmadt_probe_table(vm_paddr_t address) 292121992Sjhb{ 293121992Sjhb ACPI_TABLE_HEADER *table; 294121992Sjhb 295121992Sjhb table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER)); 296121992Sjhb if (table == NULL) { 297121992Sjhb if (bootverbose) 298122016Speter printf("MADT: Failed to map table at 0x%jx\n", 299122016Speter (uintmax_t)address); 300121992Sjhb return (0); 301121992Sjhb } 302121992Sjhb if (bootverbose) 303122016Speter printf("Table '%.4s' at 0x%jx\n", table->Signature, 304122016Speter (uintmax_t)address); 305121992Sjhb 306121992Sjhb if (strncmp(table->Signature, APIC_SIG, 4) != 0) { 307121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 308121992Sjhb return (0); 309121992Sjhb } 310121992Sjhb madt_physaddr = address; 311121992Sjhb madt_length = table->Length; 312121992Sjhb madt_unmap(table, sizeof(ACPI_TABLE_HEADER)); 313121992Sjhb return (1); 314121992Sjhb} 315121992Sjhb 316121992Sjhb/* 317121992Sjhb * Run through the MP table enumerating CPUs. 318121992Sjhb */ 319121992Sjhbstatic int 320121992Sjhbmadt_probe_cpus(void) 321121992Sjhb{ 322121992Sjhb 323121992Sjhb madt = madt_map_table(madt_physaddr, 0, APIC_SIG); 324121992Sjhb KASSERT(madt != NULL, ("Unable to re-map MADT")); 325121992Sjhb madt_walk_table(madt_probe_cpus_handler, NULL); 326121992Sjhb madt_unmap_table(madt); 327121992Sjhb madt = NULL; 328121992Sjhb return (0); 329121992Sjhb} 330121992Sjhb 331121992Sjhb/* 332121992Sjhb * Initialize the local APIC on the BSP. 333121992Sjhb */ 334121992Sjhbstatic int 335121992Sjhbmadt_setup_local(void) 336121992Sjhb{ 337121992Sjhb 338121992Sjhb madt = pmap_mapdev(madt_physaddr, madt_length); 339121992Sjhb lapic_init((uintptr_t)madt->LocalApicAddress); 340121992Sjhb printf("ACPI APIC Table: <%.*s %.*s>\n", 341123326Snjl (int)sizeof(madt->OemId), madt->OemId, 342123326Snjl (int)sizeof(madt->OemTableId), madt->OemTableId); 343121992Sjhb 344121992Sjhb /* 345121992Sjhb * We ignore 64-bit local APIC override entries. Should we 346121992Sjhb * perhaps emit a warning here if we find one? 347121992Sjhb */ 348121992Sjhb return (0); 349121992Sjhb} 350121992Sjhb 351121992Sjhb/* 352125048Sjhb * Enumerate I/O APICs and setup interrupt sources. 353121992Sjhb */ 354121992Sjhbstatic int 355121992Sjhbmadt_setup_io(void) 356121992Sjhb{ 357128930Sjhb void *ioapic; 358128930Sjhb u_int pin; 359121992Sjhb int i; 360121992Sjhb 361125048Sjhb /* Try to initialize ACPI so that we can access the FADT. */ 362125048Sjhb i = acpi_Startup(); 363125048Sjhb if (ACPI_FAILURE(i)) { 364125048Sjhb printf("MADT: ACPI Startup failed with %s\n", 365125048Sjhb AcpiFormatException(i)); 366125048Sjhb printf("Try disabling either ACPI or apic support.\n"); 367125048Sjhb panic("Using MADT but ACPI doesn't work"); 368125048Sjhb } 369125048Sjhb 370121992Sjhb /* First, we run through adding I/O APIC's. */ 371129097Sjhb if (madt->PCATCompat) 372129097Sjhb ioapic_enable_mixed_mode(); 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) { 383128930Sjhb if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin) 384128930Sjhb != 0) 385128930Sjhb printf("MADT: Could not find APIC for SCI IRQ %d\n", 386128930Sjhb AcpiGbl_FADT->SciInt); 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{ 420121992Sjhb APIC_HEADER *entry; 421121992Sjhb u_char *p, *end; 422121992Sjhb 423123326Snjl end = (u_char *)(madt) + madt->Length; 424121992Sjhb for (p = (u_char *)(madt + 1); p < end; ) { 425121992Sjhb entry = (APIC_HEADER *)p; 426121992Sjhb handler(entry, arg); 427121992Sjhb p += entry->Length; 428121992Sjhb } 429121992Sjhb} 430121992Sjhb 431121992Sjhbstatic void 432121992Sjhbmadt_probe_cpus_handler(APIC_HEADER *entry, void *arg) 433121992Sjhb{ 434123326Snjl MADT_PROCESSOR_APIC *proc; 435121992Sjhb struct lapic_info *la; 436121992Sjhb 437121992Sjhb switch (entry->Type) { 438123326Snjl case APIC_PROCESSOR: 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 */ 444123326Snjl proc = (MADT_PROCESSOR_APIC *)entry; 445121992Sjhb if (bootverbose) 446121992Sjhb printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", 447123326Snjl proc->LocalApicId, proc->ProcessorId, 448121992Sjhb proc->ProcessorEnabled ? "enabled" : "disabled"); 449123326Snjl if (proc->ProcessorId > NLAPICS) 450121992Sjhb panic("%s: CPU ID %d too high", __func__, 451123326Snjl proc->ProcessorId); 452123326Snjl la = &lapics[proc->ProcessorId]; 453121992Sjhb KASSERT(la->la_present == 0, 454123326Snjl ("Duplicate local ACPI ID %d", proc->ProcessorId)); 455121992Sjhb la->la_present = 1; 456121992Sjhb la->la_apic_id = proc->LocalApicId; 457121992Sjhb if (proc->ProcessorEnabled) { 458121992Sjhb la->la_enabled = 1; 459121992Sjhb lapic_create(proc->LocalApicId, 0); 460121992Sjhb } 461121992Sjhb break; 462121992Sjhb } 463121992Sjhb} 464121992Sjhb 465121992Sjhb 466121992Sjhb/* 467121992Sjhb * Add an I/O APIC from an entry in the table. 468121992Sjhb */ 469121992Sjhbstatic void 470121992Sjhbmadt_parse_apics(APIC_HEADER *entry, void *arg __unused) 471121992Sjhb{ 472123326Snjl MADT_IO_APIC *apic; 473121992Sjhb 474121992Sjhb switch (entry->Type) { 475121992Sjhb case APIC_IO: 476123326Snjl apic = (MADT_IO_APIC *)entry; 477121992Sjhb if (bootverbose) 478123326Snjl printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n", 479123326Snjl apic->IoApicId, apic->Interrupt, 480123326Snjl (void *)(uintptr_t)apic->Address); 481121992Sjhb if (apic->IoApicId >= NIOAPICS) 482121992Sjhb panic("%s: I/O APIC ID %d too high", __func__, 483121992Sjhb apic->IoApicId); 484121992Sjhb if (ioapics[apic->IoApicId].io_apic != NULL) 485121992Sjhb panic("%s: Double APIC ID %d", __func__, 486121992Sjhb apic->IoApicId); 487121992Sjhb ioapics[apic->IoApicId].io_apic = ioapic_create( 488123326Snjl (uintptr_t)apic->Address, apic->IoApicId, 489123326Snjl apic->Interrupt); 490123326Snjl ioapics[apic->IoApicId].io_vector = apic->Interrupt; 491121992Sjhb break; 492121992Sjhb default: 493121992Sjhb break; 494121992Sjhb } 495121992Sjhb} 496121992Sjhb 497121992Sjhb/* 498129128Sjhb * Determine properties of an interrupt source. Note that for ACPI these 499129128Sjhb * functions are only used for ISA interrupts, so we assume ISA bus values 500128930Sjhb * (Active Hi, Edge Triggered) for conforming values except for the ACPI 501129128Sjhb * SCI for which we use Active Lo, Level Triggered. 502121992Sjhb */ 503128930Sjhbstatic enum intr_polarity 504128930Sjhbinterrupt_polarity(UINT16 Polarity, UINT8 Source) 505121992Sjhb{ 506121992Sjhb 507121992Sjhb switch (Polarity) { 508123326Snjl case POLARITY_CONFORMS: 509128930Sjhb if (Source == AcpiGbl_FADT->SciInt) 510128930Sjhb return (INTR_POLARITY_LOW); 511128930Sjhb else 512128930Sjhb return (INTR_POLARITY_HIGH); 513123326Snjl case POLARITY_ACTIVE_HIGH: 514128930Sjhb return (INTR_POLARITY_HIGH); 515123326Snjl case POLARITY_ACTIVE_LOW: 516128930Sjhb return (INTR_POLARITY_LOW); 517121992Sjhb default: 518121992Sjhb panic("Bogus Interrupt Polarity"); 519121992Sjhb } 520121992Sjhb} 521121992Sjhb 522128930Sjhbstatic enum intr_trigger 523128930Sjhbinterrupt_trigger(UINT16 TriggerMode, UINT8 Source) 524121992Sjhb{ 525121992Sjhb 526121992Sjhb switch (TriggerMode) { 527123326Snjl case TRIGGER_CONFORMS: 528128930Sjhb if (Source == AcpiGbl_FADT->SciInt) 529128930Sjhb return (INTR_TRIGGER_LEVEL); 530128930Sjhb else 531128930Sjhb return (INTR_TRIGGER_EDGE); 532123326Snjl case TRIGGER_EDGE: 533128930Sjhb return (INTR_TRIGGER_EDGE); 534123326Snjl case TRIGGER_LEVEL: 535128930Sjhb return (INTR_TRIGGER_LEVEL); 536121992Sjhb default: 537121992Sjhb panic("Bogus Interrupt Trigger Mode"); 538121992Sjhb } 539121992Sjhb} 540121992Sjhb 541121992Sjhb/* 542121992Sjhb * Find the local APIC ID associated with a given ACPI Processor ID. 543121992Sjhb */ 544121992Sjhbstatic int 545121992Sjhbmadt_find_cpu(u_int acpi_id, u_int *apic_id) 546121992Sjhb{ 547121992Sjhb 548121992Sjhb if (!lapics[acpi_id].la_present) 549121992Sjhb return (ENOENT); 550121992Sjhb *apic_id = lapics[acpi_id].la_apic_id; 551121992Sjhb if (lapics[acpi_id].la_enabled) 552121992Sjhb return (0); 553121992Sjhb else 554121992Sjhb return (ENXIO); 555121992Sjhb} 556121992Sjhb 557121992Sjhb/* 558121992Sjhb * Find the IO APIC and pin on that APIC associated with a given global 559121992Sjhb * interrupt. 560121992Sjhb */ 561121992Sjhbstatic int 562121992Sjhbmadt_find_interrupt(int intr, void **apic, u_int *pin) 563121992Sjhb{ 564121992Sjhb int i, best; 565121992Sjhb 566121992Sjhb best = -1; 567121992Sjhb for (i = 0; i < NIOAPICS; i++) { 568121992Sjhb if (ioapics[i].io_apic == NULL || 569121992Sjhb ioapics[i].io_vector > intr) 570121992Sjhb continue; 571121992Sjhb if (best == -1 || 572121992Sjhb ioapics[best].io_vector < ioapics[i].io_vector) 573121992Sjhb best = i; 574121992Sjhb } 575121992Sjhb if (best == -1) 576121992Sjhb return (ENOENT); 577121992Sjhb *apic = ioapics[best].io_apic; 578121992Sjhb *pin = intr - ioapics[best].io_vector; 579121992Sjhb if (*pin > 32) 580121992Sjhb printf("WARNING: Found intpin of %u for vector %d\n", *pin, 581121992Sjhb intr); 582121992Sjhb return (0); 583121992Sjhb} 584121992Sjhb 585121992Sjhb/* 586121992Sjhb * Parse an interrupt source override for an ISA interrupt. 587121992Sjhb */ 588121992Sjhbstatic void 589123326Snjlmadt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr) 590121992Sjhb{ 591122149Sjhb void *new_ioapic, *old_ioapic; 592122149Sjhb u_int new_pin, old_pin; 593128930Sjhb enum intr_trigger trig; 594128930Sjhb enum intr_polarity pol; 595128930Sjhb char buf[64]; 596121992Sjhb 597121992Sjhb if (bootverbose) 598121992Sjhb printf("MADT: intr override: source %u, irq %u\n", 599123326Snjl intr->Source, intr->Interrupt); 600121992Sjhb KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero")); 601123326Snjl if (madt_find_interrupt(intr->Interrupt, &new_ioapic, 602122149Sjhb &new_pin) != 0) { 603121992Sjhb printf("MADT: Could not find APIC for vector %d (IRQ %d)\n", 604123326Snjl intr->Interrupt, intr->Source); 605121992Sjhb return; 606121992Sjhb } 607121992Sjhb 608125048Sjhb /* 609128930Sjhb * Lookup the appropriate trigger and polarity modes for this 610128930Sjhb * entry. 611128930Sjhb */ 612128930Sjhb trig = interrupt_trigger(intr->TriggerMode, intr->Source); 613128930Sjhb pol = interrupt_polarity(intr->Polarity, intr->Source); 614128930Sjhb 615128930Sjhb /* 616125048Sjhb * If the SCI is identity mapped but has edge trigger and 617128329Sjhb * active-hi polarity or the force_sci_lo tunable is set, 618128329Sjhb * force it to use level/lo. 619125048Sjhb */ 620128930Sjhb if (intr->Source == AcpiGbl_FADT->SciInt) { 621128930Sjhb madt_found_sci_override = 1; 622128930Sjhb if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) { 623128930Sjhb if (tolower(buf[0]) == 'e') 624128930Sjhb trig = INTR_TRIGGER_EDGE; 625128930Sjhb else if (tolower(buf[0]) == 'l') 626128930Sjhb trig = INTR_TRIGGER_LEVEL; 627128930Sjhb else 628128930Sjhb panic( 629128930Sjhb "Invalid trigger %s: must be 'edge' or 'level'", 630128930Sjhb buf); 631128930Sjhb printf("MADT: Forcing SCI to %s trigger\n", 632128930Sjhb trig == INTR_TRIGGER_EDGE ? "edge" : "level"); 633128930Sjhb } 634128930Sjhb if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) { 635128930Sjhb if (tolower(buf[0]) == 'h') 636128930Sjhb pol = INTR_POLARITY_HIGH; 637128930Sjhb else if (tolower(buf[0]) == 'l') 638128930Sjhb pol = INTR_POLARITY_LOW; 639128930Sjhb else 640128930Sjhb panic( 641128930Sjhb "Invalid polarity %s: must be 'high' or 'low'", 642128930Sjhb buf); 643128930Sjhb printf("MADT: Forcing SCI to active %s polarity\n", 644128930Sjhb pol == INTR_POLARITY_HIGH ? "high" : "low"); 645128930Sjhb } 646128930Sjhb } 647125048Sjhb 648128930Sjhb /* Remap the IRQ if it is mapped to a different interrupt vector. */ 649123326Snjl if (intr->Source != intr->Interrupt) { 650125048Sjhb /* 651125048Sjhb * If the SCI is remapped to a non-ISA global interrupt, 652125048Sjhb * then override the vector we use to setup and allocate 653125048Sjhb * the interrupt. 654125048Sjhb */ 655125048Sjhb if (intr->Interrupt > 15 && 656125048Sjhb intr->Source == AcpiGbl_FADT->SciInt) 657123326Snjl acpi_OverrideInterruptLevel(intr->Interrupt); 658122502Sjhb else 659122502Sjhb ioapic_remap_vector(new_ioapic, new_pin, intr->Source); 660122149Sjhb if (madt_find_interrupt(intr->Source, &old_ioapic, 661122149Sjhb &old_pin) != 0) 662122149Sjhb printf("MADT: Could not find APIC for source IRQ %d\n", 663122149Sjhb intr->Source); 664122172Sjhb else if (ioapic_get_vector(old_ioapic, old_pin) == 665122172Sjhb intr->Source) 666122149Sjhb ioapic_disable_pin(old_ioapic, old_pin); 667122149Sjhb } 668128930Sjhb 669128930Sjhb /* Program the polarity and trigger mode. */ 670128930Sjhb ioapic_set_triggermode(new_ioapic, new_pin, trig); 671128930Sjhb ioapic_set_polarity(new_ioapic, new_pin, pol); 672121992Sjhb} 673121992Sjhb 674121992Sjhb/* 675121992Sjhb * Parse an entry for an NMI routed to an IO APIC. 676121992Sjhb */ 677121992Sjhbstatic void 678123326Snjlmadt_parse_nmi(MADT_NMI_SOURCE *nmi) 679121992Sjhb{ 680121992Sjhb void *ioapic; 681121992Sjhb u_int pin; 682121992Sjhb 683123326Snjl if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) { 684121992Sjhb printf("MADT: Could not find APIC for vector %d\n", 685123326Snjl nmi->Interrupt); 686121992Sjhb return; 687121992Sjhb } 688121992Sjhb 689121992Sjhb ioapic_set_nmi(ioapic, pin); 690123326Snjl if (nmi->TriggerMode != TRIGGER_CONFORMS) 691121992Sjhb ioapic_set_triggermode(ioapic, pin, 692128930Sjhb interrupt_trigger(nmi->TriggerMode, 0)); 693123326Snjl if (nmi->Polarity != TRIGGER_CONFORMS) 694121992Sjhb ioapic_set_polarity(ioapic, pin, 695128930Sjhb interrupt_polarity(nmi->Polarity, 0)); 696121992Sjhb} 697121992Sjhb 698121992Sjhb/* 699121992Sjhb * Parse an entry for an NMI routed to a local APIC LVT pin. 700121992Sjhb */ 701121992Sjhbstatic void 702123326Snjlmadt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi) 703121992Sjhb{ 704121992Sjhb u_int apic_id, pin; 705121992Sjhb 706123326Snjl if (nmi->ProcessorId == 0xff) 707121992Sjhb apic_id = APIC_ID_ALL; 708123326Snjl else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) { 709121992Sjhb if (bootverbose) 710121992Sjhb printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", 711123326Snjl nmi->ProcessorId); 712121992Sjhb return; 713121992Sjhb } 714123326Snjl if (nmi->Lint == 0) 715121992Sjhb pin = LVT_LINT0; 716121992Sjhb else 717121992Sjhb pin = LVT_LINT1; 718121992Sjhb lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 719123326Snjl if (nmi->TriggerMode != TRIGGER_CONFORMS) 720121992Sjhb lapic_set_lvt_triggermode(apic_id, pin, 721128930Sjhb interrupt_trigger(nmi->TriggerMode, 0)); 722123326Snjl if (nmi->Polarity != POLARITY_CONFORMS) 723121992Sjhb lapic_set_lvt_polarity(apic_id, pin, 724128930Sjhb interrupt_polarity(nmi->Polarity, 0)); 725121992Sjhb} 726121992Sjhb 727121992Sjhb/* 728121992Sjhb * Parse interrupt entries. 729121992Sjhb */ 730121992Sjhbstatic void 731121992Sjhbmadt_parse_ints(APIC_HEADER *entry, void *arg __unused) 732121992Sjhb{ 733121992Sjhb 734121992Sjhb switch (entry->Type) { 735123326Snjl case APIC_XRUPT_OVERRIDE: 736121992Sjhb madt_parse_interrupt_override( 737123326Snjl (MADT_INTERRUPT_OVERRIDE *)entry); 738121992Sjhb break; 739121992Sjhb case APIC_NMI: 740123326Snjl madt_parse_nmi((MADT_NMI_SOURCE *)entry); 741121992Sjhb break; 742123326Snjl case APIC_LOCAL_NMI: 743123326Snjl madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry); 744121992Sjhb break; 745121992Sjhb } 746121992Sjhb} 747121992Sjhb 748121992Sjhb/* 749121992Sjhb * Setup per-CPU ACPI IDs. 750121992Sjhb */ 751121992Sjhbstatic void 752121992Sjhbmadt_set_ids(void *dummy) 753121992Sjhb{ 754121992Sjhb struct pcpu *pc; 755121992Sjhb u_int i, j; 756121992Sjhb 757121992Sjhb if (madt == NULL) 758121992Sjhb return; 759123133Sjhb for (i = 0; i <= mp_maxid; i++) { 760121992Sjhb if (CPU_ABSENT(i)) 761121992Sjhb continue; 762121992Sjhb pc = pcpu_find(i); 763121992Sjhb KASSERT(pc != NULL, ("no pcpu data for CPU %d", i)); 764121992Sjhb for (j = 0; j < NLAPICS + 1; j++) { 765121992Sjhb if (!lapics[j].la_present || !lapics[j].la_enabled) 766121992Sjhb continue; 767121992Sjhb if (lapics[j].la_apic_id == pc->pc_apic_id) { 768121992Sjhb pc->pc_acpi_id = j; 769121992Sjhb if (bootverbose) 770121992Sjhb printf("APIC: CPU %u has ACPI ID %u\n", 771121992Sjhb i, j); 772121992Sjhb break; 773121992Sjhb } 774121992Sjhb } 775121992Sjhb if (j == NLAPICS + 1) 776121992Sjhb panic("Unable to find ACPI ID for CPU %d", i); 777121992Sjhb } 778121992Sjhb} 779121992SjhbSYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL) 780