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