1 /* 2 * Copyright (c) 1996, by Steve Passe 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. The name of the developer may NOT be used to endorse or promote products 11 * derived from this software without specific prior written permission. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $ 26 */ 27 28 #include "opt_cpu.h" 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/sysctl.h> 34 #include <sys/malloc.h> 35 #include <sys/memrange.h> 36 #include <sys/cons.h> /* cngetc() */ 37 #include <sys/machintr.h> 38 39 #include <sys/mplock2.h> 40 41 #include <vm/vm.h> 42 #include <vm/vm_param.h> 43 #include <vm/pmap.h> 44 #include <vm/vm_kern.h> 45 #include <vm/vm_extern.h> 46 #include <sys/lock.h> 47 #include <vm/vm_map.h> 48 49 #include <machine/smp.h> 50 #include <machine_base/isa/isa_intr.h> 51 #include <machine_base/apic/apicreg.h> 52 #include <machine_base/apic/apicvar.h> 53 #include <machine/atomic.h> 54 #include <machine/cpufunc.h> 55 #include <machine/cputypes.h> 56 #include <machine_base/apic/lapic.h> 57 #include <machine_base/apic/ioapic.h> 58 #include <machine/psl.h> 59 #include <machine/segments.h> 60 #include <machine/tss.h> 61 #include <machine/specialreg.h> 62 #include <machine/globaldata.h> 63 #include <machine/pmap_inval.h> 64 #include <machine/mptable.h> 65 66 #include <machine/md_var.h> /* setidt() */ 67 #include <machine_base/icu/icu.h> /* IPIs */ 68 #include <machine_base/apic/ioapic_abi.h> 69 #include <machine/intr_machdep.h> /* IPIs */ 70 71 extern u_int base_memory; 72 extern u_long ebda_addr; 73 extern int imcr_present; 74 extern int naps; 75 76 static int force_enable = 0; 77 TUNABLE_INT("hw.lapic_force_enable", &force_enable); 78 79 #define BIOS_BASE (0xf0000) 80 #define BIOS_BASE2 (0xe0000) 81 #define BIOS_SIZE (0x10000) 82 #define BIOS_COUNT (BIOS_SIZE/4) 83 84 #define PROCENTRY_FLAG_EN 0x01 85 #define PROCENTRY_FLAG_BP 0x02 86 #define IOAPICENTRY_FLAG_EN 0x01 87 88 89 /* MP Floating Pointer Structure */ 90 typedef struct MPFPS { 91 char signature[4]; 92 u_int32_t pap; 93 u_char length; 94 u_char spec_rev; 95 u_char checksum; 96 u_char mpfb1; 97 u_char mpfb2; 98 u_char mpfb3; 99 u_char mpfb4; 100 u_char mpfb5; 101 } *mpfps_t; 102 103 /* MP Configuration Table Header */ 104 typedef struct MPCTH { 105 char signature[4]; 106 u_short base_table_length; 107 u_char spec_rev; 108 u_char checksum; 109 u_char oem_id[8]; 110 u_char product_id[12]; 111 u_int32_t oem_table_pointer; 112 u_short oem_table_size; 113 u_short entry_count; 114 u_int32_t apic_address; 115 u_short extended_table_length; 116 u_char extended_table_checksum; 117 u_char reserved; 118 } *mpcth_t; 119 120 121 typedef struct PROCENTRY { 122 u_char type; 123 u_char apic_id; 124 u_char apic_version; 125 u_char cpu_flags; 126 u_int32_t cpu_signature; 127 u_int32_t feature_flags; 128 u_int32_t reserved1; 129 u_int32_t reserved2; 130 } *proc_entry_ptr; 131 132 typedef struct BUSENTRY { 133 u_char type; 134 u_char bus_id; 135 char bus_type[6]; 136 } *bus_entry_ptr; 137 138 typedef struct IOAPICENTRY { 139 u_char type; 140 u_char apic_id; 141 u_char apic_version; 142 u_char apic_flags; 143 u_int32_t apic_address; 144 } *io_apic_entry_ptr; 145 146 typedef struct INTENTRY { 147 u_char type; 148 u_char int_type; 149 u_short int_flags; 150 u_char src_bus_id; 151 u_char src_bus_irq; 152 u_char dst_apic_id; 153 u_char dst_apic_int; 154 } *int_entry_ptr; 155 156 /* descriptions of MP basetable entries */ 157 typedef struct BASETABLE_ENTRY { 158 u_char type; 159 u_char length; 160 char name[16]; 161 } basetable_entry; 162 163 struct mptable_pos { 164 mpfps_t mp_fps; 165 mpcth_t mp_cth; 166 vm_size_t mp_cth_mapsz; 167 }; 168 169 #define MPTABLE_POS_USE_DEFAULT(mpt) \ 170 ((mpt)->mp_fps->mpfb1 != 0 || (mpt)->mp_cth == NULL) 171 172 struct mptable_bus { 173 int mb_id; 174 int mb_type; /* MPTABLE_BUS_ */ 175 TAILQ_ENTRY(mptable_bus) mb_link; 176 }; 177 178 #define MPTABLE_BUS_ISA 0 179 #define MPTABLE_BUS_PCI 1 180 181 struct mptable_bus_info { 182 TAILQ_HEAD(, mptable_bus) mbi_list; 183 }; 184 185 struct mptable_pci_int { 186 int mpci_bus; 187 int mpci_dev; 188 int mpci_pin; 189 190 int mpci_ioapic_idx; 191 int mpci_ioapic_pin; 192 TAILQ_ENTRY(mptable_pci_int) mpci_link; 193 }; 194 195 struct mptable_ioapic { 196 int mio_idx; 197 int mio_apic_id; 198 uint32_t mio_addr; 199 int mio_gsi_base; 200 int mio_npin; 201 TAILQ_ENTRY(mptable_ioapic) mio_link; 202 }; 203 204 typedef int (*mptable_iter_func)(void *, const void *, int); 205 206 static int mptable_iterate_entries(const mpcth_t, 207 mptable_iter_func, void *); 208 static int mptable_search(void); 209 static long mptable_search_sig(u_int32_t target, int count); 210 static int mptable_hyperthread_fixup(cpumask_t, int); 211 static int mptable_map(struct mptable_pos *); 212 static void mptable_unmap(struct mptable_pos *); 213 static void mptable_bus_info_alloc(const mpcth_t, 214 struct mptable_bus_info *); 215 static void mptable_bus_info_free(struct mptable_bus_info *); 216 217 static int mptable_lapic_probe(struct lapic_enumerator *); 218 static int mptable_lapic_enumerate(struct lapic_enumerator *); 219 static void mptable_lapic_default(void); 220 221 static int mptable_ioapic_probe(struct ioapic_enumerator *); 222 static void mptable_ioapic_enumerate(struct ioapic_enumerator *); 223 224 static basetable_entry basetable_entry_types[] = 225 { 226 {0, 20, "Processor"}, 227 {1, 8, "Bus"}, 228 {2, 8, "I/O APIC"}, 229 {3, 8, "I/O INT"}, 230 {4, 8, "Local INT"} 231 }; 232 233 static vm_paddr_t mptable_fps_phyaddr; 234 static int mptable_use_default; 235 static TAILQ_HEAD(mptable_pci_int_list, mptable_pci_int) mptable_pci_int_list = 236 TAILQ_HEAD_INITIALIZER(mptable_pci_int_list); 237 static TAILQ_HEAD(mptable_ioapic_list, mptable_ioapic) mptable_ioapic_list = 238 TAILQ_HEAD_INITIALIZER(mptable_ioapic_list); 239 240 static void 241 mptable_probe(void) 242 { 243 struct mptable_pos mpt; 244 int error; 245 246 KKASSERT(mptable_fps_phyaddr == 0); 247 248 mptable_fps_phyaddr = mptable_search(); 249 if (mptable_fps_phyaddr == 0) 250 return; 251 252 error = mptable_map(&mpt); 253 if (error) { 254 mptable_fps_phyaddr = 0; 255 return; 256 } 257 258 if (MPTABLE_POS_USE_DEFAULT(&mpt)) { 259 kprintf("MPTABLE: use default configuration\n"); 260 mptable_use_default = 1; 261 } 262 if (mpt.mp_fps->mpfb2 & 0x80) 263 imcr_present = 1; 264 265 mptable_unmap(&mpt); 266 } 267 SYSINIT(mptable_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, mptable_probe, 0); 268 269 /* 270 * Look for an Intel MP spec table (ie, SMP capable hardware). 271 */ 272 static int 273 mptable_search(void) 274 { 275 long x; 276 u_int32_t target; 277 278 /* see if EBDA exists */ 279 if (ebda_addr != 0) { 280 /* search first 1K of EBDA */ 281 target = (u_int32_t)ebda_addr; 282 if ((x = mptable_search_sig(target, 1024 / 4)) > 0) 283 return x; 284 } else { 285 /* last 1K of base memory, effective 'top of base' passed in */ 286 target = (u_int32_t)(base_memory - 0x400); 287 if ((x = mptable_search_sig(target, 1024 / 4)) > 0) 288 return x; 289 } 290 291 /* search the BIOS */ 292 target = (u_int32_t)BIOS_BASE; 293 if ((x = mptable_search_sig(target, BIOS_COUNT)) > 0) 294 return x; 295 296 /* search the extended BIOS */ 297 target = (u_int32_t)BIOS_BASE2; 298 if ((x = mptable_search_sig(target, BIOS_COUNT)) > 0) 299 return x; 300 301 /* nothing found */ 302 return 0; 303 } 304 305 static int 306 mptable_iterate_entries(const mpcth_t cth, mptable_iter_func func, void *arg) 307 { 308 int count, total_size; 309 const void *position; 310 311 KKASSERT(cth->base_table_length >= sizeof(struct MPCTH)); 312 total_size = cth->base_table_length - sizeof(struct MPCTH); 313 position = (const uint8_t *)cth + sizeof(struct MPCTH); 314 count = cth->entry_count; 315 316 while (count--) { 317 int type, error; 318 319 KKASSERT(total_size >= 0); 320 if (total_size == 0) { 321 kprintf("invalid base MP table, " 322 "entry count and length mismatch\n"); 323 return EINVAL; 324 } 325 326 type = *(const uint8_t *)position; 327 switch (type) { 328 case 0: /* processor_entry */ 329 case 1: /* bus_entry */ 330 case 2: /* io_apic_entry */ 331 case 3: /* int_entry */ 332 case 4: /* int_entry */ 333 break; 334 default: 335 kprintf("unknown base MP table entry type %d\n", type); 336 return EINVAL; 337 } 338 339 if (total_size < basetable_entry_types[type].length) { 340 kprintf("invalid base MP table length, " 341 "does not contain all entries\n"); 342 return EINVAL; 343 } 344 total_size -= basetable_entry_types[type].length; 345 346 error = func(arg, position, type); 347 if (error) 348 return error; 349 350 position = (const uint8_t *)position + 351 basetable_entry_types[type].length; 352 } 353 return 0; 354 } 355 356 /* 357 * look for the MP spec signature 358 */ 359 360 /* string defined by the Intel MP Spec as identifying the MP table */ 361 #define MP_SIG 0x5f504d5f /* _MP_ */ 362 #define NEXT(X) ((X) += 4) 363 static long 364 mptable_search_sig(u_int32_t target, int count) 365 { 366 vm_size_t map_size; 367 u_int32_t *addr; 368 int x, ret; 369 370 KKASSERT(target != 0); 371 372 map_size = count * sizeof(u_int32_t); 373 addr = pmap_mapdev((vm_paddr_t)target, map_size); 374 375 ret = 0; 376 for (x = 0; x < count; NEXT(x)) { 377 if (addr[x] == MP_SIG) { 378 /* make array index a byte index */ 379 ret = target + (x * sizeof(u_int32_t)); 380 break; 381 } 382 } 383 384 pmap_unmapdev((vm_offset_t)addr, map_size); 385 return ret; 386 } 387 388 static int processor_entry (const struct PROCENTRY *entry, int cpu); 389 390 /* 391 * Check if we should perform a hyperthreading "fix-up" to 392 * enumerate any logical CPU's that aren't already listed 393 * in the table. 394 * 395 * XXX: We assume that all of the physical CPUs in the 396 * system have the same number of logical CPUs. 397 * 398 * XXX: We assume that APIC ID's are allocated such that 399 * the APIC ID's for a physical processor are aligned 400 * with the number of logical CPU's in the processor. 401 */ 402 static int 403 mptable_hyperthread_fixup(cpumask_t id_mask, int cpu_count) 404 { 405 int i, id, lcpus_max, logical_cpus; 406 407 if ((cpu_feature & CPUID_HTT) == 0) 408 return 0; 409 410 lcpus_max = (cpu_procinfo & CPUID_HTT_CORES) >> 16; 411 if (lcpus_max <= 1) 412 return 0; 413 414 if (cpu_vendor_id == CPU_VENDOR_INTEL) { 415 /* 416 * INSTRUCTION SET REFERENCE, A-M (#253666) 417 * Page 3-181, Table 3-20 418 * "The nearest power-of-2 integer that is not smaller 419 * than EBX[23:16] is the number of unique initial APIC 420 * IDs reserved for addressing different logical 421 * processors in a physical package." 422 */ 423 for (i = 0; ; ++i) { 424 if ((1 << i) >= lcpus_max) { 425 lcpus_max = 1 << i; 426 break; 427 } 428 } 429 } 430 431 KKASSERT(cpu_count != 0); 432 if (cpu_count == lcpus_max) { 433 /* We have nothing to fix */ 434 return 0; 435 } else if (cpu_count == 1) { 436 /* XXX this may be incorrect */ 437 logical_cpus = lcpus_max; 438 } else { 439 int cur, prev, dist; 440 441 /* 442 * Calculate the distances between two nearest 443 * APIC IDs. If all such distances are same, 444 * then it is the number of missing cpus that 445 * we are going to fill later. 446 */ 447 dist = cur = prev = -1; 448 for (id = 0; id < MAXCPU; ++id) { 449 if (CPUMASK_TESTBIT(id_mask, id) == 0) 450 continue; 451 452 cur = id; 453 if (prev >= 0) { 454 int new_dist = cur - prev; 455 456 if (dist < 0) 457 dist = new_dist; 458 459 /* 460 * Make sure that all distances 461 * between two nearest APIC IDs 462 * are same. 463 */ 464 if (dist != new_dist) 465 return 0; 466 } 467 prev = cur; 468 } 469 if (dist == 1) 470 return 0; 471 472 /* Must be power of 2 */ 473 if (dist & (dist - 1)) 474 return 0; 475 476 /* Can't exceed CPU package capacity */ 477 if (dist > lcpus_max) 478 logical_cpus = lcpus_max; 479 else 480 logical_cpus = dist; 481 } 482 483 /* 484 * For each APIC ID of a CPU that is set in the mask, 485 * scan the other candidate APIC ID's for this 486 * physical processor. If any of those ID's are 487 * already in the table, then kill the fixup. 488 */ 489 for (id = 0; id < MAXCPU; id++) { 490 if (CPUMASK_TESTBIT(id_mask, id) == 0) 491 continue; 492 /* First, make sure we are on a logical_cpus boundary. */ 493 if (id % logical_cpus != 0) 494 return 0; 495 for (i = id + 1; i < id + logical_cpus; i++) 496 if (CPUMASK_TESTBIT(id_mask, i) != 0) 497 return 0; 498 } 499 return logical_cpus; 500 } 501 502 static int 503 mptable_map(struct mptable_pos *mpt) 504 { 505 mpfps_t fps = NULL; 506 mpcth_t cth = NULL; 507 vm_size_t cth_mapsz = 0; 508 509 KKASSERT(mptable_fps_phyaddr != 0); 510 511 bzero(mpt, sizeof(*mpt)); 512 513 fps = pmap_mapdev(mptable_fps_phyaddr, sizeof(*fps)); 514 if (fps->pap != 0) { 515 /* 516 * Map configuration table header to get 517 * the base table size 518 */ 519 cth = pmap_mapdev(fps->pap, sizeof(*cth)); 520 cth_mapsz = cth->base_table_length; 521 pmap_unmapdev((vm_offset_t)cth, sizeof(*cth)); 522 523 if (cth_mapsz < sizeof(*cth)) { 524 kprintf("invalid base MP table length %d\n", 525 (int)cth_mapsz); 526 pmap_unmapdev((vm_offset_t)fps, sizeof(*fps)); 527 return EINVAL; 528 } 529 530 /* 531 * Map the base table 532 */ 533 cth = pmap_mapdev(fps->pap, cth_mapsz); 534 } 535 536 mpt->mp_fps = fps; 537 mpt->mp_cth = cth; 538 mpt->mp_cth_mapsz = cth_mapsz; 539 540 return 0; 541 } 542 543 static void 544 mptable_unmap(struct mptable_pos *mpt) 545 { 546 if (mpt->mp_cth != NULL) { 547 pmap_unmapdev((vm_offset_t)mpt->mp_cth, mpt->mp_cth_mapsz); 548 mpt->mp_cth = NULL; 549 mpt->mp_cth_mapsz = 0; 550 } 551 if (mpt->mp_fps != NULL) { 552 pmap_unmapdev((vm_offset_t)mpt->mp_fps, sizeof(*mpt->mp_fps)); 553 mpt->mp_fps = NULL; 554 } 555 } 556 557 static int 558 processor_entry(const struct PROCENTRY *entry, int cpu) 559 { 560 KKASSERT(cpu > 0); 561 562 /* check for usability */ 563 if (!(entry->cpu_flags & PROCENTRY_FLAG_EN)) 564 return 0; 565 566 /* check for BSP flag */ 567 if (entry->cpu_flags & PROCENTRY_FLAG_BP) { 568 lapic_set_cpuid(0, entry->apic_id); 569 return 0; /* its already been counted */ 570 } 571 572 /* add another AP to list, if less than max number of CPUs */ 573 else if (cpu < MAXCPU) { 574 lapic_set_cpuid(cpu, entry->apic_id); 575 return 1; 576 } 577 578 return 0; 579 } 580 581 static int 582 mptable_bus_info_callback(void *xarg, const void *pos, int type) 583 { 584 struct mptable_bus_info *bus_info = xarg; 585 const struct BUSENTRY *ent; 586 struct mptable_bus *bus; 587 588 if (type != 1) 589 return 0; 590 591 ent = pos; 592 TAILQ_FOREACH(bus, &bus_info->mbi_list, mb_link) { 593 if (bus->mb_id == ent->bus_id) { 594 kprintf("mptable_bus_info_alloc: duplicated bus id " 595 "(%d)\n", bus->mb_id); 596 return EINVAL; 597 } 598 } 599 600 bus = NULL; 601 if (strncmp(ent->bus_type, "PCI", 3) == 0) { 602 bus = kmalloc(sizeof(*bus), M_TEMP, M_WAITOK | M_ZERO); 603 bus->mb_type = MPTABLE_BUS_PCI; 604 } else if (strncmp(ent->bus_type, "ISA", 3) == 0) { 605 bus = kmalloc(sizeof(*bus), M_TEMP, M_WAITOK | M_ZERO); 606 bus->mb_type = MPTABLE_BUS_ISA; 607 } 608 609 if (bus != NULL) { 610 bus->mb_id = ent->bus_id; 611 TAILQ_INSERT_TAIL(&bus_info->mbi_list, bus, mb_link); 612 } 613 return 0; 614 } 615 616 static void 617 mptable_bus_info_alloc(const mpcth_t cth, struct mptable_bus_info *bus_info) 618 { 619 int error; 620 621 bzero(bus_info, sizeof(*bus_info)); 622 TAILQ_INIT(&bus_info->mbi_list); 623 624 error = mptable_iterate_entries(cth, mptable_bus_info_callback, bus_info); 625 if (error) 626 mptable_bus_info_free(bus_info); 627 } 628 629 static void 630 mptable_bus_info_free(struct mptable_bus_info *bus_info) 631 { 632 struct mptable_bus *bus; 633 634 while ((bus = TAILQ_FIRST(&bus_info->mbi_list)) != NULL) { 635 TAILQ_REMOVE(&bus_info->mbi_list, bus, mb_link); 636 kfree(bus, M_TEMP); 637 } 638 } 639 640 struct mptable_lapic_cbarg1 { 641 int cpu_count; 642 int ht_fixup; 643 u_int ht_apicid_mask; 644 }; 645 646 static int 647 mptable_lapic_pass1_callback(void *xarg, const void *pos, int type) 648 { 649 const struct PROCENTRY *ent; 650 struct mptable_lapic_cbarg1 *arg = xarg; 651 652 if (type != 0) 653 return 0; 654 ent = pos; 655 656 if ((ent->cpu_flags & PROCENTRY_FLAG_EN) == 0) 657 return 0; 658 659 arg->cpu_count++; 660 if (ent->apic_id < 64) { 661 arg->ht_apicid_mask |= 1UL << ent->apic_id; 662 } else if (arg->ht_fixup) { 663 kprintf("MPTABLE: lapic id > 64, disable HTT fixup\n"); 664 arg->ht_fixup = 0; 665 } 666 return 0; 667 } 668 669 struct mptable_lapic_cbarg2 { 670 int cpu; 671 int logical_cpus; 672 int found_bsp; 673 }; 674 675 static int 676 mptable_lapic_pass2_callback(void *xarg, const void *pos, int type) 677 { 678 const struct PROCENTRY *ent; 679 struct mptable_lapic_cbarg2 *arg = xarg; 680 681 if (type != 0) 682 return 0; 683 ent = pos; 684 685 if (ent->cpu_flags & PROCENTRY_FLAG_BP) { 686 KKASSERT(!arg->found_bsp); 687 arg->found_bsp = 1; 688 } 689 690 if (processor_entry(ent, arg->cpu)) 691 arg->cpu++; 692 693 if (arg->logical_cpus) { 694 struct PROCENTRY proc; 695 int i; 696 697 /* 698 * Create fake mptable processor entries 699 * and feed them to processor_entry() to 700 * enumerate the logical CPUs. 701 */ 702 bzero(&proc, sizeof(proc)); 703 proc.type = 0; 704 proc.cpu_flags = (force_enable) ? PROCENTRY_FLAG_EN : ent->cpu_flags; 705 proc.apic_id = ent->apic_id; 706 707 for (i = 1; i < arg->logical_cpus; i++) { 708 proc.apic_id++; 709 processor_entry(&proc, arg->cpu); 710 arg->cpu++; 711 } 712 } 713 return 0; 714 } 715 716 static void 717 mptable_lapic_default(void) 718 { 719 int ap_apicid, bsp_apicid; 720 721 naps = 1; /* exclude BSP */ 722 723 /* Map local apic before the id field is accessed */ 724 lapic_map(DEFAULT_APIC_BASE); 725 726 bsp_apicid = LAPIC_READID; 727 ap_apicid = (bsp_apicid == 0) ? 1 : 0; 728 729 /* BSP */ 730 lapic_set_cpuid(0, bsp_apicid); 731 /* one and only AP */ 732 lapic_set_cpuid(1, ap_apicid); 733 } 734 735 /* 736 * Configure: 737 * naps 738 * APIC ID <-> CPU ID mappings 739 */ 740 static int 741 mptable_lapic_enumerate(struct lapic_enumerator *e) 742 { 743 struct mptable_pos mpt; 744 struct mptable_lapic_cbarg1 arg1; 745 struct mptable_lapic_cbarg2 arg2; 746 mpcth_t cth; 747 int error, logical_cpus = 0; 748 vm_paddr_t lapic_addr; 749 750 if (mptable_use_default) { 751 mptable_lapic_default(); 752 return 0; 753 } 754 755 error = mptable_map(&mpt); 756 if (error) 757 panic("mptable_lapic_enumerate mptable_map failed"); 758 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 759 760 cth = mpt.mp_cth; 761 762 /* Save local apic address */ 763 lapic_addr = cth->apic_address; 764 KKASSERT(lapic_addr != 0); 765 766 /* 767 * Find out how many CPUs do we have 768 */ 769 bzero(&arg1, sizeof(arg1)); 770 arg1.ht_fixup = 1; /* Apply ht fixup by default */ 771 772 error = mptable_iterate_entries(cth, 773 mptable_lapic_pass1_callback, &arg1); 774 if (error) 775 panic("mptable_iterate_entries(lapic_pass1) failed"); 776 KKASSERT(arg1.cpu_count != 0); 777 778 /* See if we need to fixup HT logical CPUs. */ 779 /* 780 * XXX fixup for cpus >= 32 ? XXX 781 */ 782 if (arg1.ht_fixup) { 783 cpumask_t mask; 784 785 CPUMASK_ASSZERO(mask); 786 mask.ary[0] = arg1.ht_apicid_mask; 787 logical_cpus = mptable_hyperthread_fixup(mask, arg1.cpu_count); 788 if (logical_cpus != 0) 789 arg1.cpu_count *= logical_cpus; 790 } 791 naps = arg1.cpu_count - 1; /* subtract the BSP */ 792 793 /* 794 * Link logical CPU id to local apic id 795 */ 796 bzero(&arg2, sizeof(arg2)); 797 arg2.cpu = 1; 798 arg2.logical_cpus = logical_cpus; 799 800 error = mptable_iterate_entries(cth, 801 mptable_lapic_pass2_callback, &arg2); 802 if (error) 803 panic("mptable_iterate_entries(lapic_pass2) failed"); 804 KKASSERT(arg2.found_bsp); 805 806 /* Map local apic */ 807 lapic_map(lapic_addr); 808 809 mptable_unmap(&mpt); 810 811 return 0; 812 } 813 814 struct mptable_lapic_probe_cbarg { 815 int cpu_count; 816 int found_bsp; 817 }; 818 819 static int 820 mptable_lapic_probe_callback(void *xarg, const void *pos, int type) 821 { 822 const struct PROCENTRY *ent; 823 struct mptable_lapic_probe_cbarg *arg = xarg; 824 825 if (type != 0) 826 return 0; 827 ent = pos; 828 829 if ((ent->cpu_flags & PROCENTRY_FLAG_EN) == 0) 830 return 0; 831 arg->cpu_count++; 832 833 if (ent->apic_id == APICID_MAX) { 834 kprintf("MPTABLE: invalid LAPIC apic id %d\n", 835 ent->apic_id); 836 return EINVAL; 837 } 838 839 if (ent->cpu_flags & PROCENTRY_FLAG_BP) { 840 if (arg->found_bsp) { 841 kprintf("more than one BSP in base MP table\n"); 842 return EINVAL; 843 } 844 arg->found_bsp = 1; 845 } 846 return 0; 847 } 848 849 static int 850 mptable_lapic_probe(struct lapic_enumerator *e) 851 { 852 struct mptable_pos mpt; 853 struct mptable_lapic_probe_cbarg arg; 854 mpcth_t cth; 855 int error; 856 857 if (mptable_fps_phyaddr == 0) 858 return ENXIO; 859 860 if (mptable_use_default) 861 return 0; 862 863 error = mptable_map(&mpt); 864 if (error) 865 return error; 866 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 867 868 error = EINVAL; 869 cth = mpt.mp_cth; 870 871 if (cth->apic_address == 0) 872 goto done; 873 874 bzero(&arg, sizeof(arg)); 875 error = mptable_iterate_entries(cth, 876 mptable_lapic_probe_callback, &arg); 877 if (!error) { 878 if (arg.cpu_count == 0) { 879 kprintf("MP table contains no processor entries\n"); 880 error = EINVAL; 881 } else if (!arg.found_bsp) { 882 kprintf("MP table does not contains BSP entry\n"); 883 error = EINVAL; 884 } 885 } 886 done: 887 mptable_unmap(&mpt); 888 return error; 889 } 890 891 static struct lapic_enumerator mptable_lapic_enumerator = { 892 .lapic_prio = LAPIC_ENUM_PRIO_MPTABLE, 893 .lapic_probe = mptable_lapic_probe, 894 .lapic_enumerate = mptable_lapic_enumerate 895 }; 896 897 static void 898 mptable_lapic_enum_register(void) 899 { 900 lapic_enumerator_register(&mptable_lapic_enumerator); 901 } 902 SYSINIT(mptable_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, 903 mptable_lapic_enum_register, 0); 904 905 static int 906 mptable_ioapic_list_callback(void *xarg, const void *pos, int type) 907 { 908 const struct IOAPICENTRY *ent; 909 struct mptable_ioapic *nioapic, *ioapic; 910 911 if (type != 2) 912 return 0; 913 ent = pos; 914 915 if ((ent->apic_flags & IOAPICENTRY_FLAG_EN) == 0) 916 return 0; 917 918 if (ent->apic_address == 0) { 919 kprintf("mptable_ioapic_create_list: zero IOAPIC addr\n"); 920 return EINVAL; 921 } 922 if (ent->apic_id == APICID_MAX) { 923 kprintf("mptable_ioapic_create_list: " 924 "invalid IOAPIC apic id %d\n", ent->apic_id); 925 return EINVAL; 926 } 927 928 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 929 if (ioapic->mio_apic_id == ent->apic_id) { 930 kprintf("mptable_ioapic_create_list: duplicated " 931 "apic id %d\n", ioapic->mio_apic_id); 932 return EINVAL; 933 } 934 if (ioapic->mio_addr == ent->apic_address) { 935 kprintf("mptable_ioapic_create_list: overlapped " 936 "IOAPIC addr 0x%08x", ioapic->mio_addr); 937 return EINVAL; 938 } 939 } 940 941 nioapic = kmalloc(sizeof(*nioapic), M_DEVBUF, M_WAITOK | M_ZERO); 942 nioapic->mio_apic_id = ent->apic_id; 943 nioapic->mio_addr = ent->apic_address; 944 945 /* 946 * Create IOAPIC list in ascending order of APIC ID 947 */ 948 TAILQ_FOREACH_REVERSE(ioapic, &mptable_ioapic_list, 949 mptable_ioapic_list, mio_link) { 950 if (nioapic->mio_apic_id > ioapic->mio_apic_id) { 951 TAILQ_INSERT_AFTER(&mptable_ioapic_list, 952 ioapic, nioapic, mio_link); 953 break; 954 } 955 } 956 if (ioapic == NULL) 957 TAILQ_INSERT_HEAD(&mptable_ioapic_list, nioapic, mio_link); 958 959 return 0; 960 } 961 962 static void 963 mptable_ioapic_create_list(void) 964 { 965 struct mptable_ioapic *ioapic; 966 struct mptable_pos mpt; 967 int idx, error; 968 969 if (mptable_fps_phyaddr == 0) 970 return; 971 972 if (mptable_use_default) { 973 ioapic = kmalloc(sizeof(*ioapic), M_DEVBUF, M_WAITOK | M_ZERO); 974 ioapic->mio_idx = 0; 975 ioapic->mio_apic_id = 0; /* NOTE: any value is ok here */ 976 ioapic->mio_addr = 0xfec00000; /* XXX magic number */ 977 978 TAILQ_INSERT_HEAD(&mptable_ioapic_list, ioapic, mio_link); 979 return; 980 } 981 982 error = mptable_map(&mpt); 983 if (error) 984 panic("mptable_ioapic_create_list: mptable_map failed"); 985 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 986 987 error = mptable_iterate_entries(mpt.mp_cth, 988 mptable_ioapic_list_callback, NULL); 989 if (error) { 990 while ((ioapic = TAILQ_FIRST(&mptable_ioapic_list)) != NULL) { 991 TAILQ_REMOVE(&mptable_ioapic_list, ioapic, mio_link); 992 kfree(ioapic, M_DEVBUF); 993 } 994 goto done; 995 } 996 997 /* 998 * Assign index number for each IOAPIC 999 */ 1000 idx = 0; 1001 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 1002 ioapic->mio_idx = idx; 1003 ++idx; 1004 } 1005 done: 1006 mptable_unmap(&mpt); 1007 } 1008 SYSINIT(mptable_ioapic_list, SI_BOOT2_PRESMP, SI_ORDER_SECOND, 1009 mptable_ioapic_create_list, 0); 1010 1011 static int 1012 mptable_pci_int_callback(void *xarg, const void *pos, int type) 1013 { 1014 const struct mptable_bus_info *bus_info = xarg; 1015 const struct mptable_ioapic *ioapic; 1016 const struct mptable_bus *bus; 1017 struct mptable_pci_int *pci_int; 1018 const struct INTENTRY *ent; 1019 int pci_pin, pci_dev; 1020 1021 if (type != 3) 1022 return 0; 1023 ent = pos; 1024 1025 if (ent->int_type != 0) 1026 return 0; 1027 1028 TAILQ_FOREACH(bus, &bus_info->mbi_list, mb_link) { 1029 if (bus->mb_type == MPTABLE_BUS_PCI && 1030 bus->mb_id == ent->src_bus_id) 1031 break; 1032 } 1033 if (bus == NULL) 1034 return 0; 1035 1036 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 1037 if (ioapic->mio_apic_id == ent->dst_apic_id) 1038 break; 1039 } 1040 if (ioapic == NULL) { 1041 if (bootverbose) { 1042 static char intdis_warned[64]; 1043 int apic_id = ent->dst_apic_id; 1044 int warn = 0; 1045 1046 if (apic_id < 0 || apic_id >= sizeof(intdis_warned)) { 1047 warn = 1; 1048 } else if (intdis_warned[apic_id] == 0) { 1049 intdis_warned[apic_id] = 1; 1050 warn = 1; 1051 } 1052 if (warn) { 1053 kprintf("MPTABLE: warning PCI int dst apic id " 1054 "%d does not exist\n", apic_id); 1055 } 1056 } 1057 return 0; 1058 } 1059 1060 pci_pin = ent->src_bus_irq & 0x3; 1061 pci_dev = (ent->src_bus_irq >> 2) & 0x1f; 1062 1063 TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) { 1064 if (pci_int->mpci_bus == ent->src_bus_id && 1065 pci_int->mpci_dev == pci_dev && 1066 pci_int->mpci_pin == pci_pin) { 1067 if (pci_int->mpci_ioapic_idx == ioapic->mio_idx && 1068 pci_int->mpci_ioapic_pin == ent->dst_apic_int) { 1069 kprintf("MPTABLE: warning duplicated " 1070 "PCI int entry for " 1071 "bus %d, dev %d, pin %d\n", 1072 pci_int->mpci_bus, 1073 pci_int->mpci_dev, 1074 pci_int->mpci_pin); 1075 return 0; 1076 } else { 1077 kprintf("mptable_pci_int_register: " 1078 "conflict PCI int entry for " 1079 "bus %d, dev %d, pin %d, " 1080 "IOAPIC %d.%d -> %d.%d\n", 1081 pci_int->mpci_bus, 1082 pci_int->mpci_dev, 1083 pci_int->mpci_pin, 1084 pci_int->mpci_ioapic_idx, 1085 pci_int->mpci_ioapic_pin, 1086 ioapic->mio_idx, 1087 ent->dst_apic_int); 1088 return EINVAL; 1089 } 1090 } 1091 } 1092 1093 pci_int = kmalloc(sizeof(*pci_int), M_DEVBUF, M_WAITOK | M_ZERO); 1094 1095 pci_int->mpci_bus = ent->src_bus_id; 1096 pci_int->mpci_dev = pci_dev; 1097 pci_int->mpci_pin = pci_pin; 1098 pci_int->mpci_ioapic_idx = ioapic->mio_idx; 1099 pci_int->mpci_ioapic_pin = ent->dst_apic_int; 1100 1101 TAILQ_INSERT_TAIL(&mptable_pci_int_list, pci_int, mpci_link); 1102 1103 return 0; 1104 } 1105 1106 static void 1107 mptable_pci_int_register(void) 1108 { 1109 struct mptable_bus_info bus_info; 1110 const struct mptable_bus *bus; 1111 struct mptable_pci_int *pci_int; 1112 struct mptable_pos mpt; 1113 int error, force_pci0, npcibus; 1114 mpcth_t cth; 1115 1116 if (mptable_fps_phyaddr == 0) 1117 return; 1118 1119 if (mptable_use_default) 1120 return; 1121 1122 if (TAILQ_EMPTY(&mptable_ioapic_list)) 1123 return; 1124 1125 error = mptable_map(&mpt); 1126 if (error) 1127 panic("mptable_pci_int_register: mptable_map failed"); 1128 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 1129 1130 cth = mpt.mp_cth; 1131 1132 mptable_bus_info_alloc(cth, &bus_info); 1133 if (TAILQ_EMPTY(&bus_info.mbi_list)) 1134 goto done; 1135 1136 force_pci0 = 0; 1137 npcibus = 0; 1138 TAILQ_FOREACH(bus, &bus_info.mbi_list, mb_link) { 1139 if (bus->mb_type == MPTABLE_BUS_PCI) 1140 ++npcibus; 1141 } 1142 if (npcibus == 0) { 1143 mptable_bus_info_free(&bus_info); 1144 goto done; 1145 } else if (npcibus == 1) { 1146 force_pci0 = 1; 1147 } 1148 1149 error = mptable_iterate_entries(cth, 1150 mptable_pci_int_callback, &bus_info); 1151 1152 mptable_bus_info_free(&bus_info); 1153 1154 if (error) { 1155 while ((pci_int = TAILQ_FIRST(&mptable_pci_int_list)) != NULL) { 1156 TAILQ_REMOVE(&mptable_pci_int_list, pci_int, mpci_link); 1157 kfree(pci_int, M_DEVBUF); 1158 } 1159 goto done; 1160 } 1161 1162 if (force_pci0) { 1163 TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) 1164 pci_int->mpci_bus = 0; 1165 } 1166 done: 1167 mptable_unmap(&mpt); 1168 } 1169 SYSINIT(mptable_pci, SI_BOOT2_PRESMP, SI_ORDER_ANY, 1170 mptable_pci_int_register, 0); 1171 1172 struct mptable_ioapic_probe_cbarg { 1173 const struct mptable_bus_info *bus_info; 1174 }; 1175 1176 static int 1177 mptable_ioapic_probe_callback(void *xarg, const void *pos, int type) 1178 { 1179 struct mptable_ioapic_probe_cbarg *arg = xarg; 1180 const struct mptable_ioapic *ioapic; 1181 const struct mptable_bus *bus; 1182 const struct INTENTRY *ent; 1183 1184 if (type != 3) 1185 return 0; 1186 ent = pos; 1187 1188 if (ent->int_type != 0) 1189 return 0; 1190 1191 TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) { 1192 if (bus->mb_type == MPTABLE_BUS_ISA && 1193 bus->mb_id == ent->src_bus_id) 1194 break; 1195 } 1196 if (bus == NULL) 1197 return 0; 1198 1199 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 1200 if (ioapic->mio_apic_id == ent->dst_apic_id) 1201 break; 1202 } 1203 if (ioapic == NULL) { 1204 kprintf("MPTABLE: warning ISA int dst apic id %d " 1205 "does not exist\n", ent->dst_apic_id); 1206 return 0; 1207 } 1208 1209 /* XXX magic number */ 1210 if (ent->src_bus_irq >= ISA_IRQ_CNT) { 1211 kprintf("mptable_ioapic_probe: invalid ISA irq (%d)\n", 1212 ent->src_bus_irq); 1213 return EINVAL; 1214 } 1215 return 0; 1216 } 1217 1218 static int 1219 mptable_ioapic_probe(struct ioapic_enumerator *e) 1220 { 1221 struct mptable_ioapic_probe_cbarg arg; 1222 struct mptable_bus_info bus_info; 1223 struct mptable_pos mpt; 1224 mpcth_t cth; 1225 int error; 1226 1227 if (mptable_fps_phyaddr == 0) 1228 return ENXIO; 1229 1230 if (mptable_use_default) 1231 return 0; 1232 1233 if (TAILQ_EMPTY(&mptable_ioapic_list)) 1234 return ENXIO; 1235 1236 error = mptable_map(&mpt); 1237 if (error) 1238 panic("mptable_ioapic_probe: mptable_map failed"); 1239 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 1240 1241 cth = mpt.mp_cth; 1242 1243 mptable_bus_info_alloc(cth, &bus_info); 1244 1245 bzero(&arg, sizeof(arg)); 1246 arg.bus_info = &bus_info; 1247 1248 error = mptable_iterate_entries(cth, 1249 mptable_ioapic_probe_callback, &arg); 1250 1251 mptable_bus_info_free(&bus_info); 1252 mptable_unmap(&mpt); 1253 1254 return error; 1255 } 1256 1257 struct mptable_ioapic_int_cbarg { 1258 const struct mptable_bus_info *bus_info; 1259 int ioapic_nint; 1260 }; 1261 1262 static int 1263 mptable_ioapic_int_callback(void *xarg, const void *pos, int type) 1264 { 1265 struct mptable_ioapic_int_cbarg *arg = xarg; 1266 const struct mptable_ioapic *ioapic; 1267 const struct mptable_bus *bus; 1268 const struct INTENTRY *ent; 1269 int gsi; 1270 1271 if (type != 3) 1272 return 0; 1273 1274 arg->ioapic_nint++; 1275 1276 ent = pos; 1277 if (ent->int_type != 0) 1278 return 0; 1279 1280 TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) { 1281 if (bus->mb_type == MPTABLE_BUS_ISA && 1282 bus->mb_id == ent->src_bus_id) 1283 break; 1284 } 1285 if (bus == NULL) 1286 return 0; 1287 1288 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 1289 if (ioapic->mio_apic_id == ent->dst_apic_id) 1290 break; 1291 } 1292 if (ioapic == NULL) { 1293 kprintf("MPTABLE: warning ISA int dst apic id %d " 1294 "does not exist\n", ent->dst_apic_id); 1295 return 0; 1296 } 1297 1298 if (ent->dst_apic_int >= ioapic->mio_npin) { 1299 panic("mptable_ioapic_enumerate: invalid I/O APIC " 1300 "pin %d, should be < %d", 1301 ent->dst_apic_int, ioapic->mio_npin); 1302 } 1303 gsi = ioapic->mio_gsi_base + ent->dst_apic_int; 1304 1305 if (ent->src_bus_irq != gsi) { 1306 if (bootverbose) { 1307 kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", 1308 ent->src_bus_irq, gsi); 1309 } 1310 ioapic_intsrc(ent->src_bus_irq, gsi, 1311 INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); 1312 } 1313 return 0; 1314 } 1315 1316 static void 1317 mptable_ioapic_enumerate(struct ioapic_enumerator *e) 1318 { 1319 struct mptable_bus_info bus_info; 1320 struct mptable_ioapic *ioapic; 1321 struct mptable_pos mpt; 1322 mpcth_t cth; 1323 int error; 1324 1325 KKASSERT(mptable_fps_phyaddr != 0); 1326 KKASSERT(!TAILQ_EMPTY(&mptable_ioapic_list)); 1327 1328 TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { 1329 const struct mptable_ioapic *prev_ioapic; 1330 uint32_t ver; 1331 void *addr; 1332 1333 addr = ioapic_map(ioapic->mio_addr); 1334 1335 ver = ioapic_read(addr, IOAPIC_VER); 1336 ioapic->mio_npin = ((ver & IOART_VER_MAXREDIR) 1337 >> MAXREDIRSHIFT) + 1; 1338 1339 prev_ioapic = TAILQ_PREV(ioapic, 1340 mptable_ioapic_list, mio_link); 1341 if (prev_ioapic == NULL) { 1342 ioapic->mio_gsi_base = 0; 1343 } else { 1344 ioapic->mio_gsi_base = 1345 prev_ioapic->mio_gsi_base + 1346 prev_ioapic->mio_npin; 1347 } 1348 ioapic_add(addr, ioapic->mio_gsi_base, ioapic->mio_npin); 1349 1350 if (bootverbose) { 1351 kprintf("MPTABLE: IOAPIC addr 0x%08x, " 1352 "apic id %d, idx %d, gsi base %d, npin %d\n", 1353 ioapic->mio_addr, 1354 ioapic->mio_apic_id, 1355 ioapic->mio_idx, 1356 ioapic->mio_gsi_base, 1357 ioapic->mio_npin); 1358 } 1359 } 1360 1361 if (mptable_use_default) { 1362 if (bootverbose) 1363 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n"); 1364 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); 1365 return; 1366 } 1367 1368 error = mptable_map(&mpt); 1369 if (error) 1370 panic("mptable_ioapic_probe: mptable_map failed"); 1371 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt)); 1372 1373 cth = mpt.mp_cth; 1374 1375 mptable_bus_info_alloc(cth, &bus_info); 1376 1377 if (TAILQ_EMPTY(&bus_info.mbi_list)) { 1378 if (bootverbose) 1379 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n"); 1380 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); 1381 } else { 1382 struct mptable_ioapic_int_cbarg arg; 1383 1384 bzero(&arg, sizeof(arg)); 1385 arg.bus_info = &bus_info; 1386 1387 error = mptable_iterate_entries(cth, 1388 mptable_ioapic_int_callback, &arg); 1389 if (error) 1390 panic("mptable_ioapic_int failed"); 1391 1392 if (arg.ioapic_nint == 0) { 1393 if (bootverbose) { 1394 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 " 1395 "(no int)\n"); 1396 } 1397 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, 1398 INTR_POLARITY_HIGH); 1399 } 1400 } 1401 1402 mptable_bus_info_free(&bus_info); 1403 1404 mptable_unmap(&mpt); 1405 } 1406 1407 static struct ioapic_enumerator mptable_ioapic_enumerator = { 1408 .ioapic_prio = IOAPIC_ENUM_PRIO_MPTABLE, 1409 .ioapic_probe = mptable_ioapic_probe, 1410 .ioapic_enumerate = mptable_ioapic_enumerate 1411 }; 1412 1413 static void 1414 mptable_ioapic_enum_register(void) 1415 { 1416 ioapic_enumerator_register(&mptable_ioapic_enumerator); 1417 } 1418 SYSINIT(mptable_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, 1419 mptable_ioapic_enum_register, 0); 1420 1421 void 1422 mptable_pci_int_dump(void) 1423 { 1424 const struct mptable_pci_int *pci_int; 1425 1426 if (!bootverbose) 1427 return; 1428 1429 TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) { 1430 kprintf("MPTABLE: %d:%d INT%c -> IOAPIC %d.%d\n", 1431 pci_int->mpci_bus, 1432 pci_int->mpci_dev, 1433 pci_int->mpci_pin + 'A', 1434 pci_int->mpci_ioapic_idx, 1435 pci_int->mpci_ioapic_pin); 1436 } 1437 } 1438 1439 int 1440 mptable_pci_int_route(int bus, int dev, int pin, int intline) 1441 { 1442 const struct mptable_pci_int *pci_int; 1443 int irq = -1; 1444 1445 KKASSERT(pin >= 1); 1446 --pin; /* zero based */ 1447 1448 TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) { 1449 if (pci_int->mpci_bus == bus && 1450 pci_int->mpci_dev == dev && 1451 pci_int->mpci_pin == pin) 1452 break; 1453 } 1454 if (pci_int != NULL) { 1455 int gsi; 1456 1457 gsi = ioapic_gsi(pci_int->mpci_ioapic_idx, 1458 pci_int->mpci_ioapic_pin); 1459 if (gsi >= 0) { 1460 irq = machintr_legacy_intr_find_bygsi(gsi, 1461 INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); 1462 } 1463 } 1464 1465 if (irq < 0 && intline >= 0) { 1466 kprintf("MPTABLE: fixed interrupt routing " 1467 "for %d:%d INT%c\n", bus, dev, pin + 'A'); 1468 irq = machintr_legacy_intr_find(intline, 1469 INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); 1470 } 1471 1472 if (irq >= 0 && bootverbose) { 1473 kprintf("MPTABLE: %d:%d INT%c routed to irq %d\n", 1474 bus, dev, pin + 'A', irq); 1475 } 1476 return irq; 1477 } 1478