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 45 #include "acpi_sdt.h" 46 #include "acpi_sdt_var.h" 47 #include "acpi_sci_var.h" 48 49 extern int naps; 50 51 #define MADT_VPRINTF(fmt, arg...) \ 52 do { \ 53 if (bootverbose) \ 54 kprintf("ACPI MADT: " fmt , ##arg); \ 55 } while (0) 56 57 /* Multiple APIC Description Table */ 58 struct acpi_madt { 59 struct acpi_sdth madt_hdr; 60 uint32_t madt_lapic_addr; 61 uint32_t madt_flags; 62 uint8_t madt_ents[1]; 63 } __packed; 64 65 /* Common parts of MADT APIC structure */ 66 struct acpi_madt_ent { 67 uint8_t me_type; /* MADT_ENT_ */ 68 uint8_t me_len; 69 } __packed; 70 71 #define MADT_ENT_LAPIC 0 72 #define MADT_ENT_IOAPIC 1 73 #define MADT_ENT_INTSRC 2 74 #define MADT_ENT_LAPIC_ADDR 5 75 76 /* MADT Processor Local APIC */ 77 struct acpi_madt_lapic { 78 struct acpi_madt_ent ml_hdr; 79 uint8_t ml_cpu_id; 80 uint8_t ml_apic_id; 81 uint32_t ml_flags; /* MADT_LAPIC_ */ 82 } __packed; 83 84 #define MADT_LAPIC_ENABLED 0x1 85 86 /* MADT I/O APIC */ 87 struct acpi_madt_ioapic { 88 struct acpi_madt_ent mio_hdr; 89 uint8_t mio_apic_id; 90 uint8_t mio_reserved; 91 uint32_t mio_addr; 92 uint32_t mio_gsi_base; 93 } __packed; 94 95 /* MADT Interrupt Source Override */ 96 struct acpi_madt_intsrc { 97 struct acpi_madt_ent mint_hdr; 98 uint8_t mint_bus; /* MADT_INT_BUS_ */ 99 uint8_t mint_src; 100 uint32_t mint_gsi; 101 uint16_t mint_flags; /* MADT_INT_ */ 102 } __packed; 103 104 #define MADT_INT_BUS_ISA 0 105 106 #define MADT_INT_POLA_MASK 0x3 107 #define MADT_INT_POLA_SHIFT 0 108 #define MADT_INT_POLA_CONFORM 0 109 #define MADT_INT_POLA_HIGH 1 110 #define MADT_INT_POLA_RSVD 2 111 #define MADT_INT_POLA_LOW 3 112 #define MADT_INT_TRIG_MASK 0xc 113 #define MADT_INT_TRIG_SHIFT 2 114 #define MADT_INT_TRIG_CONFORM 0 115 #define MADT_INT_TRIG_EDGE 1 116 #define MADT_INT_TRIG_RSVD 2 117 #define MADT_INT_TRIG_LEVEL 3 118 119 /* MADT Local APIC Address Override */ 120 struct acpi_madt_lapic_addr { 121 struct acpi_madt_ent mla_hdr; 122 uint16_t mla_reserved; 123 uint64_t mla_lapic_addr; 124 } __packed; 125 126 typedef int (*madt_iter_t)(void *, 127 const struct acpi_madt_ent *); 128 129 static int madt_check(vm_paddr_t); 130 static int madt_iterate_entries(struct acpi_madt *, 131 madt_iter_t, void *); 132 133 static vm_paddr_t madt_lapic_pass1(void); 134 static int madt_lapic_pass2(int); 135 136 static int madt_lapic_enumerate(struct lapic_enumerator *); 137 static int madt_lapic_probe(struct lapic_enumerator *); 138 139 static void madt_ioapic_enumerate( 140 struct ioapic_enumerator *); 141 static int madt_ioapic_probe(struct ioapic_enumerator *); 142 143 static vm_paddr_t madt_phyaddr; 144 145 static void 146 madt_probe(void) 147 { 148 vm_paddr_t madt_paddr; 149 150 KKASSERT(madt_phyaddr == 0); 151 152 madt_paddr = sdt_search(ACPI_MADT_SIG); 153 if (madt_paddr == 0) { 154 kprintf("madt_probe: can't locate MADT\n"); 155 return; 156 } 157 158 /* Preliminary checks */ 159 if (madt_check(madt_paddr)) { 160 kprintf("madt_probe: madt_check failed\n"); 161 return; 162 } 163 164 madt_phyaddr = madt_paddr; 165 } 166 SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0); 167 168 static int 169 madt_check(vm_paddr_t madt_paddr) 170 { 171 struct acpi_madt *madt; 172 int error = 0; 173 174 KKASSERT(madt_paddr != 0); 175 176 madt = sdt_sdth_map(madt_paddr); 177 KKASSERT(madt != NULL); 178 179 /* 180 * MADT in ACPI specification 1.0 - 4.0 181 */ 182 if (madt->madt_hdr.sdth_rev < 1 || madt->madt_hdr.sdth_rev > 3) { 183 kprintf("madt_check: unknown MADT revision %d\n", 184 madt->madt_hdr.sdth_rev); 185 } 186 187 if (madt->madt_hdr.sdth_len < 188 sizeof(*madt) - sizeof(madt->madt_ents)) { 189 kprintf("madt_check: invalid MADT length %u\n", 190 madt->madt_hdr.sdth_len); 191 error = EINVAL; 192 goto back; 193 } 194 back: 195 sdt_sdth_unmap(&madt->madt_hdr); 196 return error; 197 } 198 199 static int 200 madt_iterate_entries(struct acpi_madt *madt, madt_iter_t func, void *arg) 201 { 202 int size, cur, error; 203 204 size = madt->madt_hdr.sdth_len - 205 (sizeof(*madt) - sizeof(madt->madt_ents)); 206 cur = 0; 207 error = 0; 208 209 while (size - cur > sizeof(struct acpi_madt_ent)) { 210 const struct acpi_madt_ent *ent; 211 212 ent = (const struct acpi_madt_ent *)&madt->madt_ents[cur]; 213 if (ent->me_len < sizeof(*ent)) { 214 kprintf("madt_iterate_entries: invalid MADT " 215 "entry len %d\n", ent->me_len); 216 error = EINVAL; 217 break; 218 } 219 if (ent->me_len > (size - cur)) { 220 kprintf("madt_iterate_entries: invalid MADT " 221 "entry len %d, > table length\n", ent->me_len); 222 error = EINVAL; 223 break; 224 } 225 226 cur += ent->me_len; 227 228 /* 229 * Only Local APIC, I/O APIC and Interrupt Source Override 230 * are defined in ACPI specification 1.0 - 4.0 231 */ 232 switch (ent->me_type) { 233 case MADT_ENT_LAPIC: 234 if (ent->me_len < sizeof(struct acpi_madt_lapic)) { 235 kprintf("madt_iterate_entries: invalid MADT " 236 "lapic entry len %d\n", ent->me_len); 237 error = EINVAL; 238 } 239 break; 240 241 case MADT_ENT_IOAPIC: 242 if (ent->me_len < sizeof(struct acpi_madt_ioapic)) { 243 kprintf("madt_iterate_entries: invalid MADT " 244 "ioapic entry len %d\n", ent->me_len); 245 error = EINVAL; 246 } 247 break; 248 249 case MADT_ENT_INTSRC: 250 if (ent->me_len < sizeof(struct acpi_madt_intsrc)) { 251 kprintf("madt_iterate_entries: invalid MADT " 252 "intsrc entry len %d\n", 253 ent->me_len); 254 error = EINVAL; 255 } 256 break; 257 } 258 if (error) 259 break; 260 261 error = func(arg, ent); 262 if (error) 263 break; 264 } 265 return error; 266 } 267 268 static int 269 madt_lapic_pass1_callback(void *xarg, const struct acpi_madt_ent *ent) 270 { 271 const struct acpi_madt_lapic_addr *lapic_addr_ent; 272 uint64_t *addr64 = xarg; 273 274 if (ent->me_type != MADT_ENT_LAPIC_ADDR) 275 return 0; 276 if (ent->me_len < sizeof(*lapic_addr_ent)) { 277 kprintf("madt_lapic_pass1: " 278 "invalid LAPIC address override length\n"); 279 return 0; 280 } 281 lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent; 282 283 *addr64 = lapic_addr_ent->mla_lapic_addr; 284 return 0; 285 } 286 287 static vm_paddr_t 288 madt_lapic_pass1(void) 289 { 290 struct acpi_madt *madt; 291 vm_paddr_t lapic_addr; 292 uint64_t lapic_addr64; 293 int error; 294 295 KKASSERT(madt_phyaddr != 0); 296 297 madt = sdt_sdth_map(madt_phyaddr); 298 KKASSERT(madt != NULL); 299 300 MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n", 301 madt->madt_lapic_addr, madt->madt_flags); 302 lapic_addr = madt->madt_lapic_addr; 303 304 lapic_addr64 = 0; 305 error = madt_iterate_entries(madt, madt_lapic_pass1_callback, 306 &lapic_addr64); 307 if (error) 308 panic("madt_iterate_entries(pass1) failed"); 309 310 if (lapic_addr64 != 0) { 311 kprintf("ACPI MADT: 64bits lapic address 0x%lx\n", 312 lapic_addr64); 313 lapic_addr = lapic_addr64; 314 } 315 316 sdt_sdth_unmap(&madt->madt_hdr); 317 318 return lapic_addr; 319 } 320 321 struct madt_lapic_pass2_cbarg { 322 int cpu; 323 int bsp_found; 324 int bsp_apic_id; 325 }; 326 327 static int 328 madt_lapic_pass2_callback(void *xarg, const struct acpi_madt_ent *ent) 329 { 330 const struct acpi_madt_lapic *lapic_ent; 331 struct madt_lapic_pass2_cbarg *arg = xarg; 332 333 if (ent->me_type != MADT_ENT_LAPIC) 334 return 0; 335 336 lapic_ent = (const struct acpi_madt_lapic *)ent; 337 if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED) { 338 MADT_VPRINTF("cpu id %d, apic id %d\n", 339 lapic_ent->ml_cpu_id, lapic_ent->ml_apic_id); 340 if (lapic_ent->ml_apic_id == arg->bsp_apic_id) { 341 lapic_set_cpuid(0, lapic_ent->ml_apic_id); 342 arg->bsp_found = 1; 343 } else { 344 lapic_set_cpuid(arg->cpu, lapic_ent->ml_apic_id); 345 arg->cpu++; 346 } 347 } 348 return 0; 349 } 350 351 static int 352 madt_lapic_pass2(int bsp_apic_id) 353 { 354 struct acpi_madt *madt; 355 struct madt_lapic_pass2_cbarg arg; 356 int error; 357 358 MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id); 359 360 KKASSERT(madt_phyaddr != 0); 361 362 madt = sdt_sdth_map(madt_phyaddr); 363 KKASSERT(madt != NULL); 364 365 bzero(&arg, sizeof(arg)); 366 arg.cpu = 1; 367 arg.bsp_apic_id = bsp_apic_id; 368 369 error = madt_iterate_entries(madt, madt_lapic_pass2_callback, &arg); 370 if (error) 371 panic("madt_iterate_entries(pass2) failed"); 372 373 KKASSERT(arg.bsp_found); 374 naps = arg.cpu - 1; /* exclude BSP */ 375 376 sdt_sdth_unmap(&madt->madt_hdr); 377 378 return 0; 379 } 380 381 struct madt_lapic_probe_cbarg { 382 int cpu_count; 383 vm_paddr_t lapic_addr; 384 }; 385 386 static int 387 madt_lapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) 388 { 389 struct madt_lapic_probe_cbarg *arg = xarg; 390 391 if (ent->me_type == MADT_ENT_LAPIC) { 392 const struct acpi_madt_lapic *lapic_ent; 393 394 lapic_ent = (const struct acpi_madt_lapic *)ent; 395 if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED) { 396 arg->cpu_count++; 397 if (lapic_ent->ml_apic_id == APICID_MAX) { 398 kprintf("madt_lapic_probe: " 399 "invalid LAPIC apic id %d\n", 400 lapic_ent->ml_apic_id); 401 return EINVAL; 402 } 403 } 404 } else if (ent->me_type == MADT_ENT_LAPIC_ADDR) { 405 const struct acpi_madt_lapic_addr *lapic_addr_ent; 406 407 if (ent->me_len < sizeof(*lapic_addr_ent)) { 408 kprintf("madt_lapic_probe: " 409 "invalid LAPIC address override length\n"); 410 return 0; 411 } 412 lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent; 413 414 if (lapic_addr_ent->mla_lapic_addr != 0) 415 arg->lapic_addr = lapic_addr_ent->mla_lapic_addr; 416 } 417 return 0; 418 } 419 420 static int 421 madt_lapic_probe(struct lapic_enumerator *e) 422 { 423 struct madt_lapic_probe_cbarg arg; 424 struct acpi_madt *madt; 425 int error; 426 427 if (madt_phyaddr == 0) 428 return ENXIO; 429 430 madt = sdt_sdth_map(madt_phyaddr); 431 KKASSERT(madt != NULL); 432 433 bzero(&arg, sizeof(arg)); 434 arg.lapic_addr = madt->madt_lapic_addr; 435 436 error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg); 437 if (!error) { 438 if (arg.cpu_count == 0) { 439 kprintf("madt_lapic_probe: no CPU is found\n"); 440 error = EOPNOTSUPP; 441 } 442 if (arg.lapic_addr == 0) { 443 kprintf("madt_lapic_probe: zero LAPIC address\n"); 444 error = EOPNOTSUPP; 445 } 446 } 447 448 sdt_sdth_unmap(&madt->madt_hdr); 449 return error; 450 } 451 452 static int 453 madt_lapic_enumerate(struct lapic_enumerator *e) 454 { 455 vm_paddr_t lapic_addr; 456 int bsp_apic_id; 457 458 KKASSERT(madt_phyaddr != 0); 459 460 lapic_addr = madt_lapic_pass1(); 461 if (lapic_addr == 0) 462 panic("madt_lapic_enumerate: no local apic"); 463 464 lapic_map(lapic_addr); 465 466 bsp_apic_id = APIC_ID(lapic->id); 467 if (bsp_apic_id == APICID_MAX) { 468 /* 469 * XXX 470 * Some old brain dead BIOS will set BSP's LAPIC apic id 471 * to 255, though all LAPIC entries in MADT are valid. 472 */ 473 kprintf("%s invalid BSP LAPIC apic id %d\n", __func__, 474 bsp_apic_id); 475 return EINVAL; 476 } 477 478 if (madt_lapic_pass2(bsp_apic_id)) 479 panic("madt_lapic_enumerate: madt_lapic_pass2 failed"); 480 481 return 0; 482 } 483 484 static struct lapic_enumerator madt_lapic_enumerator = { 485 .lapic_prio = LAPIC_ENUM_PRIO_MADT, 486 .lapic_probe = madt_lapic_probe, 487 .lapic_enumerate = madt_lapic_enumerate 488 }; 489 490 static void 491 madt_lapic_enum_register(void) 492 { 493 int prio; 494 495 prio = LAPIC_ENUM_PRIO_MADT; 496 kgetenv_int("hw.madt_lapic_prio", &prio); 497 madt_lapic_enumerator.lapic_prio = prio; 498 499 lapic_enumerator_register(&madt_lapic_enumerator); 500 } 501 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0); 502 503 struct madt_ioapic_probe_cbarg { 504 int ioapic_cnt; 505 int gsi_base0; 506 }; 507 508 static int 509 madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) 510 { 511 struct madt_ioapic_probe_cbarg *arg = xarg; 512 513 if (ent->me_type == MADT_ENT_INTSRC) { 514 const struct acpi_madt_intsrc *intsrc_ent; 515 int trig, pola; 516 517 intsrc_ent = (const struct acpi_madt_intsrc *)ent; 518 519 if (intsrc_ent->mint_src >= ISA_IRQ_CNT) { 520 kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n", 521 intsrc_ent->mint_src); 522 return EINVAL; 523 } 524 525 if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) { 526 kprintf("ACPI MADT: warning intsrc irq %d " 527 "bus is not ISA (%d)\n", 528 intsrc_ent->mint_src, intsrc_ent->mint_bus); 529 } 530 531 trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> 532 MADT_INT_TRIG_SHIFT; 533 if (trig == MADT_INT_TRIG_RSVD) { 534 kprintf("ACPI MADT: warning invalid intsrc irq %d " 535 "trig, reserved\n", intsrc_ent->mint_src); 536 } else if (trig == MADT_INT_TRIG_LEVEL) { 537 MADT_VPRINTF("warning invalid intsrc irq %d " 538 "trig, level\n", intsrc_ent->mint_src); 539 } 540 541 pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >> 542 MADT_INT_POLA_SHIFT; 543 if (pola == MADT_INT_POLA_RSVD) { 544 kprintf("ACPI MADT: warning invalid intsrc irq %d " 545 "pola, reserved\n", intsrc_ent->mint_src); 546 } else if (pola == MADT_INT_POLA_LOW) { 547 MADT_VPRINTF("warning invalid intsrc irq %d " 548 "pola, low\n", intsrc_ent->mint_src); 549 } 550 } else if (ent->me_type == MADT_ENT_IOAPIC) { 551 const struct acpi_madt_ioapic *ioapic_ent; 552 553 ioapic_ent = (const struct acpi_madt_ioapic *)ent; 554 if (ioapic_ent->mio_addr == 0) { 555 kprintf("madt_ioapic_probe: zero IOAPIC address\n"); 556 return EINVAL; 557 } 558 if (ioapic_ent->mio_apic_id == APICID_MAX) { 559 kprintf("madt_ioapic_probe: " 560 "invalid IOAPIC apic id %d\n", 561 ioapic_ent->mio_apic_id); 562 return EINVAL; 563 } 564 565 arg->ioapic_cnt++; 566 if (ioapic_ent->mio_gsi_base == 0) 567 arg->gsi_base0 = 1; 568 } 569 return 0; 570 } 571 572 static int 573 madt_ioapic_probe(struct ioapic_enumerator *e) 574 { 575 struct madt_ioapic_probe_cbarg arg; 576 struct acpi_madt *madt; 577 int error; 578 579 if (madt_phyaddr == 0) 580 return ENXIO; 581 582 madt = sdt_sdth_map(madt_phyaddr); 583 KKASSERT(madt != NULL); 584 585 bzero(&arg, sizeof(arg)); 586 587 error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg); 588 if (!error) { 589 if (arg.ioapic_cnt == 0) { 590 kprintf("madt_ioapic_probe: no IOAPIC\n"); 591 error = ENXIO; 592 } 593 if (!arg.gsi_base0) { 594 kprintf("madt_ioapic_probe: no GSI base 0\n"); 595 error = EINVAL; 596 } 597 } 598 599 sdt_sdth_unmap(&madt->madt_hdr); 600 return error; 601 } 602 603 static int 604 madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) 605 { 606 if (ent->me_type == MADT_ENT_INTSRC) { 607 const struct acpi_madt_intsrc *intsrc_ent; 608 enum intr_trigger trig; 609 enum intr_polarity pola; 610 int ent_trig, ent_pola; 611 612 intsrc_ent = (const struct acpi_madt_intsrc *)ent; 613 614 KKASSERT(intsrc_ent->mint_src < ISA_IRQ_CNT); 615 if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) 616 return 0; 617 618 ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> 619 MADT_INT_TRIG_SHIFT; 620 if (ent_trig == MADT_INT_TRIG_RSVD) 621 return 0; 622 else if (ent_trig == MADT_INT_TRIG_LEVEL) 623 trig = INTR_TRIGGER_LEVEL; 624 else 625 trig = INTR_TRIGGER_EDGE; 626 627 ent_pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >> 628 MADT_INT_POLA_SHIFT; 629 if (ent_pola == MADT_INT_POLA_RSVD) 630 return 0; 631 else if (ent_pola == MADT_INT_POLA_LOW) 632 pola = INTR_POLARITY_LOW; 633 else 634 pola = INTR_POLARITY_HIGH; 635 636 if (intsrc_ent->mint_src == acpi_sci_irqno()) { 637 acpi_sci_setmode1(trig, pola); 638 MADT_VPRINTF("SCI irq %d, first test %s/%s\n", 639 intsrc_ent->mint_src, 640 intr_str_trigger(trig), intr_str_polarity(pola)); 641 } 642 643 /* 644 * We ignore the polarity and trigger changes, since 645 * most of them are wrong or useless at best. 646 */ 647 if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) { 648 /* Nothing changed */ 649 return 0; 650 } 651 trig = INTR_TRIGGER_EDGE; 652 pola = INTR_POLARITY_HIGH; 653 654 MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n", 655 intsrc_ent->mint_src, intsrc_ent->mint_gsi, 656 intr_str_trigger(trig), intr_str_polarity(pola)); 657 ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi, 658 trig, pola); 659 } else if (ent->me_type == MADT_ENT_IOAPIC) { 660 const struct acpi_madt_ioapic *ioapic_ent; 661 uint32_t ver; 662 void *addr; 663 int npin; 664 665 ioapic_ent = (const struct acpi_madt_ioapic *)ent; 666 MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n", 667 ioapic_ent->mio_addr, ioapic_ent->mio_apic_id, 668 ioapic_ent->mio_gsi_base); 669 670 addr = ioapic_map(ioapic_ent->mio_addr); 671 672 ver = ioapic_read(addr, IOAPIC_VER); 673 npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; 674 675 ioapic_add(addr, ioapic_ent->mio_gsi_base, npin); 676 } 677 return 0; 678 } 679 680 static void 681 madt_ioapic_enumerate(struct ioapic_enumerator *e) 682 { 683 struct acpi_madt *madt; 684 int error; 685 686 KKASSERT(madt_phyaddr != 0); 687 688 madt = sdt_sdth_map(madt_phyaddr); 689 KKASSERT(madt != NULL); 690 691 error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL); 692 if (error) 693 panic("madt_ioapic_enumerate failed"); 694 695 sdt_sdth_unmap(&madt->madt_hdr); 696 } 697 698 static struct ioapic_enumerator madt_ioapic_enumerator = { 699 .ioapic_prio = IOAPIC_ENUM_PRIO_MADT, 700 .ioapic_probe = madt_ioapic_probe, 701 .ioapic_enumerate = madt_ioapic_enumerate 702 }; 703 704 static void 705 madt_ioapic_enum_register(void) 706 { 707 int prio; 708 709 prio = IOAPIC_ENUM_PRIO_MADT; 710 kgetenv_int("hw.madt_ioapic_prio", &prio); 711 madt_ioapic_enumerator.ioapic_prio = prio; 712 713 ioapic_enumerator_register(&madt_ioapic_enumerator); 714 } 715 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, 716 madt_ioapic_enum_register, 0); 717