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