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