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