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