1/* $NetBSD: mpacpi.c,v 1.110 2023/03/24 12:25:28 bouyer Exp $ */ 2 3/* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Frank van der Linden for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: mpacpi.c,v 1.110 2023/03/24 12:25:28 bouyer Exp $"); 40 41#include "acpica.h" 42#include "opt_acpi.h" 43#include "opt_ddb.h" 44#include "opt_mpbios.h" 45#include "opt_multiprocessor.h" 46#include "pchb.h" 47 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/kernel.h> 51#include <sys/device.h> 52#include <sys/kmem.h> 53#include <sys/queue.h> 54 55#include <uvm/uvm_extern.h> 56 57#include <machine/specialreg.h> 58#include <machine/cpuvar.h> 59#include <sys/bus.h> 60#include <machine/mpacpi.h> 61#include <machine/mpbiosvar.h> 62 63#include <machine/i82093reg.h> 64#include <machine/i82093var.h> 65#include <machine/i82489reg.h> 66#include <machine/i82489var.h> 67#include <dev/isa/isareg.h> 68#include <dev/pci/pcivar.h> 69#include <dev/pci/pcidevs.h> 70#include <dev/pci/ppbreg.h> 71 72#include <dev/acpi/acpica.h> 73#include <dev/acpi/acpireg.h> 74#include <dev/acpi/acpivar.h> 75 76#include <dev/cons.h> 77 78#define _COMPONENT ACPI_RESOURCE_COMPONENT 79ACPI_MODULE_NAME ("mpacpi") 80 81#include "pci.h" 82#include "ioapic.h" 83#include "lapic.h" 84 85#include "locators.h" 86 87/* XXX room for PCI-to-PCI bus */ 88#define BUS_BUFFER (16) 89 90#if NPCI > 0 91struct mpacpi_pcibus { 92 TAILQ_ENTRY(mpacpi_pcibus) mpr_list; 93 devhandle_t mpr_devhandle; 94 ACPI_BUFFER mpr_buf; /* preserve _PRT */ 95 int mpr_seg; /* PCI segment number */ 96 int mpr_bus; /* PCI bus number */ 97}; 98 99static TAILQ_HEAD(, mpacpi_pcibus) mpacpi_pcibusses; 100 101#endif 102 103static int mpacpi_cpuprint(void *, const char *); 104static int mpacpi_ioapicprint(void *, const char *); 105 106/* acpi_madt_walk callbacks */ 107static ACPI_STATUS mpacpi_count(ACPI_SUBTABLE_HEADER *, void *); 108static ACPI_STATUS mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *, void *); 109static ACPI_STATUS mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *, void *); 110static ACPI_STATUS mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *, void *); 111 112#if NPCI > 0 113static int mpacpi_pcircount(struct mpacpi_pcibus *); 114static int mpacpi_pciroute(struct mpacpi_pcibus *); 115static int mpacpi_find_pcibusses(struct acpi_softc *); 116 117static void mpacpi_print_pci_intr(int); 118#endif 119 120static void mpacpi_config_irouting(struct acpi_softc *); 121 122static void mpacpi_print_intr(struct mp_intr_map *); 123static void mpacpi_print_isa_intr(int); 124 125static void mpacpi_user_continue(const char *fmt, ...); 126 127#ifdef DDB 128void mpacpi_dump(void); 129#endif 130 131int mpacpi_nioapic; /* number of ioapics */ 132int mpacpi_ncpu; /* number of cpus */ 133int mpacpi_nintsrc; /* number of non-device interrupts */ 134 135#if NPCI > 0 136static int mpacpi_npci; 137static int mpacpi_maxpci; 138static int mpacpi_npciroots; 139#endif 140 141static int mpacpi_intr_index; 142static paddr_t mpacpi_lapic_base = LAPIC_BASE; 143 144int mpacpi_step; 145int mpacpi_force; 146 147static int 148mpacpi_cpuprint(void *aux, const char *pnp) 149{ 150 struct cpu_attach_args *caa = aux; 151 152 if (pnp) 153 aprint_normal("cpu at %s", pnp); 154 aprint_normal(" apid %d", caa->cpu_number); 155 return UNCONF; 156} 157 158static int 159mpacpi_ioapicprint(void *aux, const char *pnp) 160{ 161 struct apic_attach_args *aaa = aux; 162 163 if (pnp) 164 aprint_normal("ioapic at %s", pnp); 165 aprint_normal(" apid %d", aaa->apic_id); 166 return UNCONF; 167} 168 169/* 170 * Handle special interrupt sources and overrides from the MADT. 171 * This is a callback function for acpi_madt_walk() (see acpi.c). 172 */ 173static ACPI_STATUS 174mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 175{ 176 int *index = aux, pin, lindex; 177 struct mp_intr_map *mpi; 178 ACPI_MADT_NMI_SOURCE *ioapic_nmi; 179 ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi; 180 ACPI_MADT_INTERRUPT_OVERRIDE *isa_ovr; 181 ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi; 182 struct pic *pic; 183 extern struct acpi_softc *acpi_softc; /* XXX */ 184 185 switch (hdrp->Type) { 186 case ACPI_MADT_TYPE_NMI_SOURCE: 187 ioapic_nmi = (ACPI_MADT_NMI_SOURCE *)hdrp; 188 pic = intr_findpic(ioapic_nmi->GlobalIrq); 189 if (pic == NULL) 190 break; 191#if NIOAPIC == 0 192 if (pic->pic_type == PIC_IOAPIC) 193 break; 194#endif 195 mpi = &mp_intrs[*index]; 196 (*index)++; 197 mpi->next = NULL; 198 mpi->bus = NULL; 199 mpi->type = MPS_INTTYPE_NMI; 200 mpi->ioapic = pic; 201 pin = ioapic_nmi->GlobalIrq - pic->pic_vecbase; 202 mpi->ioapic_pin = pin; 203 mpi->bus_pin = -1; 204 mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT); 205#if NIOAPIC > 0 206 if (pic->pic_type == PIC_IOAPIC) { 207 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 208 mpi->ioapic_ih = APIC_INT_VIA_APIC | 209 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 210 (pin << APIC_INT_PIN_SHIFT); 211 } else 212#endif 213 mpi->ioapic_ih = pin; 214 mpi->flags = ioapic_nmi->IntiFlags; 215 mpi->global_int = ioapic_nmi->GlobalIrq; 216 break; 217 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 218 lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)hdrp; 219 mpi = &mp_intrs[*index]; 220 (*index)++; 221 mpi->next = NULL; 222 mpi->bus = NULL; 223 mpi->ioapic = NULL; 224 mpi->type = MPS_INTTYPE_NMI; 225 mpi->ioapic_pin = lapic_nmi->Lint; 226 mpi->cpu_id = lapic_nmi->ProcessorId; 227 mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT); 228 mpi->global_int = -1; 229 break; 230 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 231 isa_ovr = (ACPI_MADT_INTERRUPT_OVERRIDE *)hdrp; 232 if (mp_verbose) { 233 printf("mpacpi: ISA interrupt override %d -> %d (%d/%d)\n", 234 isa_ovr->SourceIrq, isa_ovr->GlobalIrq, 235 isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK, 236 (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) >>2); 237 } 238 if (isa_ovr->SourceIrq > 15 || isa_ovr->SourceIrq == 2 || 239 (isa_ovr->SourceIrq == 0 && isa_ovr->GlobalIrq == 2 && 240 (acpi_softc->sc_quirks & ACPI_QUIRK_IRQ0))) 241 break; 242 pic = intr_findpic(isa_ovr->GlobalIrq); 243 if (pic == NULL) 244 break; 245#if NIOAPIC == 0 246 if (pic->pic_type == PIC_IOAPIC) 247 break; 248#endif 249 pin = isa_ovr->GlobalIrq - pic->pic_vecbase; 250 lindex = isa_ovr->SourceIrq; 251 /* 252 * IRQ 2 was skipped in the default setup. 253 */ 254 if (lindex > 2) 255 lindex--; 256 mpi = &mp_intrs[lindex]; 257#if NIOAPIC > 0 258 if (pic->pic_type == PIC_IOAPIC) { 259 mpi->ioapic_ih = APIC_INT_VIA_APIC | 260 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 261 (pin << APIC_INT_PIN_SHIFT); 262 } else 263#endif 264 mpi->ioapic_ih = pin; 265 mpi->bus_pin = isa_ovr->SourceIrq; 266 mpi->ioapic = (struct pic *)pic; 267 mpi->ioapic_pin = pin; 268 mpi->sflags |= MPI_OVR; 269 mpi->redir = 0; 270 mpi->global_int = isa_ovr->GlobalIrq; 271 switch (isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK) { 272 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 273 mpi->redir &= ~IOAPIC_REDLO_ACTLO; 274 break; 275 case ACPI_MADT_POLARITY_ACTIVE_LOW: 276 mpi->redir |= IOAPIC_REDLO_ACTLO; 277 break; 278 case ACPI_MADT_POLARITY_CONFORMS: 279 if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 280 mpi->redir |= IOAPIC_REDLO_ACTLO; 281 else 282 mpi->redir &= ~IOAPIC_REDLO_ACTLO; 283 break; 284 } 285 mpi->redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT); 286 switch (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) { 287 case ACPI_MADT_TRIGGER_LEVEL: 288 mpi->redir |= IOAPIC_REDLO_LEVEL; 289 break; 290 case ACPI_MADT_TRIGGER_EDGE: 291 mpi->redir &= ~IOAPIC_REDLO_LEVEL; 292 break; 293 case ACPI_MADT_TRIGGER_CONFORMS: 294 if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt) 295 mpi->redir |= IOAPIC_REDLO_LEVEL; 296 else 297 mpi->redir &= ~IOAPIC_REDLO_LEVEL; 298 break; 299 } 300 mpi->flags = isa_ovr->IntiFlags; 301#if NIOAPIC > 0 302 if (pic->pic_type == PIC_IOAPIC) 303 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 304#endif 305 break; 306 307 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 308 x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)hdrp; 309 310 mpi = &mp_intrs[*index]; 311 (*index)++; 312 mpi->next = NULL; 313 mpi->bus = NULL; 314 mpi->ioapic = NULL; 315 mpi->type = MPS_INTTYPE_NMI; 316 mpi->ioapic_pin = x2apic_nmi->Lint; 317 mpi->cpu_id = x2apic_nmi->Uid; 318 mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT); 319 mpi->global_int = -1; 320 break; 321 322 default: 323 break; 324 } 325 return AE_OK; 326} 327 328/* 329 * Count various MP resources present in the MADT. 330 * This is a callback function for acpi_madt_walk(). 331 */ 332static ACPI_STATUS 333mpacpi_count(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 334{ 335 ACPI_MADT_LOCAL_APIC_OVERRIDE *lop; 336 337 switch (hdrp->Type) { 338 case ACPI_MADT_TYPE_LOCAL_APIC: 339 case ACPI_MADT_TYPE_LOCAL_X2APIC: 340 mpacpi_ncpu++; 341 break; 342 case ACPI_MADT_TYPE_IO_APIC: 343 mpacpi_nioapic++; 344 break; 345 case ACPI_MADT_TYPE_NMI_SOURCE: 346 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 347 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 348 mpacpi_nintsrc++; 349 break; 350 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 351 lop = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)hdrp; 352 mpacpi_lapic_base = lop->Address; 353 default: 354 break; 355 } 356 return AE_OK; 357} 358 359static ACPI_STATUS 360mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 361{ 362 device_t parent = aux; 363 ACPI_MADT_LOCAL_APIC *lapic; 364 ACPI_MADT_LOCAL_X2APIC *x2apic; 365 struct cpu_attach_args caa; 366 int cpunum = 0; 367 int locs[CPUBUSCF_NLOCS]; 368 369#if defined(MULTIPROCESSOR) || defined(IOAPIC) 370 if (mpacpi_ncpu > 1) 371 cpunum = lapic_cpu_number(); 372#endif 373 374 switch (hdrp->Type) { 375 case ACPI_MADT_TYPE_LOCAL_APIC: 376 lapic = (ACPI_MADT_LOCAL_APIC *)hdrp; 377 if (lapic->LapicFlags & ACPI_MADT_ENABLED) { 378 if (lapic->Id != cpunum) 379 caa.cpu_role = CPU_ROLE_AP; 380 else 381 caa.cpu_role = CPU_ROLE_BP; 382 caa.cpu_id = lapic->ProcessorId; 383 caa.cpu_number = lapic->Id; 384 caa.cpu_func = &mp_cpu_funcs; 385 locs[CPUBUSCF_APID] = caa.cpu_number; 386 config_found(parent, &caa, mpacpi_cpuprint, 387 CFARGS(.submatch = config_stdsubmatch, 388 .iattr = "cpubus", 389 .locators = locs)); 390 } 391 break; 392 393 case ACPI_MADT_TYPE_LOCAL_X2APIC: 394 x2apic = (ACPI_MADT_LOCAL_X2APIC *)hdrp; 395 396 /* ACPI spec: "Logical processors with APIC ID values 397 * less than 255 must use the Processor Local APIC 398 * structure to convey their APIC information to OSPM." 399 * But Xen with PVH dom0 breaks this ACPI spec. 400 */ 401 if (x2apic->LocalApicId <= 0xff && vm_guest != VM_GUEST_XENPVH) { 402 printf("bogus MADT X2APIC entry (id = 0x%"PRIx32")\n", 403 x2apic->LocalApicId); 404 break; 405 } 406 407 if (x2apic->LapicFlags & ACPI_MADT_ENABLED) { 408 if (x2apic->LocalApicId != cpunum) 409 caa.cpu_role = CPU_ROLE_AP; 410 else 411 caa.cpu_role = CPU_ROLE_BP; 412 caa.cpu_id = x2apic->Uid; 413 caa.cpu_number = x2apic->LocalApicId; 414 caa.cpu_func = &mp_cpu_funcs; 415 locs[CPUBUSCF_APID] = caa.cpu_number; 416 config_found(parent, &caa, mpacpi_cpuprint, 417 CFARGS(.submatch = config_stdsubmatch, 418 .iattr = "cpubus", 419 .locators = locs)); 420 } 421 break; 422 423 } 424 return AE_OK; 425} 426 427static ACPI_STATUS 428mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 429{ 430 device_t parent = aux; 431 struct apic_attach_args aaa; 432 ACPI_MADT_IO_APIC *p; 433 int locs[IOAPICBUSCF_NLOCS]; 434 435 if (hdrp->Type == ACPI_MADT_TYPE_IO_APIC) { 436 p = (ACPI_MADT_IO_APIC *)hdrp; 437 aaa.apic_id = p->Id; 438 aaa.apic_address = p->Address; 439 aaa.apic_version = -1; 440 aaa.flags = IOAPIC_VWIRE; 441 aaa.apic_vecbase = p->GlobalIrqBase; 442 locs[IOAPICBUSCF_APID] = aaa.apic_id; 443 config_found(parent, &aaa, mpacpi_ioapicprint, 444 CFARGS(.submatch = config_stdsubmatch, 445 .iattr = "ioapicbus", 446 .locators = locs)); 447 } 448 return AE_OK; 449} 450 451int 452mpacpi_scan_apics(device_t self, int *ncpup) 453{ 454 int rv = 0; 455 456 if (acpi_madt_map() != AE_OK) 457 return 0; 458 459 mpacpi_ncpu = mpacpi_nintsrc = mpacpi_nioapic = 0; 460 acpi_madt_walk(mpacpi_count, self); 461 462 acpi_madt_walk(mpacpi_config_ioapic, self); 463 464#if NLAPIC > 0 465 lapic_boot_init(mpacpi_lapic_base); 466#endif 467 468 acpi_madt_walk(mpacpi_config_cpu, self); 469 470 if (mpacpi_ncpu == 0) 471 goto done; 472 473#if NPCI > 0 474 /* 475 * If PCI routing tables can't be built we report failure 476 * and let MPBIOS do the work. 477 */ 478 if (!mpacpi_force && 479 (acpi_find_quirks() & (ACPI_QUIRK_BADPCI)) != 0) 480 goto done; 481#endif 482 rv = 1; 483done: 484 *ncpup = mpacpi_ncpu; 485 acpi_madt_unmap(); 486 return rv; 487} 488 489#if NPCI > 0 490 491static void 492mpacpi_pci_foundbus(struct acpi_devnode *ad) 493{ 494 struct mpacpi_pcibus *mpr; 495 ACPI_BUFFER buf; 496 int rv; 497 498 /* 499 * set mpr_buf from _PRT (if it exists). 500 * set mpr_seg and mpr_bus from previously cached info. 501 */ 502 503 rv = acpi_get(ad->ad_handle, &buf, AcpiGetIrqRoutingTable); 504 if (ACPI_FAILURE(rv)) { 505 buf.Length = 0; 506 buf.Pointer = NULL; 507 } 508 509 mpr = kmem_zalloc(sizeof(struct mpacpi_pcibus), KM_SLEEP); 510 mpr->mpr_devhandle = 511 devhandle_from_acpi(devhandle_invalid(), ad->ad_handle); 512 mpr->mpr_buf = buf; 513 mpr->mpr_seg = ad->ad_pciinfo->ap_segment; 514 mpr->mpr_bus = ad->ad_pciinfo->ap_downbus; 515 TAILQ_INSERT_TAIL(&mpacpi_pcibusses, mpr, mpr_list); 516 517 if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { 518 if (mp_verbose) 519 printf("mpacpi: found root PCI bus %d\n", 520 mpr->mpr_bus); 521 mpacpi_npciroots++; 522 } else { 523 if (mp_verbose) 524 printf("mpacpi: found subordinate bus %d\n", 525 mpr->mpr_bus); 526 } 527 528 /* 529 * XXX this wrongly assumes that bus numbers are unique 530 * even between segments. 531 */ 532 if (mpr->mpr_bus > mpacpi_maxpci) 533 mpacpi_maxpci = mpr->mpr_bus; 534 535 mpacpi_npci++; 536} 537 538 539static void 540mpacpi_pci_walk(struct acpi_devnode *ad) 541{ 542 struct acpi_devnode *child; 543 544 if (ad->ad_pciinfo && 545 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0) { 546 mpacpi_pci_foundbus(ad); 547 } 548 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) { 549 mpacpi_pci_walk(child); 550 } 551} 552 553static int 554mpacpi_find_pcibusses(struct acpi_softc *sc) 555{ 556 557 TAILQ_INIT(&mpacpi_pcibusses); 558 mpacpi_pci_walk(sc->sc_root); 559 return 0; 560} 561 562/* 563 * Find all static PRT entries for a PCI bus. 564 */ 565static int 566mpacpi_pciroute(struct mpacpi_pcibus *mpr) 567{ 568 ACPI_PCI_ROUTING_TABLE *ptrp; 569 ACPI_HANDLE linkdev; 570 char *p; 571 struct mp_intr_map *mpi, *iter; 572 struct mp_bus *mpb; 573 struct pic *pic; 574 unsigned dev; 575 int pin; 576 577 if (mp_verbose) 578 printf("mpacpi: configuring PCI bus %d int routing\n", 579 mpr->mpr_bus); 580 581 mpb = &mp_busses[mpr->mpr_bus]; 582 583 if (mpb->mb_name != NULL) 584 printf("mpacpi: PCI bus %d int routing already done!\n", 585 mpr->mpr_bus); 586 587 mpb->mb_intrs = NULL; 588 mpb->mb_name = "pci"; 589 mpb->mb_idx = mpr->mpr_bus; 590 mpb->mb_intr_print = mpacpi_print_pci_intr; 591 mpb->mb_intr_cfg = NULL; 592 mpb->mb_data = 0; 593 594 if (mpr->mpr_buf.Length == 0) { 595 goto out; 596 } 597 598 for (p = mpr->mpr_buf.Pointer; ; p += ptrp->Length) { 599 ptrp = (ACPI_PCI_ROUTING_TABLE *)p; 600 if (ptrp->Length == 0) 601 break; 602 dev = ACPI_HIWORD(ptrp->Address); 603 604 if (ptrp->Source[0] == 0 && 605 (ptrp->SourceIndex == 14 || ptrp->SourceIndex == 15)) { 606 printf("Skipping PCI routing entry for PCI IDE compat IRQ"); 607 continue; 608 } 609 610 mpi = &mp_intrs[mpacpi_intr_index]; 611 mpi->bus_pin = (dev << 2) | (ptrp->Pin & 3); 612 mpi->bus = mpb; 613 mpi->type = MPS_INTTYPE_INT; 614 615 /* 616 * First check if an entry for this device/pin combination 617 * was already found. Some DSDTs have more than one entry 618 * and it seems that the first is generally the right one. 619 */ 620 for (iter = mpb->mb_intrs; iter != NULL; iter = iter->next) { 621 if (iter->bus_pin == mpi->bus_pin) 622 break; 623 } 624 if (iter != NULL) 625 continue; 626 627 ++mpacpi_intr_index; 628 629 if (ptrp->Source[0] != 0) { 630 if (mp_verbose > 1) 631 printf("pciroute: dev %d INT%c on lnkdev %s\n", 632 dev, 'A' + (ptrp->Pin & 3), ptrp->Source); 633 mpi->global_int = -1; 634 mpi->sourceindex = ptrp->SourceIndex; 635 if (AcpiGetHandle(ACPI_ROOT_OBJECT, ptrp->Source, 636 &linkdev) != AE_OK) { 637 printf("AcpiGetHandle failed for '%s'\n", 638 ptrp->Source); 639 continue; 640 } 641 /* acpi_allocate_resources(linkdev); */ 642 mpi->ioapic_pin = -1; 643 mpi->linkdev = acpi_pci_link_devbyhandle(linkdev); 644 acpi_pci_link_add_reference(mpi->linkdev, NULL, 0, 645 mpr->mpr_bus, dev, ptrp->Pin & 3); 646 mpi->ioapic = NULL; 647 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2); 648 if (mp_verbose > 1) 649 printf("pciroute: done adding entry\n"); 650 } else { 651 if (mp_verbose > 1) 652 printf("pciroute: dev %d INT%c on globint %d\n", 653 dev, 'A' + (ptrp->Pin & 3), 654 ptrp->SourceIndex); 655 mpi->sourceindex = 0; 656 mpi->global_int = ptrp->SourceIndex; 657 pic = intr_findpic(ptrp->SourceIndex); 658 if (pic == NULL) 659 continue; 660 /* Defaults for PCI (active low, level triggered) */ 661 mpi->redir = 662 (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT) | 663 IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO; 664 mpi->ioapic = pic; 665 pin = ptrp->SourceIndex - pic->pic_vecbase; 666 if (pic->pic_type == PIC_I8259 && pin > 15) 667 panic("bad pin %d for legacy IRQ", pin); 668 mpi->ioapic_pin = pin; 669#if NIOAPIC > 0 670 if (pic->pic_type == PIC_IOAPIC) { 671 pic->pic_ioapic->sc_pins[pin].ip_map = mpi; 672 mpi->ioapic_ih = APIC_INT_VIA_APIC | 673 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 674 (pin << APIC_INT_PIN_SHIFT); 675 } else 676#endif 677 mpi->ioapic_ih = pin; 678 mpi->linkdev = NULL; 679 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2); 680 if (mp_verbose > 1) 681 printf("pciroute: done adding entry\n"); 682 } 683 684 mpi->cpu_id = 0; 685 686 mpi->next = mpb->mb_intrs; 687 mpb->mb_intrs = mpi; 688 } 689 690 ACPI_FREE(mpr->mpr_buf.Pointer); 691 mpr->mpr_buf.Pointer = NULL; /* be preventive to bugs */ 692 693out: 694 if (mp_verbose > 1) 695 printf("pciroute: done\n"); 696 697 return 0; 698} 699 700/* 701 * Count number of elements in _PRT 702 */ 703static int 704mpacpi_pcircount(struct mpacpi_pcibus *mpr) 705{ 706 int count = 0; 707 ACPI_PCI_ROUTING_TABLE *PrtElement; 708 uint8_t *Buffer; 709 710 if (mpr->mpr_buf.Length == 0) { 711 return 0; 712 } 713 714 for (Buffer = mpr->mpr_buf.Pointer;; Buffer += PrtElement->Length) { 715 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer; 716 if (PrtElement->Length == 0) 717 break; 718 count++; 719 } 720 721 return count; 722} 723#endif 724 725/* 726 * Set up the interrupt config lists, in the same format as the mpbios does. 727 */ 728static void 729mpacpi_config_irouting(struct acpi_softc *acpi) 730{ 731#if NPCI > 0 732 struct mpacpi_pcibus *mpr; 733#endif 734 int nintr; 735 int i; 736 struct mp_bus *mbp; 737 struct mp_intr_map *mpi; 738 struct pic *pic; 739 740 nintr = mpacpi_nintsrc + NUM_LEGACY_IRQS - 1; 741#if NPCI > 0 742 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) { 743 nintr += mpacpi_pcircount(mpr); 744 } 745 746 mp_isa_bus = mpacpi_maxpci + BUS_BUFFER; /* XXX */ 747#else 748 mp_isa_bus = 0; 749#endif 750 mp_nbus = mp_isa_bus + 1; 751 mp_nintr = nintr; 752 753 mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP); 754 mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * mp_nintr, KM_SLEEP); 755 mbp = &mp_busses[mp_isa_bus]; 756 mbp->mb_name = "isa"; 757 mbp->mb_idx = 0; 758 mbp->mb_intr_print = mpacpi_print_isa_intr; 759 mbp->mb_intr_cfg = NULL; 760 mbp->mb_intrs = &mp_intrs[0]; 761 mbp->mb_data = 0; 762 763 pic = intr_findpic(0); 764 if (pic == NULL) 765 panic("mpacpi: can't find first PIC"); 766#if NIOAPIC == 0 767 if (pic->pic_type == PIC_IOAPIC) 768 panic("mpacpi: ioapic but no i8259?"); 769#endif 770 771 /* 772 * Set up default identity mapping for ISA irqs to first ioapic. 773 */ 774 for (i = mpacpi_intr_index = 0; i < NUM_LEGACY_IRQS; i++) { 775 if (i == 2) 776 continue; 777 mpi = &mp_intrs[mpacpi_intr_index]; 778 if (mpacpi_intr_index < (NUM_LEGACY_IRQS - 2)) 779 mpi->next = &mp_intrs[mpacpi_intr_index + 1]; 780 else 781 mpi->next = NULL; 782 mpi->bus = mbp; 783 mpi->bus_pin = i; 784 mpi->ioapic_pin = i; 785 mpi->ioapic = pic; 786 mpi->type = MPS_INTTYPE_INT; 787 mpi->cpu_id = 0; 788 mpi->redir = 0; 789#if NIOAPIC > 0 790 if (pic->pic_type == PIC_IOAPIC) { 791 mpi->ioapic_ih = APIC_INT_VIA_APIC | 792 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 793 (i << APIC_INT_PIN_SHIFT); 794 mpi->redir = 795 (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT); 796 pic->pic_ioapic->sc_pins[i].ip_map = mpi; 797 } else 798#endif 799 mpi->ioapic_ih = i; 800 801 mpi->flags = MPS_INTPO_DEF | (MPS_INTTR_DEF << 2); 802 mpi->global_int = i; 803 mpacpi_intr_index++; 804 } 805 806 mpacpi_user_continue("done setting up mp_bus array and ISA maps"); 807 808 if (acpi_madt_map() == AE_OK) { 809 acpi_madt_walk(mpacpi_nonpci_intr, &mpacpi_intr_index); 810 acpi_madt_unmap(); 811 } 812 813 mpacpi_user_continue("done with non-PCI interrupts"); 814 815#if NPCI > 0 816 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) { 817 mpacpi_pciroute(mpr); 818 } 819#endif 820 821 mpacpi_user_continue("done routing PCI interrupts"); 822 823 mp_nintr = mpacpi_intr_index; 824} 825 826/* 827 * XXX code duplication with mpbios.c 828 */ 829 830#if NPCI > 0 831static void 832mpacpi_print_pci_intr(int intr) 833{ 834 printf(" device %d INT_%c", (intr >> 2) & 0x1f, 'A' + (intr & 0x3)); 835} 836#endif 837 838static void 839mpacpi_print_isa_intr(int intr) 840{ 841 printf(" irq %d", intr); 842} 843 844static const char inttype_fmt[] = "\177\020" 845 "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0"; 846 847static const char flagtype_fmt[] = "\177\020" 848 "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0" 849 "f\2\2trig\0" "=\1Edge\0" "=\3Level\0"; 850 851static void 852mpacpi_print_intr(struct mp_intr_map *mpi) 853{ 854 char buf[256]; 855 int pin; 856 struct pic *sc; 857 const char *busname; 858 859 sc = mpi->ioapic; 860 pin = mpi->ioapic_pin; 861 if (mpi->bus != NULL) 862 busname = mpi->bus->mb_name; 863 else { 864 switch (mpi->type) { 865 case MPS_INTTYPE_NMI: 866 busname = "NMI"; 867 break; 868 case MPS_INTTYPE_SMI: 869 busname = "SMI"; 870 break; 871 case MPS_INTTYPE_ExtINT: 872 busname = "ExtINT"; 873 break; 874 default: 875 busname = "<unknown>"; 876 break; 877 } 878 } 879 880 if (mpi->linkdev != NULL) 881 printf("linkdev %s attached to %s", 882 acpi_pci_link_name(mpi->linkdev), busname); 883 else 884 printf("%s: pin %d attached to %s", 885 sc ? sc->pic_name : "local apic", 886 pin, busname); 887 888 if (mpi->bus != NULL) { 889 if (mpi->bus->mb_idx != -1) 890 printf("%d", mpi->bus->mb_idx); 891 (*(mpi->bus->mb_intr_print))(mpi->bus_pin); 892 } 893 snprintb(buf, sizeof(buf), inttype_fmt, mpi->type); 894 printf(" (type %s", buf); 895 896 snprintb(buf, sizeof(buf), flagtype_fmt, mpi->flags); 897 printf(" flags %s)\n", buf); 898 899} 900 901 902int 903mpacpi_find_interrupts(void *self) 904{ 905#if NIOAPIC > 0 906 ACPI_STATUS rv; 907#endif 908 struct acpi_softc *acpi = self; 909 int i; 910 911#ifdef MPBIOS 912 /* 913 * If MPBIOS was enabled, and did the work (because the initial 914 * MADT scan failed for some reason), there's nothing left to 915 * do here. Same goes for the case where no I/O APICS were found. 916 */ 917 if (mpbios_scanned) 918 return 0; 919#endif 920 921#if NIOAPIC > 0 922 if (mpacpi_nioapic != 0) { 923 /* 924 * Switch us into APIC mode by evaluating _PIC(1). 925 * Needs to be done now, since it has an effect on 926 * the interrupt information we're about to retrieve. 927 * 928 * ACPI 3.0 (section 5.8.1): 929 * 0 = PIC mode, 1 = APIC mode, 2 = SAPIC mode. 930 */ 931 rv = acpi_eval_set_integer(NULL, "\\_PIC", 1); 932 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { 933 if (mp_verbose) 934 printf("mpacpi: switch to APIC mode failed\n"); 935 return 0; 936 } 937 } 938#endif 939 940#if NPCI > 0 941 mpacpi_user_continue("finding PCI busses "); 942 mpacpi_find_pcibusses(acpi); 943 if (mp_verbose) 944 printf("mpacpi: %d PCI busses\n", mpacpi_npci); 945#endif 946 mpacpi_config_irouting(acpi); 947 if (mp_verbose) 948 for (i = 0; i < mp_nintr; i++) 949 mpacpi_print_intr(&mp_intrs[i]); 950 return 0; 951} 952 953#if NPCI > 0 954 955static void 956mpacpi_set_devhandle(device_t self, struct pcibus_attach_args *pba) 957{ 958 devhandle_t devhandle = device_handle(self); 959 struct mpacpi_pcibus *mpr; 960 961 /* If we already have a valid handle, eject now. */ 962 if (devhandle_type(devhandle) != DEVHANDLE_TYPE_INVALID) { 963 return; 964 } 965 966 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) { 967 /* XXX Assuming always segment 0 on x86. */ 968 if (mpr->mpr_seg != 0) { 969 continue; 970 } 971 if (mpr->mpr_bus == pba->pba_bus) { 972 device_set_handle(self, mpr->mpr_devhandle); 973 return; 974 } 975 } 976} 977 978int 979mpacpi_pci_attach_hook(device_t parent, device_t self, 980 struct pcibus_attach_args *pba) 981{ 982 struct mp_bus *mpb; 983 984#ifdef MPBIOS 985 if (mpbios_scanned != 0) 986 return ENOENT; 987#endif 988 989 if (TAILQ_EMPTY(&mpacpi_pcibusses)) 990 return 0; 991 992 /* 993 * If this bus is not found in mpacpi_find_pcibusses 994 * (i.e. behind PCI-to-PCI bridge), register as an extra bus. 995 * 996 * at this point, mp_busses[] are as follows: 997 * mp_busses[0 .. mpacpi_maxpci] : PCI 998 * mp_busses[mpacpi_maxpci + BUS_BUFFER] : ISA 999 */ 1000 if (pba->pba_bus >= mp_isa_bus) { 1001 intr_add_pcibus(pba); 1002 return 0; 1003 } 1004 1005 mpb = &mp_busses[pba->pba_bus]; 1006 if (mpb->mb_name != NULL) { 1007 if (strcmp(mpb->mb_name, "pci")) 1008 return EINVAL; 1009 } else { 1010 /* 1011 * As we cannot find all PCI-to-PCI bridge in 1012 * mpacpi_find_pcibusses, some of the MP_busses may remain 1013 * uninitialized. 1014 */ 1015 mpb->mb_name = "pci"; 1016 } 1017 1018 mpacpi_set_devhandle(self, pba); 1019 1020 mpb->mb_dev = self; 1021 mpb->mb_pci_bridge_tag = pba->pba_bridgetag; 1022 mpb->mb_pci_chipset_tag = pba->pba_pc; 1023 1024 if (mp_verbose) 1025 printf("\n%s: added to list as bus %d", device_xname(parent), 1026 pba->pba_bus); 1027 1028 1029 if (pba->pba_bus > mpacpi_maxpci) 1030 mpacpi_maxpci = pba->pba_bus; 1031 1032 return 0; 1033} 1034#endif 1035 1036int 1037mpacpi_findintr_linkdev(struct mp_intr_map *mip) 1038{ 1039 int irq, line, pol, trig; 1040 struct pic *pic; 1041 int pin; 1042 1043 if (mip->linkdev == NULL) 1044 return ENOENT; 1045 1046 irq = acpi_pci_link_route_interrupt(mip->linkdev, NULL, 1047 mip->sourceindex, &line, &pol, &trig); 1048 if (mp_verbose) 1049 printf("linkdev %s returned ACPI global irq %d, line %d\n", 1050 acpi_pci_link_name(mip->linkdev), irq, line); 1051 if (irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) 1052 return ENOENT; 1053 if (irq != line) { 1054 aprint_error("%s: mpacpi_findintr_linkdev:" 1055 " irq mismatch (%d vs %d)\n", 1056 acpi_pci_link_name(mip->linkdev), irq, line); 1057 return ENOENT; 1058 } 1059 1060 /* 1061 * Convert ACPICA values to MPS values 1062 */ 1063 if (pol == ACPI_ACTIVE_LOW) 1064 pol = MPS_INTPO_ACTLO; 1065 else 1066 pol = MPS_INTPO_ACTHI; 1067 1068 if (trig == ACPI_EDGE_SENSITIVE) 1069 trig = MPS_INTTR_EDGE; 1070 else 1071 trig = MPS_INTTR_LEVEL; 1072 1073 mip->flags = pol | (trig << 2); 1074 mip->global_int = irq; 1075 pic = intr_findpic(irq); 1076 if (pic == NULL) 1077 return ENOENT; 1078 mip->ioapic = pic; 1079 pin = irq - pic->pic_vecbase; 1080 1081 if (pic->pic_type == PIC_IOAPIC) { 1082#if NIOAPIC > 0 1083 mip->redir = (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT); 1084 if (pol == MPS_INTPO_ACTLO) 1085 mip->redir |= IOAPIC_REDLO_ACTLO; 1086 if (trig == MPS_INTTR_LEVEL) 1087 mip->redir |= IOAPIC_REDLO_LEVEL; 1088 mip->ioapic_ih = APIC_INT_VIA_APIC | 1089 (pic->pic_apicid << APIC_INT_APIC_SHIFT) | 1090 (pin << APIC_INT_PIN_SHIFT); 1091 pic->pic_ioapic->sc_pins[pin].ip_map = mip; 1092 mip->ioapic_pin = pin; 1093#else 1094 return ENOENT; 1095#endif 1096 } else 1097 mip->ioapic_ih = pin; 1098 return 0; 1099} 1100 1101static void 1102mpacpi_user_continue(const char *fmt, ...) 1103{ 1104 va_list ap; 1105 1106 if (!mpacpi_step) 1107 return; 1108 1109 printf("mpacpi: "); 1110 va_start(ap, fmt); 1111 vprintf(fmt, ap); 1112 va_end(ap); 1113 printf("<press any key to continue>\n>"); 1114 cngetc(); 1115} 1116 1117#ifdef DDB 1118void 1119mpacpi_dump(void) 1120{ 1121 int i; 1122 for (i = 0; i < mp_nintr; i++) 1123 mpacpi_print_intr(&mp_intrs[i]); 1124} 1125#endif 1126