1 /* 2 * Copyright (c) 2009 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Sepherosa Ziehau <sepherosa@gmail.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/bus.h> 37 #include <sys/kernel.h> 38 #include <sys/systm.h> 39 40 #include <machine_base/isa/isa_intr.h> 41 #include <machine_base/apic/lapic.h> 42 #include <machine_base/apic/ioapic.h> 43 #include <machine_base/apic/apicvar.h> 44 #include <machine_base/acpica/acpi_md_cpu.h> 45 #include <machine/specialreg.h> 46 47 #include <contrib/dev/acpica/source/include/acpi.h> 48 49 #include "acpi_sdt_var.h" 50 #include "acpi_sci_var.h" 51 52 extern int naps; 53 54 #define MADT_VPRINTF(fmt, arg...) \ 55 do { \ 56 if (bootverbose) \ 57 kprintf("ACPI MADT: " fmt , ##arg); \ 58 } while (0) 59 60 #define MADT_INT_BUS_ISA 0 61 62 typedef int (*madt_iter_t)(void *, 63 const ACPI_SUBTABLE_HEADER *); 64 65 static int madt_check(vm_paddr_t); 66 static int madt_iterate_entries(ACPI_TABLE_MADT *, 67 madt_iter_t, void *); 68 69 static vm_paddr_t madt_lapic_pass1(void); 70 static int madt_lapic_pass2(int); 71 72 static int madt_lapic_enumerate(struct lapic_enumerator *); 73 static int madt_lapic_probe(struct lapic_enumerator *); 74 75 static void madt_ioapic_enumerate( 76 struct ioapic_enumerator *); 77 static int madt_ioapic_probe(struct ioapic_enumerator *); 78 79 static vm_paddr_t madt_phyaddr; 80 81 static boolean_t madt_use_x2apic = FALSE; 82 83 u_int cpu_id_to_acpi_id[NAPICID]; 84 85 static void 86 madt_probe(void) 87 { 88 vm_paddr_t madt_paddr; 89 int i; 90 91 for (i = 0; i < NAPICID; ++i) 92 CPUID_TO_ACPIID(i) = (u_int)-1; 93 94 KKASSERT(madt_phyaddr == 0); 95 96 madt_paddr = sdt_search(ACPI_SIG_MADT); 97 if (madt_paddr == 0) { 98 kprintf("madt_probe: can't locate MADT\n"); 99 return; 100 } 101 102 /* Preliminary checks */ 103 if (madt_check(madt_paddr)) { 104 kprintf("madt_probe: madt_check failed\n"); 105 return; 106 } 107 108 madt_phyaddr = madt_paddr; 109 } 110 SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0); 111 112 static int 113 madt_check(vm_paddr_t madt_paddr) 114 { 115 ACPI_TABLE_MADT *madt; 116 int error = 0; 117 118 KKASSERT(madt_paddr != 0); 119 120 madt = sdt_sdth_map(madt_paddr); 121 KKASSERT(madt != NULL); 122 123 /* 124 * MADT in ACPI specification 1.0 - 5.0 125 */ 126 if (madt->Header.Revision < 1 || madt->Header.Revision > 3) { 127 kprintf("madt_check: unknown MADT revision %d\n", 128 madt->Header.Revision); 129 } 130 131 if (madt->Header.Length < sizeof(*madt)) { 132 kprintf("madt_check: invalid MADT length %u\n", 133 madt->Header.Length); 134 error = EINVAL; 135 goto back; 136 } 137 back: 138 sdt_sdth_unmap(&madt->Header); 139 return error; 140 } 141 142 static int 143 madt_iterate_entries(ACPI_TABLE_MADT *madt, madt_iter_t func, void *arg) 144 { 145 int size, cur, error; 146 147 size = madt->Header.Length - sizeof(*madt); 148 cur = 0; 149 error = 0; 150 151 while (size - cur > sizeof(ACPI_SUBTABLE_HEADER)) { 152 const ACPI_SUBTABLE_HEADER *ent; 153 154 ent = (const ACPI_SUBTABLE_HEADER *) 155 ((char *)madt + sizeof(*madt) + cur); 156 if (ent->Length < sizeof(*ent)) { 157 kprintf("madt_iterate_entries: invalid MADT " 158 "entry len %d\n", ent->Length); 159 error = EINVAL; 160 break; 161 } 162 if (ent->Length > (size - cur)) { 163 kprintf("madt_iterate_entries: invalid MADT " 164 "entry len %d, > table length\n", ent->Length); 165 error = EINVAL; 166 break; 167 } 168 169 cur += ent->Length; 170 171 /* 172 * Only Local APIC, I/O APIC and Interrupt Source Override 173 * are defined in ACPI specification 1.0 - 5.0 174 */ 175 switch (ent->Type) { 176 case ACPI_MADT_TYPE_LOCAL_APIC: 177 if (ent->Length < sizeof(ACPI_MADT_LOCAL_APIC)) { 178 kprintf("madt_iterate_entries: invalid MADT " 179 "lapic entry len %d\n", ent->Length); 180 error = EINVAL; 181 } 182 break; 183 184 case ACPI_MADT_TYPE_LOCAL_X2APIC: 185 if (ent->Length < sizeof(ACPI_MADT_LOCAL_X2APIC)) { 186 kprintf("madt_iterate_entries: invalid MADT " 187 "x2apic entry len %d\n", ent->Length); 188 error = EINVAL; 189 } 190 break; 191 192 case ACPI_MADT_TYPE_IO_APIC: 193 if (ent->Length < sizeof(ACPI_MADT_IO_APIC)) { 194 kprintf("madt_iterate_entries: invalid MADT " 195 "ioapic entry len %d\n", ent->Length); 196 error = EINVAL; 197 } 198 break; 199 200 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 201 if (ent->Length < sizeof(ACPI_MADT_INTERRUPT_OVERRIDE)) { 202 kprintf("madt_iterate_entries: invalid MADT " 203 "intsrc entry len %d\n", 204 ent->Length); 205 error = EINVAL; 206 } 207 break; 208 } 209 if (error) 210 break; 211 212 error = func(arg, ent); 213 if (error) 214 break; 215 216 ent = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, ent, ent->Length); 217 } 218 return error; 219 } 220 221 static int 222 madt_lapic_pass1_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 223 { 224 const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent; 225 uint64_t *addr64 = xarg; 226 227 if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) 228 return 0; 229 if (ent->Length < sizeof(*lapic_addr_ent)) { 230 kprintf("madt_lapic_pass1: " 231 "invalid LAPIC address override length\n"); 232 return 0; 233 } 234 lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent; 235 236 *addr64 = lapic_addr_ent->Address; 237 return 0; 238 } 239 240 static vm_paddr_t 241 madt_lapic_pass1(void) 242 { 243 ACPI_TABLE_MADT *madt; 244 vm_paddr_t lapic_addr; 245 uint64_t lapic_addr64; 246 int error; 247 248 KKASSERT(madt_phyaddr != 0); 249 250 madt = sdt_sdth_map(madt_phyaddr); 251 KKASSERT(madt != NULL); 252 253 MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n", 254 madt->Address, madt->Flags); 255 lapic_addr = madt->Address; 256 257 lapic_addr64 = 0; 258 error = madt_iterate_entries(madt, madt_lapic_pass1_callback, 259 &lapic_addr64); 260 if (error) 261 panic("madt_iterate_entries(pass1) failed"); 262 263 if (lapic_addr64 != 0) { 264 kprintf("ACPI MADT: 64bits lapic address 0x%lx\n", 265 lapic_addr64); 266 lapic_addr = lapic_addr64; 267 } 268 269 sdt_sdth_unmap(&madt->Header); 270 271 return lapic_addr; 272 } 273 274 struct madt_lapic_pass2_cbarg { 275 int cpu; 276 int bsp_found; 277 int bsp_apic_id; 278 }; 279 280 static int 281 madt_lapic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 282 { 283 const ACPI_MADT_LOCAL_APIC *lapic_ent; 284 struct madt_lapic_pass2_cbarg *arg = xarg; 285 286 if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC) 287 return 0; 288 289 lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent; 290 if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) { 291 int cpu; 292 293 if (lapic_ent->Id == arg->bsp_apic_id) { 294 cpu = 0; 295 arg->bsp_found = 1; 296 } else { 297 cpu = arg->cpu; 298 arg->cpu++; 299 } 300 MADT_VPRINTF("cpu id %d, acpi id %d, apic id %d\n", 301 cpu, lapic_ent->ProcessorId, lapic_ent->Id); 302 lapic_set_cpuid(cpu, lapic_ent->Id); 303 CPUID_TO_ACPIID(cpu) = lapic_ent->ProcessorId; 304 } 305 return 0; 306 } 307 308 static int 309 madt_x2apic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 310 { 311 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent; 312 struct madt_lapic_pass2_cbarg *arg = xarg; 313 314 if (ent->Type != ACPI_MADT_TYPE_LOCAL_X2APIC) 315 return 0; 316 317 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent; 318 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) { 319 int cpu; 320 321 if (x2apic_ent->LocalApicId == arg->bsp_apic_id) { 322 cpu = 0; 323 arg->bsp_found = 1; 324 } else { 325 cpu = arg->cpu; 326 arg->cpu++; 327 } 328 MADT_VPRINTF("cpu id %d, acpi uid %u, apic id %d\n", 329 cpu, x2apic_ent->Uid, x2apic_ent->LocalApicId); 330 lapic_set_cpuid(cpu, x2apic_ent->LocalApicId); 331 CPUID_TO_ACPIID(cpu) = x2apic_ent->Uid; 332 } 333 return 0; 334 } 335 336 static int 337 madt_lapic_pass2(int bsp_apic_id) 338 { 339 ACPI_TABLE_MADT *madt; 340 struct madt_lapic_pass2_cbarg arg; 341 madt_iter_t func; 342 int error; 343 344 MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id); 345 346 KKASSERT(madt_phyaddr != 0); 347 348 madt = sdt_sdth_map(madt_phyaddr); 349 KKASSERT(madt != NULL); 350 351 bzero(&arg, sizeof(arg)); 352 arg.cpu = 1; 353 arg.bsp_apic_id = bsp_apic_id; 354 355 if (madt_use_x2apic) 356 func = madt_x2apic_pass2_callback; 357 else 358 func = madt_lapic_pass2_callback; 359 error = madt_iterate_entries(madt, func, &arg); 360 if (error) 361 panic("madt_iterate_entries(pass2) failed"); 362 363 KKASSERT(arg.bsp_found); 364 naps = arg.cpu - 1; /* exclude BSP */ 365 366 sdt_sdth_unmap(&madt->Header); 367 368 return 0; 369 } 370 371 struct madt_lapic_probe_cbarg { 372 int x2apic_count; 373 int lapic_count; 374 vm_paddr_t lapic_addr; 375 }; 376 377 static int 378 madt_lapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 379 { 380 struct madt_lapic_probe_cbarg *arg = xarg; 381 382 if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC) { 383 const ACPI_MADT_LOCAL_APIC *lapic_ent; 384 385 lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent; 386 if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) { 387 arg->lapic_count++; 388 if (lapic_ent->Id == APICID_MAX) { 389 kprintf("madt_lapic_probe: " 390 "invalid LAPIC apic id %d\n", 391 lapic_ent->Id); 392 return EINVAL; 393 } 394 } 395 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_X2APIC) { 396 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent; 397 398 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent; 399 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) { 400 if (x2apic_ent->LocalApicId < APICID_MAX) { 401 /* 402 * XXX we only support APIC ID 0~254 at 403 * the moment. 404 */ 405 arg->x2apic_count++; 406 } 407 } 408 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) { 409 const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent; 410 411 if (ent->Length < sizeof(*lapic_addr_ent)) { 412 kprintf("madt_lapic_probe: " 413 "invalid LAPIC address override length\n"); 414 return 0; 415 } 416 lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent; 417 418 if (lapic_addr_ent->Address != 0) 419 arg->lapic_addr = lapic_addr_ent->Address; 420 } 421 return 0; 422 } 423 424 static int 425 madt_lapic_probe(struct lapic_enumerator *e) 426 { 427 struct madt_lapic_probe_cbarg arg; 428 ACPI_TABLE_MADT *madt; 429 int error; 430 431 if (madt_phyaddr == 0) 432 return ENXIO; 433 434 madt = sdt_sdth_map(madt_phyaddr); 435 KKASSERT(madt != NULL); 436 437 bzero(&arg, sizeof(arg)); 438 arg.lapic_addr = madt->Address; 439 440 error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg); 441 if (!error) { 442 if (arg.lapic_count == 0 && arg.x2apic_count == 0) { 443 kprintf("madt_lapic_probe: no CPU is found\n"); 444 error = EOPNOTSUPP; 445 } else if (arg.lapic_count == 0) { 446 /* 447 * ACPI 5.1 says that LOCAL_X2APIC entry should 448 * be used only if APIC ID > 255. While ACPI 6.2 449 * removes that constraint, which means that 450 * LOCAL_X2APIC entry could be used for any APIC 451 * ID. 452 * 453 * XXX 454 * In DragonFlyBSD, we don't support APIC ID >= 455 * 255, so LOCAL_X2APIC entries should be ignored, 456 * if LOCAL_X2APIC entries are mixed with 457 * LOCAL_APIC entries. LOCAL_X2APIC entries are 458 * used, iff only LOCAL_X2APIC entries exist. 459 */ 460 madt_use_x2apic = TRUE; 461 kprintf("MADT: use X2APIC entries\n"); 462 } 463 464 if (arg.lapic_addr == 0) { 465 /* 466 * The LAPIC address does not matter in X2APIC mode. 467 */ 468 if ((cpu_feature2 & CPUID2_X2APIC) == 0) { 469 kprintf("madt_lapic_probe: zero LAPIC address\n"); 470 error = EOPNOTSUPP; 471 } 472 } 473 } 474 475 sdt_sdth_unmap(&madt->Header); 476 return error; 477 } 478 479 static int 480 madt_lapic_enumerate(struct lapic_enumerator *e) 481 { 482 vm_paddr_t lapic_addr = 0; 483 int bsp_apic_id; 484 485 KKASSERT(madt_phyaddr != 0); 486 487 if (!x2apic_enable) { 488 lapic_addr = madt_lapic_pass1(); 489 if (lapic_addr == 0) { 490 /* 491 * No LAPIC address. 492 */ 493 if (cpu_feature2 & CPUID2_X2APIC) { 494 /* 495 * X2APIC mode is not enabled, but the CPU supports 496 * it. Forcefully enable X2APIC mode, which nullifies 497 * the requirement of the LAPIC address. 498 */ 499 kprintf("MADT: no LAPIC address, force X2APIC mode\n"); 500 KKASSERT(!x2apic_enable); 501 x2apic_enable = 1; 502 lapic_x2apic_enter(TRUE); 503 } else { 504 /* 505 * We should not reach here, madt_lapic_probe() must 506 * have failed. 507 */ 508 panic("madt_lapic_enumerate: no local apic"); 509 } 510 } 511 } 512 513 if (!x2apic_enable) { 514 KASSERT(lapic_addr != 0, ("madt_lapic_enumerate: zero LAPIC address")); 515 lapic_map(lapic_addr); 516 } 517 518 bsp_apic_id = LAPIC_READID; 519 if (bsp_apic_id == APICID_MAX) { 520 /* 521 * XXX 522 * Some old brain dead BIOS will set BSP's LAPIC apic id 523 * to 255, though all LAPIC entries in MADT are valid. 524 */ 525 kprintf("%s invalid BSP LAPIC apic id %d\n", __func__, 526 bsp_apic_id); 527 return EINVAL; 528 } 529 530 if (madt_lapic_pass2(bsp_apic_id)) 531 panic("madt_lapic_enumerate: madt_lapic_pass2 failed"); 532 533 return 0; 534 } 535 536 static struct lapic_enumerator madt_lapic_enumerator = { 537 .lapic_prio = LAPIC_ENUM_PRIO_MADT, 538 .lapic_probe = madt_lapic_probe, 539 .lapic_enumerate = madt_lapic_enumerate 540 }; 541 542 static void 543 madt_lapic_enum_register(void) 544 { 545 int prio; 546 547 prio = LAPIC_ENUM_PRIO_MADT; 548 kgetenv_int("hw.madt_lapic_prio", &prio); 549 madt_lapic_enumerator.lapic_prio = prio; 550 551 lapic_enumerator_register(&madt_lapic_enumerator); 552 } 553 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0); 554 555 struct madt_ioapic_probe_cbarg { 556 int ioapic_cnt; 557 int gsi_base0; 558 }; 559 560 static int 561 madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 562 { 563 struct madt_ioapic_probe_cbarg *arg = xarg; 564 565 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { 566 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent; 567 int trig, pola; 568 569 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent; 570 571 if (intsrc_ent->SourceIrq >= ISA_IRQ_CNT) { 572 kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n", 573 intsrc_ent->SourceIrq); 574 return EINVAL; 575 } 576 577 if (intsrc_ent->Bus != MADT_INT_BUS_ISA) { 578 kprintf("ACPI MADT: warning intsrc irq %d " 579 "bus is not ISA (%d)\n", 580 intsrc_ent->SourceIrq, intsrc_ent->Bus); 581 } 582 583 trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK; 584 if (trig == ACPI_MADT_TRIGGER_RESERVED) { 585 kprintf("ACPI MADT: warning invalid intsrc irq %d " 586 "trig, reserved\n", intsrc_ent->SourceIrq); 587 } else if (trig == ACPI_MADT_TRIGGER_LEVEL) { 588 MADT_VPRINTF("warning invalid intsrc irq %d " 589 "trig, level\n", intsrc_ent->SourceIrq); 590 } 591 592 pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK; 593 if (pola == ACPI_MADT_POLARITY_RESERVED) { 594 kprintf("ACPI MADT: warning invalid intsrc irq %d " 595 "pola, reserved\n", intsrc_ent->SourceIrq); 596 } else if (pola == ACPI_MADT_POLARITY_ACTIVE_LOW) { 597 MADT_VPRINTF("warning invalid intsrc irq %d " 598 "pola, low\n", intsrc_ent->SourceIrq); 599 } 600 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) { 601 const ACPI_MADT_IO_APIC *ioapic_ent; 602 603 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent; 604 if (ioapic_ent->Address == 0) { 605 kprintf("madt_ioapic_probe: zero IOAPIC address\n"); 606 return EINVAL; 607 } 608 if (ioapic_ent->Id == APICID_MAX) { 609 kprintf("madt_ioapic_probe: " 610 "invalid IOAPIC apic id %d\n", 611 ioapic_ent->Id); 612 return EINVAL; 613 } 614 615 arg->ioapic_cnt++; 616 if (ioapic_ent->GlobalIrqBase == 0) 617 arg->gsi_base0 = 1; 618 } 619 return 0; 620 } 621 622 static int 623 madt_ioapic_probe(struct ioapic_enumerator *e) 624 { 625 struct madt_ioapic_probe_cbarg arg; 626 ACPI_TABLE_MADT *madt; 627 int error; 628 629 if (madt_phyaddr == 0) 630 return ENXIO; 631 632 madt = sdt_sdth_map(madt_phyaddr); 633 KKASSERT(madt != NULL); 634 635 bzero(&arg, sizeof(arg)); 636 637 error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg); 638 if (!error) { 639 if (arg.ioapic_cnt == 0) { 640 kprintf("madt_ioapic_probe: no IOAPIC\n"); 641 error = ENXIO; 642 } 643 if (!arg.gsi_base0) { 644 kprintf("madt_ioapic_probe: no GSI base 0\n"); 645 error = EINVAL; 646 } 647 } 648 649 sdt_sdth_unmap(&madt->Header); 650 return error; 651 } 652 653 static int 654 madt_ioapic_enum_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 655 { 656 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { 657 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent; 658 enum intr_trigger trig; 659 enum intr_polarity pola; 660 int ent_trig, ent_pola; 661 662 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent; 663 664 KKASSERT(intsrc_ent->SourceIrq < ISA_IRQ_CNT); 665 if (intsrc_ent->Bus != MADT_INT_BUS_ISA) 666 return 0; 667 668 ent_trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK; 669 if (ent_trig == ACPI_MADT_TRIGGER_RESERVED) 670 return 0; 671 else if (ent_trig == ACPI_MADT_TRIGGER_LEVEL) 672 trig = INTR_TRIGGER_LEVEL; 673 else 674 trig = INTR_TRIGGER_EDGE; 675 676 ent_pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK; 677 if (ent_pola == ACPI_MADT_POLARITY_RESERVED) 678 return 0; 679 else if (ent_pola == ACPI_MADT_POLARITY_ACTIVE_LOW) 680 pola = INTR_POLARITY_LOW; 681 else 682 pola = INTR_POLARITY_HIGH; 683 684 if (intsrc_ent->SourceIrq == acpi_sci_irqno()) { 685 acpi_sci_setmode1(trig, pola); 686 MADT_VPRINTF("SCI irq %d, first test %s/%s\n", 687 intsrc_ent->SourceIrq, 688 intr_str_trigger(trig), intr_str_polarity(pola)); 689 } 690 691 /* 692 * We ignore the polarity and trigger changes, since 693 * most of them are wrong or useless at best. 694 */ 695 if (intsrc_ent->SourceIrq == intsrc_ent->GlobalIrq) { 696 /* Nothing changed */ 697 return 0; 698 } 699 trig = INTR_TRIGGER_EDGE; 700 pola = INTR_POLARITY_HIGH; 701 702 MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n", 703 intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq, 704 intr_str_trigger(trig), intr_str_polarity(pola)); 705 ioapic_intsrc(intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq, 706 trig, pola); 707 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) { 708 const ACPI_MADT_IO_APIC *ioapic_ent; 709 uint32_t ver; 710 void *addr; 711 int npin; 712 713 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent; 714 MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n", 715 ioapic_ent->Address, ioapic_ent->Id, 716 ioapic_ent->GlobalIrqBase); 717 718 addr = ioapic_map(ioapic_ent->Address); 719 720 ver = ioapic_read(addr, IOAPIC_VER); 721 npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; 722 723 ioapic_add(addr, ioapic_ent->GlobalIrqBase, npin); 724 } 725 return 0; 726 } 727 728 static void 729 madt_ioapic_enumerate(struct ioapic_enumerator *e) 730 { 731 ACPI_TABLE_MADT *madt; 732 int error; 733 734 KKASSERT(madt_phyaddr != 0); 735 736 madt = sdt_sdth_map(madt_phyaddr); 737 KKASSERT(madt != NULL); 738 739 error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL); 740 if (error) 741 panic("madt_ioapic_enumerate failed"); 742 743 sdt_sdth_unmap(&madt->Header); 744 } 745 746 static struct ioapic_enumerator madt_ioapic_enumerator = { 747 .ioapic_prio = IOAPIC_ENUM_PRIO_MADT, 748 .ioapic_probe = madt_ioapic_probe, 749 .ioapic_enumerate = madt_ioapic_enumerate 750 }; 751 752 static void 753 madt_ioapic_enum_register(void) 754 { 755 int prio; 756 757 prio = IOAPIC_ENUM_PRIO_MADT; 758 kgetenv_int("hw.madt_ioapic_prio", &prio); 759 madt_ioapic_enumerator.ioapic_prio = prio; 760 761 ioapic_enumerator_register(&madt_ioapic_enumerator); 762 } 763 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, 764 madt_ioapic_enum_register, 0); 765