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 if (arg->bsp_found) { 296 kprintf("cpu id %d, duplicate BSP found\n", 297 arg->cpu); 298 } 299 arg->bsp_found = 1; 300 } else { 301 cpu = arg->cpu; 302 arg->cpu++; 303 } 304 MADT_VPRINTF("cpu id %d, acpi id %d, apic id %d\n", 305 cpu, lapic_ent->ProcessorId, lapic_ent->Id); 306 if (lapic_ent->Id >= 255) { 307 kprintf("cpu id %d, WARNING acpi id %d\n", 308 cpu, lapic_ent->Id); 309 } 310 if (lapic_ent->ProcessorId >= 255) { 311 kprintf("cpu id %d, WARNING acpi processorid %d\n", 312 cpu, lapic_ent->ProcessorId); 313 } 314 lapic_set_cpuid(cpu, lapic_ent->Id); 315 CPUID_TO_ACPIID(cpu) = lapic_ent->ProcessorId; 316 } 317 return 0; 318 } 319 320 static int 321 madt_x2apic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 322 { 323 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent; 324 struct madt_lapic_pass2_cbarg *arg = xarg; 325 326 if (ent->Type != ACPI_MADT_TYPE_LOCAL_X2APIC) 327 return 0; 328 329 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent; 330 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) { 331 int cpu; 332 333 if (x2apic_ent->LocalApicId == arg->bsp_apic_id) { 334 cpu = 0; 335 arg->bsp_found = 1; 336 } else { 337 cpu = arg->cpu; 338 arg->cpu++; 339 } 340 MADT_VPRINTF("cpu id %d, acpi uid %u, apic id %d\n", 341 cpu, x2apic_ent->Uid, x2apic_ent->LocalApicId); 342 lapic_set_cpuid(cpu, x2apic_ent->LocalApicId); 343 CPUID_TO_ACPIID(cpu) = x2apic_ent->Uid; 344 } 345 return 0; 346 } 347 348 static int 349 madt_lapic_pass2(int bsp_apic_id) 350 { 351 ACPI_TABLE_MADT *madt; 352 struct madt_lapic_pass2_cbarg arg; 353 madt_iter_t func; 354 int error; 355 356 MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id); 357 358 KKASSERT(madt_phyaddr != 0); 359 360 madt = sdt_sdth_map(madt_phyaddr); 361 KKASSERT(madt != NULL); 362 363 bzero(&arg, sizeof(arg)); 364 arg.cpu = 1; 365 arg.bsp_apic_id = bsp_apic_id; 366 367 if (madt_use_x2apic) 368 func = madt_x2apic_pass2_callback; 369 else 370 func = madt_lapic_pass2_callback; 371 error = madt_iterate_entries(madt, func, &arg); 372 if (error) 373 panic("madt_iterate_entries(pass2) failed"); 374 375 KKASSERT(arg.bsp_found); 376 naps = arg.cpu - 1; /* exclude BSP */ 377 kprintf("ACPI CPUS = %d\n", arg.cpu); 378 379 sdt_sdth_unmap(&madt->Header); 380 381 return 0; 382 } 383 384 struct madt_lapic_probe_cbarg { 385 int x2apic_count; 386 int lapic_count; 387 vm_paddr_t lapic_addr; 388 }; 389 390 static int 391 madt_lapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 392 { 393 struct madt_lapic_probe_cbarg *arg = xarg; 394 395 if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC) { 396 const ACPI_MADT_LOCAL_APIC *lapic_ent; 397 398 lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent; 399 if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) { 400 arg->lapic_count++; 401 if (lapic_ent->Id == APICID_MAX) { 402 kprintf("madt_lapic_probe: " 403 "invalid LAPIC apic id %d\n", 404 lapic_ent->Id); 405 return EINVAL; 406 } 407 } 408 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_X2APIC) { 409 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent; 410 411 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent; 412 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) { 413 if (x2apic_ent->LocalApicId < APICID_MAX) { 414 /* 415 * XXX we only support APIC ID 0~254 at 416 * the moment. 417 */ 418 arg->x2apic_count++; 419 } 420 } 421 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) { 422 const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent; 423 424 if (ent->Length < sizeof(*lapic_addr_ent)) { 425 kprintf("madt_lapic_probe: " 426 "invalid LAPIC address override length\n"); 427 return 0; 428 } 429 lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent; 430 431 if (lapic_addr_ent->Address != 0) 432 arg->lapic_addr = lapic_addr_ent->Address; 433 } 434 return 0; 435 } 436 437 static int 438 madt_lapic_probe(struct lapic_enumerator *e) 439 { 440 struct madt_lapic_probe_cbarg arg; 441 ACPI_TABLE_MADT *madt; 442 int error; 443 444 if (madt_phyaddr == 0) 445 return ENXIO; 446 447 madt = sdt_sdth_map(madt_phyaddr); 448 KKASSERT(madt != NULL); 449 450 bzero(&arg, sizeof(arg)); 451 arg.lapic_addr = madt->Address; 452 453 error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg); 454 if (!error) { 455 kprintf("madt_lapic_probe: lapic_count=%d x2apic_count=%d\n", 456 arg.lapic_count, arg.x2apic_count); 457 if (arg.lapic_count == 0 && arg.x2apic_count == 0) { 458 kprintf("madt_lapic_probe: no CPU is found\n"); 459 error = EOPNOTSUPP; 460 } else if (arg.lapic_count == 0) { 461 /* 462 * ACPI 5.1 says that LOCAL_X2APIC entry should 463 * be used only if APIC ID > 255. While ACPI 6.2 464 * removes that constraint, which means that 465 * LOCAL_X2APIC entry could be used for any APIC 466 * ID. 467 * 468 * XXX 469 * In DragonFlyBSD, we don't support APIC ID >= 470 * 255, so LOCAL_X2APIC entries should be ignored, 471 * if LOCAL_X2APIC entries are mixed with 472 * LOCAL_APIC entries. LOCAL_X2APIC entries are 473 * used, iff only LOCAL_X2APIC entries exist. 474 */ 475 madt_use_x2apic = TRUE; 476 kprintf("MADT: use X2APIC entries\n"); 477 } 478 479 if (arg.lapic_addr == 0) { 480 /* 481 * The LAPIC address does not matter in X2APIC mode. 482 */ 483 if ((cpu_feature2 & CPUID2_X2APIC) == 0) { 484 kprintf("madt_lapic_probe: zero LAPIC address\n"); 485 error = EOPNOTSUPP; 486 } 487 } 488 } 489 490 sdt_sdth_unmap(&madt->Header); 491 return error; 492 } 493 494 static int 495 madt_lapic_enumerate(struct lapic_enumerator *e) 496 { 497 vm_paddr_t lapic_addr = 0; 498 int bsp_apic_id; 499 500 KKASSERT(madt_phyaddr != 0); 501 502 if (!x2apic_enable) { 503 lapic_addr = madt_lapic_pass1(); 504 if (lapic_addr == 0) { 505 /* 506 * No LAPIC address. 507 */ 508 if (cpu_feature2 & CPUID2_X2APIC) { 509 /* 510 * X2APIC mode is not enabled, but the CPU supports 511 * it. Forcefully enable X2APIC mode, which nullifies 512 * the requirement of the LAPIC address. 513 */ 514 kprintf("MADT: no LAPIC address, force X2APIC mode\n"); 515 KKASSERT(!x2apic_enable); 516 x2apic_enable = 1; 517 lapic_x2apic_enter(TRUE); 518 } else { 519 /* 520 * We should not reach here, madt_lapic_probe() must 521 * have failed. 522 */ 523 panic("madt_lapic_enumerate: no local apic"); 524 } 525 } 526 } 527 528 if (!x2apic_enable) { 529 KASSERT(lapic_addr != 0, ("madt_lapic_enumerate: zero LAPIC address")); 530 lapic_map(lapic_addr); 531 } 532 533 bsp_apic_id = LAPIC_READID; 534 if (bsp_apic_id == APICID_MAX) { 535 /* 536 * XXX 537 * Some old brain dead BIOS will set BSP's LAPIC apic id 538 * to 255, though all LAPIC entries in MADT are valid. 539 */ 540 kprintf("%s invalid BSP LAPIC apic id %d\n", __func__, 541 bsp_apic_id); 542 return EINVAL; 543 } 544 545 if (madt_lapic_pass2(bsp_apic_id)) 546 panic("madt_lapic_enumerate: madt_lapic_pass2 failed"); 547 548 return 0; 549 } 550 551 static struct lapic_enumerator madt_lapic_enumerator = { 552 .lapic_prio = LAPIC_ENUM_PRIO_MADT, 553 .lapic_probe = madt_lapic_probe, 554 .lapic_enumerate = madt_lapic_enumerate 555 }; 556 557 static void 558 madt_lapic_enum_register(void) 559 { 560 int prio; 561 562 prio = LAPIC_ENUM_PRIO_MADT; 563 kgetenv_int("hw.madt_lapic_prio", &prio); 564 madt_lapic_enumerator.lapic_prio = prio; 565 566 lapic_enumerator_register(&madt_lapic_enumerator); 567 } 568 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0); 569 570 struct madt_ioapic_probe_cbarg { 571 int ioapic_cnt; 572 int gsi_base0; 573 }; 574 575 static int 576 madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 577 { 578 struct madt_ioapic_probe_cbarg *arg = xarg; 579 580 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { 581 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent; 582 int trig, pola; 583 584 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent; 585 586 if (intsrc_ent->SourceIrq >= ISA_IRQ_CNT) { 587 kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n", 588 intsrc_ent->SourceIrq); 589 return EINVAL; 590 } 591 592 if (intsrc_ent->Bus != MADT_INT_BUS_ISA) { 593 kprintf("ACPI MADT: warning intsrc irq %d " 594 "bus is not ISA (%d)\n", 595 intsrc_ent->SourceIrq, intsrc_ent->Bus); 596 } 597 598 trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK; 599 if (trig == ACPI_MADT_TRIGGER_RESERVED) { 600 kprintf("ACPI MADT: warning invalid intsrc irq %d " 601 "trig, reserved\n", intsrc_ent->SourceIrq); 602 } else if (trig == ACPI_MADT_TRIGGER_LEVEL) { 603 MADT_VPRINTF("warning invalid intsrc irq %d " 604 "trig, level\n", intsrc_ent->SourceIrq); 605 } 606 607 pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK; 608 if (pola == ACPI_MADT_POLARITY_RESERVED) { 609 kprintf("ACPI MADT: warning invalid intsrc irq %d " 610 "pola, reserved\n", intsrc_ent->SourceIrq); 611 } else if (pola == ACPI_MADT_POLARITY_ACTIVE_LOW) { 612 MADT_VPRINTF("warning invalid intsrc irq %d " 613 "pola, low\n", intsrc_ent->SourceIrq); 614 } 615 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) { 616 const ACPI_MADT_IO_APIC *ioapic_ent; 617 618 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent; 619 if (ioapic_ent->Address == 0) { 620 kprintf("madt_ioapic_probe: zero IOAPIC address\n"); 621 return EINVAL; 622 } 623 if (ioapic_ent->Id == APICID_MAX) { 624 kprintf("madt_ioapic_probe: " 625 "invalid IOAPIC apic id %d\n", 626 ioapic_ent->Id); 627 return EINVAL; 628 } 629 630 arg->ioapic_cnt++; 631 if (ioapic_ent->GlobalIrqBase == 0) 632 arg->gsi_base0 = 1; 633 } 634 return 0; 635 } 636 637 static int 638 madt_ioapic_probe(struct ioapic_enumerator *e) 639 { 640 struct madt_ioapic_probe_cbarg arg; 641 ACPI_TABLE_MADT *madt; 642 int error; 643 644 if (madt_phyaddr == 0) 645 return ENXIO; 646 647 madt = sdt_sdth_map(madt_phyaddr); 648 KKASSERT(madt != NULL); 649 650 bzero(&arg, sizeof(arg)); 651 652 error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg); 653 if (!error) { 654 if (arg.ioapic_cnt == 0) { 655 kprintf("madt_ioapic_probe: no IOAPIC\n"); 656 error = ENXIO; 657 } 658 if (!arg.gsi_base0) { 659 kprintf("madt_ioapic_probe: no GSI base 0\n"); 660 error = EINVAL; 661 } 662 } 663 664 sdt_sdth_unmap(&madt->Header); 665 return error; 666 } 667 668 static int 669 madt_ioapic_enum_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent) 670 { 671 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { 672 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent; 673 enum intr_trigger trig; 674 enum intr_polarity pola; 675 int ent_trig, ent_pola; 676 677 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent; 678 679 KKASSERT(intsrc_ent->SourceIrq < ISA_IRQ_CNT); 680 if (intsrc_ent->Bus != MADT_INT_BUS_ISA) 681 return 0; 682 683 ent_trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK; 684 if (ent_trig == ACPI_MADT_TRIGGER_RESERVED) 685 return 0; 686 else if (ent_trig == ACPI_MADT_TRIGGER_LEVEL) 687 trig = INTR_TRIGGER_LEVEL; 688 else 689 trig = INTR_TRIGGER_EDGE; 690 691 ent_pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK; 692 if (ent_pola == ACPI_MADT_POLARITY_RESERVED) 693 return 0; 694 else if (ent_pola == ACPI_MADT_POLARITY_ACTIVE_LOW) 695 pola = INTR_POLARITY_LOW; 696 else 697 pola = INTR_POLARITY_HIGH; 698 699 if (intsrc_ent->SourceIrq == acpi_sci_irqno()) { 700 acpi_sci_setmode1(trig, pola); 701 MADT_VPRINTF("SCI irq %d, first test %s/%s\n", 702 intsrc_ent->SourceIrq, 703 intr_str_trigger(trig), intr_str_polarity(pola)); 704 } 705 706 /* 707 * We ignore the polarity and trigger changes, since 708 * most of them are wrong or useless at best. 709 */ 710 if (intsrc_ent->SourceIrq == intsrc_ent->GlobalIrq) { 711 /* Nothing changed */ 712 return 0; 713 } 714 trig = INTR_TRIGGER_EDGE; 715 pola = INTR_POLARITY_HIGH; 716 717 MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n", 718 intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq, 719 intr_str_trigger(trig), intr_str_polarity(pola)); 720 ioapic_intsrc(intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq, 721 trig, pola); 722 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) { 723 const ACPI_MADT_IO_APIC *ioapic_ent; 724 uint32_t ver; 725 void *addr; 726 int npin; 727 728 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent; 729 MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n", 730 ioapic_ent->Address, ioapic_ent->Id, 731 ioapic_ent->GlobalIrqBase); 732 733 addr = ioapic_map(ioapic_ent->Address); 734 735 ver = ioapic_read(addr, IOAPIC_VER); 736 npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; 737 738 ioapic_add(addr, ioapic_ent->GlobalIrqBase, npin); 739 } 740 return 0; 741 } 742 743 static void 744 madt_ioapic_enumerate(struct ioapic_enumerator *e) 745 { 746 ACPI_TABLE_MADT *madt; 747 int error; 748 749 KKASSERT(madt_phyaddr != 0); 750 751 madt = sdt_sdth_map(madt_phyaddr); 752 KKASSERT(madt != NULL); 753 754 error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL); 755 if (error) 756 panic("madt_ioapic_enumerate failed"); 757 758 sdt_sdth_unmap(&madt->Header); 759 } 760 761 static struct ioapic_enumerator madt_ioapic_enumerator = { 762 .ioapic_prio = IOAPIC_ENUM_PRIO_MADT, 763 .ioapic_probe = madt_ioapic_probe, 764 .ioapic_enumerate = madt_ioapic_enumerate 765 }; 766 767 static void 768 madt_ioapic_enum_register(void) 769 { 770 int prio; 771 772 prio = IOAPIC_ENUM_PRIO_MADT; 773 kgetenv_int("hw.madt_ioapic_prio", &prio); 774 madt_ioapic_enumerator.ioapic_prio = prio; 775 776 ioapic_enumerator_register(&madt_ioapic_enumerator); 777 } 778 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, 779 madt_ioapic_enum_register, 0); 780