1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1996, by Steve Passe 5 * All rights reserved. 6 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. The name of the developer may NOT be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_mptable_force_htt.h" 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/bus.h> 36 #include <sys/kernel.h> 37 #include <sys/limits.h> 38 #include <sys/malloc.h> 39 #include <sys/smp.h> 40 #ifdef NEW_PCIB 41 #include <sys/rman.h> 42 #endif 43 44 #include <vm/vm.h> 45 #include <vm/vm_param.h> 46 #include <vm/pmap.h> 47 48 #include <dev/pci/pcivar.h> 49 #ifdef NEW_PCIB 50 #include <dev/pci/pcib_private.h> 51 #endif 52 #include <x86/apicreg.h> 53 #include <x86/mptable.h> 54 #include <machine/frame.h> 55 #include <machine/intr_machdep.h> 56 #include <x86/apicvar.h> 57 #include <machine/md_var.h> 58 #include <machine/pc/bios.h> 59 #ifdef NEW_PCIB 60 #include <machine/resource.h> 61 #endif 62 #include <machine/specialreg.h> 63 64 /* string defined by the Intel MP Spec as identifying the MP table */ 65 #define MP_SIG 0x5f504d5f /* _MP_ */ 66 67 #ifdef __amd64__ 68 #define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */ 69 #else 70 #define MAX_LAPIC_ID 31 /* Max local APIC ID for HTT fixup */ 71 #endif 72 73 #define BIOS_BASE (0xf0000) 74 #define BIOS_SIZE (0x10000) 75 #define BIOS_COUNT (BIOS_SIZE/4) 76 77 typedef void mptable_entry_handler(u_char *entry, void *arg); 78 typedef void mptable_extended_entry_handler(ext_entry_ptr entry, void *arg); 79 80 /* descriptions of MP table entries */ 81 typedef struct BASETABLE_ENTRY { 82 uint8_t type; 83 uint8_t length; 84 uint8_t name[16]; 85 } basetable_entry; 86 87 static basetable_entry basetable_entry_types[] = 88 { 89 {0, 20, "Processor"}, 90 {1, 8, "Bus"}, 91 {2, 8, "I/O APIC"}, 92 {3, 8, "I/O INT"}, 93 {4, 8, "Local INT"} 94 }; 95 96 typedef struct BUSDATA { 97 u_char bus_id; 98 enum busTypes bus_type; 99 } bus_datum; 100 101 typedef struct INTDATA { 102 u_char int_type; 103 u_short int_flags; 104 u_char src_bus_id; 105 u_char src_bus_irq; 106 u_char dst_apic_id; 107 u_char dst_apic_int; 108 u_char int_vector; 109 } io_int, local_int; 110 111 typedef struct BUSTYPENAME { 112 u_char type; 113 char name[7]; 114 } bus_type_name; 115 116 /* From MP spec v1.4, table 4-8. */ 117 static bus_type_name bus_type_table[] = 118 { 119 {UNKNOWN_BUSTYPE, "CBUS "}, 120 {UNKNOWN_BUSTYPE, "CBUSII"}, 121 {EISA, "EISA "}, 122 {UNKNOWN_BUSTYPE, "FUTURE"}, 123 {UNKNOWN_BUSTYPE, "INTERN"}, 124 {ISA, "ISA "}, 125 {UNKNOWN_BUSTYPE, "MBI "}, 126 {UNKNOWN_BUSTYPE, "MBII "}, 127 {MCA, "MCA "}, 128 {UNKNOWN_BUSTYPE, "MPI "}, 129 {UNKNOWN_BUSTYPE, "MPSA "}, 130 {UNKNOWN_BUSTYPE, "NUBUS "}, 131 {PCI, "PCI "}, 132 {UNKNOWN_BUSTYPE, "PCMCIA"}, 133 {UNKNOWN_BUSTYPE, "TC "}, 134 {UNKNOWN_BUSTYPE, "VL "}, 135 {UNKNOWN_BUSTYPE, "VME "}, 136 {UNKNOWN_BUSTYPE, "XPRESS"} 137 }; 138 139 /* From MP spec v1.4, table 5-1. */ 140 static int default_data[7][5] = 141 { 142 /* nbus, id0, type0, id1, type1 */ 143 {1, 0, ISA, 255, NOBUS}, 144 {1, 0, EISA, 255, NOBUS}, 145 {1, 0, EISA, 255, NOBUS}, 146 {1, 0, MCA, 255, NOBUS}, 147 {2, 0, ISA, 1, PCI}, 148 {2, 0, EISA, 1, PCI}, 149 {2, 0, MCA, 1, PCI} 150 }; 151 152 struct pci_probe_table_args { 153 u_char bus; 154 u_char found; 155 }; 156 157 struct pci_route_interrupt_args { 158 u_char bus; /* Source bus. */ 159 u_char irq; /* Source slot:pin. */ 160 int vector; /* Return value. */ 161 }; 162 163 static mpfps_t mpfps; 164 static mpcth_t mpct; 165 static ext_entry_ptr mpet; 166 static void *ioapics[IOAPIC_MAX_ID + 1]; 167 static bus_datum *busses; 168 static int mptable_nioapics, mptable_nbusses, mptable_maxbusid; 169 static int pci0 = -1; 170 171 static MALLOC_DEFINE(M_MPTABLE, "mptable", "MP Table Items"); 172 173 static enum intr_polarity conforming_polarity(u_char src_bus, 174 u_char src_bus_irq); 175 static enum intr_trigger conforming_trigger(u_char src_bus, u_char src_bus_irq); 176 static enum intr_polarity intentry_polarity(int_entry_ptr intr); 177 static enum intr_trigger intentry_trigger(int_entry_ptr intr); 178 static int lookup_bus_type(char *name); 179 static void mptable_count_items(void); 180 static void mptable_count_items_handler(u_char *entry, void *arg); 181 #ifdef MPTABLE_FORCE_HTT 182 static void mptable_hyperthread_fixup(u_int id_mask); 183 #endif 184 static void mptable_parse_apics_and_busses(void); 185 static void mptable_parse_apics_and_busses_handler(u_char *entry, 186 void *arg); 187 static void mptable_parse_default_config_ints(void); 188 static void mptable_parse_ints(void); 189 static void mptable_parse_ints_handler(u_char *entry, void *arg); 190 static void mptable_parse_io_int(int_entry_ptr intr); 191 static void mptable_parse_local_int(int_entry_ptr intr); 192 static void mptable_pci_probe_table_handler(u_char *entry, void *arg); 193 static void mptable_pci_route_interrupt_handler(u_char *entry, void *arg); 194 static void mptable_pci_setup(void); 195 static int mptable_probe(void); 196 static int mptable_probe_cpus(void); 197 static void mptable_probe_cpus_handler(u_char *entry, void *arg __unused); 198 static void mptable_setup_cpus_handler(u_char *entry, void *arg __unused); 199 static void mptable_register(void *dummy); 200 static int mptable_setup_local(void); 201 static int mptable_setup_io(void); 202 #ifdef NEW_PCIB 203 static void mptable_walk_extended_table( 204 mptable_extended_entry_handler *handler, void *arg); 205 #endif 206 static void mptable_walk_table(mptable_entry_handler *handler, void *arg); 207 static int search_for_sig(u_int32_t target, int count); 208 209 static struct apic_enumerator mptable_enumerator = { 210 .apic_name = "MPTable", 211 .apic_probe = mptable_probe, 212 .apic_probe_cpus = mptable_probe_cpus, 213 .apic_setup_local = mptable_setup_local, 214 .apic_setup_io = mptable_setup_io 215 }; 216 217 /* 218 * look for the MP spec signature 219 */ 220 221 static int 222 search_for_sig(u_int32_t target, int count) 223 { 224 int x; 225 u_int32_t *addr; 226 227 addr = (u_int32_t *)BIOS_PADDRTOVADDR(target); 228 for (x = 0; x < count; x += 4) 229 if (addr[x] == MP_SIG) 230 /* make array index a byte index */ 231 return (target + (x * sizeof(u_int32_t))); 232 return (-1); 233 } 234 235 static int 236 lookup_bus_type(char *name) 237 { 238 int x; 239 240 for (x = 0; x < MAX_BUSTYPE; ++x) 241 if (strncmp(bus_type_table[x].name, name, 6) == 0) 242 return (bus_type_table[x].type); 243 244 return (UNKNOWN_BUSTYPE); 245 } 246 247 /* 248 * Look for an Intel MP spec table (ie, SMP capable hardware). 249 */ 250 static int 251 mptable_probe(void) 252 { 253 int x; 254 u_long segment; 255 u_int32_t target; 256 257 /* see if EBDA exists */ 258 if ((segment = *(u_short *)BIOS_PADDRTOVADDR(0x40e)) != 0) { 259 /* search first 1K of EBDA */ 260 target = (u_int32_t) (segment << 4); 261 if ((x = search_for_sig(target, 1024 / 4)) >= 0) 262 goto found; 263 } else { 264 /* last 1K of base memory, effective 'top of base' passed in */ 265 target = (u_int32_t) ((basemem * 1024) - 0x400); 266 if ((x = search_for_sig(target, 1024 / 4)) >= 0) 267 goto found; 268 } 269 270 /* search the BIOS */ 271 target = (u_int32_t) BIOS_BASE; 272 if ((x = search_for_sig(target, BIOS_COUNT)) >= 0) 273 goto found; 274 275 /* nothing found */ 276 return (ENXIO); 277 278 found: 279 mpfps = (mpfps_t)BIOS_PADDRTOVADDR(x); 280 281 /* Map in the configuration table if it exists. */ 282 if (mpfps->config_type != 0) { 283 if (bootverbose) 284 printf( 285 "MP Table version 1.%d found using Default Configuration %d\n", 286 mpfps->spec_rev, mpfps->config_type); 287 if (mpfps->config_type != 5 && mpfps->config_type != 6) { 288 printf( 289 "MP Table Default Configuration %d is unsupported\n", 290 mpfps->config_type); 291 return (ENXIO); 292 } 293 mpct = NULL; 294 } else { 295 if ((uintptr_t)mpfps->pap >= 1024 * 1024) { 296 printf("%s: Unable to map MP Configuration Table\n", 297 __func__); 298 return (ENXIO); 299 } 300 mpct = (mpcth_t)BIOS_PADDRTOVADDR((uintptr_t)mpfps->pap); 301 if (mpct->base_table_length + (uintptr_t)mpfps->pap >= 302 1024 * 1024) { 303 printf("%s: Unable to map end of MP Config Table\n", 304 __func__); 305 return (ENXIO); 306 } 307 if (mpct->extended_table_length != 0 && 308 mpct->extended_table_length + mpct->base_table_length + 309 (uintptr_t)mpfps->pap < 1024 * 1024) 310 mpet = (ext_entry_ptr)((char *)mpct + 311 mpct->base_table_length); 312 if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' || 313 mpct->signature[2] != 'M' || mpct->signature[3] != 'P') { 314 printf("%s: MP Config Table has bad signature: %c%c%c%c\n", 315 __func__, mpct->signature[0], mpct->signature[1], 316 mpct->signature[2], mpct->signature[3]); 317 return (ENXIO); 318 } 319 if (bootverbose) 320 printf( 321 "MP Configuration Table version 1.%d found at %p\n", 322 mpct->spec_rev, mpct); 323 } 324 325 return (-100); 326 } 327 328 /* 329 * Run through the MP table enumerating CPUs. 330 */ 331 static int 332 mptable_probe_cpus(void) 333 { 334 u_int cpu_mask; 335 336 /* Is this a pre-defined config? */ 337 if (mpfps->config_type != 0) { 338 #ifdef SMP 339 mp_ncpus = 2; 340 mp_maxid = 1; 341 #endif 342 max_apic_id = 1; 343 } else { 344 mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask); 345 } 346 return (0); 347 } 348 349 /* 350 * Initialize the local APIC on the BSP. 351 */ 352 static int 353 mptable_setup_local(void) 354 { 355 vm_paddr_t addr; 356 u_int cpu_mask; 357 358 /* Is this a pre-defined config? */ 359 printf("MPTable: <"); 360 if (mpfps->config_type != 0) { 361 lapic_create(0, 1); 362 lapic_create(1, 0); 363 addr = DEFAULT_APIC_BASE; 364 printf("Default Configuration %d", mpfps->config_type); 365 366 } else { 367 cpu_mask = 0; 368 mptable_walk_table(mptable_setup_cpus_handler, &cpu_mask); 369 #ifdef MPTABLE_FORCE_HTT 370 mptable_hyperthread_fixup(cpu_mask); 371 #endif 372 addr = mpct->apic_address; 373 printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id, 374 (int)sizeof(mpct->product_id), mpct->product_id); 375 } 376 printf(">\n"); 377 lapic_init(addr); 378 return (0); 379 } 380 381 /* 382 * Run through the MP table enumerating I/O APICs. 383 */ 384 static int 385 mptable_setup_io(void) 386 { 387 int i; 388 u_char byte; 389 390 /* First, we count individual items and allocate arrays. */ 391 mptable_count_items(); 392 busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE, 393 M_WAITOK); 394 for (i = 0; i <= mptable_maxbusid; i++) 395 busses[i].bus_type = NOBUS; 396 397 /* Second, we run through adding I/O APIC's and buses. */ 398 mptable_parse_apics_and_busses(); 399 400 /* Third, we run through the table tweaking interrupt sources. */ 401 mptable_parse_ints(); 402 403 /* Fourth, we register all the I/O APIC's. */ 404 for (i = 0; i <= IOAPIC_MAX_ID; i++) 405 if (ioapics[i] != NULL) 406 ioapic_register(ioapics[i]); 407 408 /* Fifth, we setup data structures to handle PCI interrupt routing. */ 409 mptable_pci_setup(); 410 411 /* Finally, we throw the switch to enable the I/O APIC's. */ 412 if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) { 413 outb(0x22, 0x70); /* select IMCR */ 414 byte = inb(0x23); /* current contents */ 415 byte |= 0x01; /* mask external INTR */ 416 outb(0x23, byte); /* disconnect 8259s/NMI */ 417 } 418 419 return (0); 420 } 421 422 static void 423 mptable_register(void *dummy __unused) 424 { 425 426 apic_register_enumerator(&mptable_enumerator); 427 } 428 SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, mptable_register, 429 NULL); 430 431 /* 432 * Call the handler routine for each entry in the MP config base table. 433 */ 434 static void 435 mptable_walk_table(mptable_entry_handler *handler, void *arg) 436 { 437 u_int i; 438 u_char *entry; 439 440 entry = (u_char *)(mpct + 1); 441 for (i = 0; i < mpct->entry_count; i++) { 442 switch (*entry) { 443 case MPCT_ENTRY_PROCESSOR: 444 case MPCT_ENTRY_IOAPIC: 445 case MPCT_ENTRY_BUS: 446 case MPCT_ENTRY_INT: 447 case MPCT_ENTRY_LOCAL_INT: 448 break; 449 default: 450 panic("%s: Unknown MP Config Entry %d\n", __func__, 451 (int)*entry); 452 } 453 handler(entry, arg); 454 entry += basetable_entry_types[*entry].length; 455 } 456 } 457 458 #ifdef NEW_PCIB 459 /* 460 * Call the handler routine for each entry in the MP config extended 461 * table. 462 */ 463 static void 464 mptable_walk_extended_table(mptable_extended_entry_handler *handler, void *arg) 465 { 466 ext_entry_ptr end, entry; 467 468 if (mpet == NULL) 469 return; 470 entry = mpet; 471 end = (ext_entry_ptr)((char *)mpet + mpct->extended_table_length); 472 while (entry < end) { 473 handler(entry, arg); 474 entry = (ext_entry_ptr)((char *)entry + entry->length); 475 } 476 } 477 #endif 478 479 static void 480 mptable_probe_cpus_handler(u_char *entry, void *arg) 481 { 482 proc_entry_ptr proc; 483 484 switch (*entry) { 485 case MPCT_ENTRY_PROCESSOR: 486 proc = (proc_entry_ptr)entry; 487 if (proc->cpu_flags & PROCENTRY_FLAG_EN && 488 proc->apic_id < MAX_LAPIC_ID && mp_ncpus < MAXCPU) { 489 #ifdef SMP 490 mp_ncpus++; 491 mp_maxid = mp_ncpus - 1; 492 #endif 493 max_apic_id = max(max_apic_id, proc->apic_id); 494 } 495 break; 496 } 497 } 498 499 static void 500 mptable_setup_cpus_handler(u_char *entry, void *arg) 501 { 502 proc_entry_ptr proc; 503 u_int *cpu_mask; 504 505 switch (*entry) { 506 case MPCT_ENTRY_PROCESSOR: 507 proc = (proc_entry_ptr)entry; 508 if (proc->cpu_flags & PROCENTRY_FLAG_EN) { 509 lapic_create(proc->apic_id, proc->cpu_flags & 510 PROCENTRY_FLAG_BP); 511 if (proc->apic_id < MAX_LAPIC_ID) { 512 cpu_mask = (u_int *)arg; 513 *cpu_mask |= (1ul << proc->apic_id); 514 } 515 } 516 break; 517 } 518 } 519 520 static void 521 mptable_count_items_handler(u_char *entry, void *arg __unused) 522 { 523 io_apic_entry_ptr apic; 524 bus_entry_ptr bus; 525 526 switch (*entry) { 527 case MPCT_ENTRY_BUS: 528 bus = (bus_entry_ptr)entry; 529 mptable_nbusses++; 530 if (bus->bus_id > mptable_maxbusid) 531 mptable_maxbusid = bus->bus_id; 532 break; 533 case MPCT_ENTRY_IOAPIC: 534 apic = (io_apic_entry_ptr)entry; 535 if (apic->apic_flags & IOAPICENTRY_FLAG_EN) 536 mptable_nioapics++; 537 break; 538 } 539 } 540 541 /* 542 * Count items in the table. 543 */ 544 static void 545 mptable_count_items(void) 546 { 547 548 /* Is this a pre-defined config? */ 549 if (mpfps->config_type != 0) { 550 mptable_nioapics = 1; 551 switch (mpfps->config_type) { 552 case 1: 553 case 2: 554 case 3: 555 case 4: 556 mptable_nbusses = 1; 557 break; 558 case 5: 559 case 6: 560 case 7: 561 mptable_nbusses = 2; 562 break; 563 default: 564 panic("Unknown pre-defined MP Table config type %d", 565 mpfps->config_type); 566 } 567 mptable_maxbusid = mptable_nbusses - 1; 568 } else 569 mptable_walk_table(mptable_count_items_handler, NULL); 570 } 571 572 /* 573 * Add a bus or I/O APIC from an entry in the table. 574 */ 575 static void 576 mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused) 577 { 578 io_apic_entry_ptr apic; 579 bus_entry_ptr bus; 580 enum busTypes bus_type; 581 int i; 582 583 switch (*entry) { 584 case MPCT_ENTRY_BUS: 585 bus = (bus_entry_ptr)entry; 586 bus_type = lookup_bus_type(bus->bus_type); 587 if (bus_type == UNKNOWN_BUSTYPE) { 588 printf("MPTable: Unknown bus %d type \"", bus->bus_id); 589 for (i = 0; i < 6; i++) 590 printf("%c", bus->bus_type[i]); 591 printf("\"\n"); 592 } 593 busses[bus->bus_id].bus_id = bus->bus_id; 594 busses[bus->bus_id].bus_type = bus_type; 595 break; 596 case MPCT_ENTRY_IOAPIC: 597 apic = (io_apic_entry_ptr)entry; 598 if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN)) 599 break; 600 if (apic->apic_id > IOAPIC_MAX_ID) 601 panic("%s: I/O APIC ID %d too high", __func__, 602 apic->apic_id); 603 if (ioapics[apic->apic_id] != NULL) 604 panic("%s: Double APIC ID %d", __func__, 605 apic->apic_id); 606 ioapics[apic->apic_id] = ioapic_create(apic->apic_address, 607 apic->apic_id, -1); 608 break; 609 default: 610 break; 611 } 612 } 613 614 /* 615 * Enumerate I/O APIC's and buses. 616 */ 617 static void 618 mptable_parse_apics_and_busses(void) 619 { 620 621 /* Is this a pre-defined config? */ 622 if (mpfps->config_type != 0) { 623 ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0); 624 busses[0].bus_id = 0; 625 busses[0].bus_type = default_data[mpfps->config_type - 1][2]; 626 if (mptable_nbusses > 1) { 627 busses[1].bus_id = 1; 628 busses[1].bus_type = 629 default_data[mpfps->config_type - 1][4]; 630 } 631 } else 632 mptable_walk_table(mptable_parse_apics_and_busses_handler, 633 NULL); 634 } 635 636 /* 637 * Determine conforming polarity for a given bus type. 638 */ 639 static enum intr_polarity 640 conforming_polarity(u_char src_bus, u_char src_bus_irq) 641 { 642 643 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); 644 switch (busses[src_bus].bus_type) { 645 case ISA: 646 case EISA: 647 return (INTR_POLARITY_HIGH); 648 case PCI: 649 return (INTR_POLARITY_LOW); 650 default: 651 panic("%s: unknown bus type %d", __func__, 652 busses[src_bus].bus_type); 653 } 654 } 655 656 /* 657 * Determine conforming trigger for a given bus type. 658 */ 659 static enum intr_trigger 660 conforming_trigger(u_char src_bus, u_char src_bus_irq) 661 { 662 663 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); 664 switch (busses[src_bus].bus_type) { 665 case ISA: 666 if (elcr_found) 667 return (elcr_read_trigger(src_bus_irq)); 668 else 669 return (INTR_TRIGGER_EDGE); 670 case PCI: 671 return (INTR_TRIGGER_LEVEL); 672 673 case EISA: 674 KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq)); 675 KASSERT(elcr_found, ("Missing ELCR")); 676 return (elcr_read_trigger(src_bus_irq)); 677 678 default: 679 panic("%s: unknown bus type %d", __func__, 680 busses[src_bus].bus_type); 681 } 682 } 683 684 static enum intr_polarity 685 intentry_polarity(int_entry_ptr intr) 686 { 687 688 switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) { 689 case INTENTRY_FLAGS_POLARITY_CONFORM: 690 return (conforming_polarity(intr->src_bus_id, 691 intr->src_bus_irq)); 692 case INTENTRY_FLAGS_POLARITY_ACTIVEHI: 693 return (INTR_POLARITY_HIGH); 694 case INTENTRY_FLAGS_POLARITY_ACTIVELO: 695 return (INTR_POLARITY_LOW); 696 default: 697 panic("Bogus interrupt flags"); 698 } 699 } 700 701 static enum intr_trigger 702 intentry_trigger(int_entry_ptr intr) 703 { 704 705 switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) { 706 case INTENTRY_FLAGS_TRIGGER_CONFORM: 707 return (conforming_trigger(intr->src_bus_id, 708 intr->src_bus_irq)); 709 case INTENTRY_FLAGS_TRIGGER_EDGE: 710 return (INTR_TRIGGER_EDGE); 711 case INTENTRY_FLAGS_TRIGGER_LEVEL: 712 return (INTR_TRIGGER_LEVEL); 713 default: 714 panic("Bogus interrupt flags"); 715 } 716 } 717 718 /* 719 * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC. 720 */ 721 static void 722 mptable_parse_io_int(int_entry_ptr intr) 723 { 724 void *ioapic; 725 u_int pin, apic_id; 726 727 apic_id = intr->dst_apic_id; 728 if (intr->dst_apic_id == 0xff) { 729 /* 730 * An APIC ID of 0xff means that the interrupt is connected 731 * to the specified pin on all I/O APICs in the system. If 732 * there is only one I/O APIC, then use that APIC to route 733 * the interrupts. If there is more than one I/O APIC, then 734 * punt. 735 */ 736 if (mptable_nioapics == 1) { 737 apic_id = 0; 738 while (ioapics[apic_id] == NULL) 739 apic_id++; 740 } else { 741 printf( 742 "MPTable: Ignoring global interrupt entry for pin %d\n", 743 intr->dst_apic_int); 744 return; 745 } 746 } 747 if (apic_id > IOAPIC_MAX_ID) { 748 printf("MPTable: Ignoring interrupt entry for ioapic%d\n", 749 intr->dst_apic_id); 750 return; 751 } 752 ioapic = ioapics[apic_id]; 753 if (ioapic == NULL) { 754 printf( 755 "MPTable: Ignoring interrupt entry for missing ioapic%d\n", 756 apic_id); 757 return; 758 } 759 pin = intr->dst_apic_int; 760 switch (intr->int_type) { 761 case INTENTRY_TYPE_INT: 762 switch (busses[intr->src_bus_id].bus_type) { 763 case NOBUS: 764 panic("interrupt from missing bus"); 765 case ISA: 766 case EISA: 767 if (busses[intr->src_bus_id].bus_type == ISA) 768 ioapic_set_bus(ioapic, pin, APIC_BUS_ISA); 769 else 770 ioapic_set_bus(ioapic, pin, APIC_BUS_EISA); 771 if (intr->src_bus_irq == pin) 772 break; 773 ioapic_remap_vector(ioapic, pin, intr->src_bus_irq); 774 if (ioapic_get_vector(ioapic, intr->src_bus_irq) == 775 intr->src_bus_irq) 776 ioapic_disable_pin(ioapic, intr->src_bus_irq); 777 break; 778 case PCI: 779 ioapic_set_bus(ioapic, pin, APIC_BUS_PCI); 780 break; 781 default: 782 ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN); 783 break; 784 } 785 break; 786 case INTENTRY_TYPE_NMI: 787 ioapic_set_nmi(ioapic, pin); 788 break; 789 case INTENTRY_TYPE_SMI: 790 ioapic_set_smi(ioapic, pin); 791 break; 792 case INTENTRY_TYPE_EXTINT: 793 ioapic_set_extint(ioapic, pin); 794 break; 795 default: 796 panic("%s: invalid interrupt entry type %d\n", __func__, 797 intr->int_type); 798 } 799 if (intr->int_type == INTENTRY_TYPE_INT || 800 (intr->int_flags & INTENTRY_FLAGS_TRIGGER) != 801 INTENTRY_FLAGS_TRIGGER_CONFORM) 802 ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr)); 803 if (intr->int_type == INTENTRY_TYPE_INT || 804 (intr->int_flags & INTENTRY_FLAGS_POLARITY) != 805 INTENTRY_FLAGS_POLARITY_CONFORM) 806 ioapic_set_polarity(ioapic, pin, intentry_polarity(intr)); 807 } 808 809 /* 810 * Parse an interrupt entry for a local APIC LVT pin. 811 */ 812 static void 813 mptable_parse_local_int(int_entry_ptr intr) 814 { 815 u_int apic_id, pin; 816 817 if (intr->dst_apic_id == 0xff) 818 apic_id = APIC_ID_ALL; 819 else 820 apic_id = intr->dst_apic_id; 821 if (intr->dst_apic_int == 0) 822 pin = APIC_LVT_LINT0; 823 else 824 pin = APIC_LVT_LINT1; 825 switch (intr->int_type) { 826 case INTENTRY_TYPE_INT: 827 #if 1 828 printf( 829 "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n", 830 intr->dst_apic_int, intr->src_bus_irq); 831 return; 832 #else 833 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED); 834 break; 835 #endif 836 case INTENTRY_TYPE_NMI: 837 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 838 break; 839 case INTENTRY_TYPE_SMI: 840 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI); 841 break; 842 case INTENTRY_TYPE_EXTINT: 843 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT); 844 break; 845 default: 846 panic("%s: invalid interrupt entry type %d\n", __func__, 847 intr->int_type); 848 } 849 if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) != 850 INTENTRY_FLAGS_TRIGGER_CONFORM) 851 lapic_set_lvt_triggermode(apic_id, pin, 852 intentry_trigger(intr)); 853 if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) != 854 INTENTRY_FLAGS_POLARITY_CONFORM) 855 lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr)); 856 } 857 858 /* 859 * Parse interrupt entries. 860 */ 861 static void 862 mptable_parse_ints_handler(u_char *entry, void *arg __unused) 863 { 864 int_entry_ptr intr; 865 866 intr = (int_entry_ptr)entry; 867 switch (*entry) { 868 case MPCT_ENTRY_INT: 869 mptable_parse_io_int(intr); 870 break; 871 case MPCT_ENTRY_LOCAL_INT: 872 mptable_parse_local_int(intr); 873 break; 874 } 875 } 876 877 /* 878 * Configure interrupt pins for a default configuration. For details see 879 * Table 5-2 in Section 5 of the MP Table specification. 880 */ 881 static void 882 mptable_parse_default_config_ints(void) 883 { 884 struct INTENTRY entry; 885 int pin; 886 887 /* 888 * All default configs route IRQs from bus 0 to the first 16 pins 889 * of the first I/O APIC with an APIC ID of 2. 890 */ 891 entry.type = MPCT_ENTRY_INT; 892 entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | 893 INTENTRY_FLAGS_TRIGGER_CONFORM; 894 entry.src_bus_id = 0; 895 entry.dst_apic_id = 2; 896 897 /* Run through all 16 pins. */ 898 for (pin = 0; pin < 16; pin++) { 899 entry.dst_apic_int = pin; 900 switch (pin) { 901 case 0: 902 /* Pin 0 is an ExtINT pin. */ 903 entry.int_type = INTENTRY_TYPE_EXTINT; 904 break; 905 case 2: 906 /* IRQ 0 is routed to pin 2. */ 907 entry.int_type = INTENTRY_TYPE_INT; 908 entry.src_bus_irq = 0; 909 break; 910 default: 911 /* All other pins are identity mapped. */ 912 entry.int_type = INTENTRY_TYPE_INT; 913 entry.src_bus_irq = pin; 914 break; 915 } 916 mptable_parse_io_int(&entry); 917 } 918 919 /* Certain configs disable certain pins. */ 920 if (mpfps->config_type == 7) 921 ioapic_disable_pin(ioapics[2], 0); 922 if (mpfps->config_type == 2) { 923 ioapic_disable_pin(ioapics[2], 2); 924 ioapic_disable_pin(ioapics[2], 13); 925 } 926 } 927 928 /* 929 * Configure the interrupt pins 930 */ 931 static void 932 mptable_parse_ints(void) 933 { 934 935 /* Is this a pre-defined config? */ 936 if (mpfps->config_type != 0) { 937 /* Configure LINT pins. */ 938 lapic_set_lvt_mode(APIC_ID_ALL, APIC_LVT_LINT0, 939 APIC_LVT_DM_EXTINT); 940 lapic_set_lvt_mode(APIC_ID_ALL, APIC_LVT_LINT1, APIC_LVT_DM_NMI); 941 942 /* Configure I/O APIC pins. */ 943 mptable_parse_default_config_ints(); 944 } else 945 mptable_walk_table(mptable_parse_ints_handler, NULL); 946 } 947 948 #ifdef MPTABLE_FORCE_HTT 949 /* 950 * Perform a hyperthreading "fix-up" to enumerate any logical CPU's 951 * that aren't already listed in the table. 952 * 953 * XXX: We assume that all of the physical CPUs in the 954 * system have the same number of logical CPUs. 955 * 956 * XXX: We assume that APIC ID's are allocated such that 957 * the APIC ID's for a physical processor are aligned 958 * with the number of logical CPU's in the processor. 959 */ 960 static void 961 mptable_hyperthread_fixup(u_int id_mask) 962 { 963 u_int i, id, logical_cpus; 964 965 /* Nothing to do if there is no HTT support. */ 966 if ((cpu_feature & CPUID_HTT) == 0) 967 return; 968 logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; 969 if (logical_cpus <= 1) 970 return; 971 972 /* 973 * For each APIC ID of a CPU that is set in the mask, 974 * scan the other candidate APIC ID's for this 975 * physical processor. If any of those ID's are 976 * already in the table, then kill the fixup. 977 */ 978 for (id = 0; id <= MAX_LAPIC_ID; id++) { 979 if ((id_mask & 1 << id) == 0) 980 continue; 981 /* First, make sure we are on a logical_cpus boundary. */ 982 if (id % logical_cpus != 0) 983 return; 984 for (i = id + 1; i < id + logical_cpus; i++) 985 if ((id_mask & 1 << i) != 0) 986 return; 987 } 988 989 /* 990 * Ok, the ID's checked out, so perform the fixup by 991 * adding the logical CPUs. 992 */ 993 while ((id = ffs(id_mask)) != 0) { 994 id--; 995 for (i = id + 1; i < id + logical_cpus; i++) { 996 if (bootverbose) 997 printf( 998 "MPTable: Adding logical CPU %d from main CPU %d\n", 999 i, id); 1000 lapic_create(i, 0); 1001 } 1002 id_mask &= ~(1 << id); 1003 } 1004 } 1005 #endif /* MPTABLE_FORCE_HTT */ 1006 1007 /* 1008 * Support code for routing PCI interrupts using the MP Table. 1009 */ 1010 static void 1011 mptable_pci_setup(void) 1012 { 1013 int i; 1014 1015 /* 1016 * Find the first pci bus and call it 0. Panic if pci0 is not 1017 * bus zero and there are multiple PCI buses. 1018 */ 1019 for (i = 0; i <= mptable_maxbusid; i++) 1020 if (busses[i].bus_type == PCI) { 1021 if (pci0 == -1) 1022 pci0 = i; 1023 else if (pci0 != 0) 1024 panic( 1025 "MPTable contains multiple PCI buses but no PCI bus 0"); 1026 } 1027 } 1028 1029 static void 1030 mptable_pci_probe_table_handler(u_char *entry, void *arg) 1031 { 1032 struct pci_probe_table_args *args; 1033 int_entry_ptr intr; 1034 1035 if (*entry != MPCT_ENTRY_INT) 1036 return; 1037 intr = (int_entry_ptr)entry; 1038 args = (struct pci_probe_table_args *)arg; 1039 KASSERT(args->bus <= mptable_maxbusid, 1040 ("bus %d is too big", args->bus)); 1041 KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus")); 1042 if (intr->src_bus_id == args->bus) 1043 args->found = 1; 1044 } 1045 1046 int 1047 mptable_pci_probe_table(int bus) 1048 { 1049 struct pci_probe_table_args args; 1050 1051 if (bus < 0) 1052 return (EINVAL); 1053 if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid) 1054 return (ENXIO); 1055 if (busses[pci0 + bus].bus_type != PCI) 1056 return (ENXIO); 1057 args.bus = pci0 + bus; 1058 args.found = 0; 1059 mptable_walk_table(mptable_pci_probe_table_handler, &args); 1060 if (args.found == 0) 1061 return (ENXIO); 1062 return (0); 1063 } 1064 1065 static void 1066 mptable_pci_route_interrupt_handler(u_char *entry, void *arg) 1067 { 1068 struct pci_route_interrupt_args *args; 1069 int_entry_ptr intr; 1070 int vector; 1071 1072 if (*entry != MPCT_ENTRY_INT) 1073 return; 1074 intr = (int_entry_ptr)entry; 1075 args = (struct pci_route_interrupt_args *)arg; 1076 if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq) 1077 return; 1078 1079 /* Make sure the APIC maps to a known APIC. */ 1080 KASSERT(ioapics[intr->dst_apic_id] != NULL, 1081 ("No I/O APIC %d to route interrupt to", intr->dst_apic_id)); 1082 1083 /* 1084 * Look up the vector for this APIC / pin combination. If we 1085 * have previously matched an entry for this PCI IRQ but it 1086 * has the same vector as this entry, just return. Otherwise, 1087 * we use the vector for this APIC / pin combination. 1088 */ 1089 vector = ioapic_get_vector(ioapics[intr->dst_apic_id], 1090 intr->dst_apic_int); 1091 if (args->vector == vector) 1092 return; 1093 KASSERT(args->vector == -1, 1094 ("Multiple IRQs for PCI interrupt %d.%d.INT%c: %d and %d\n", 1095 args->bus, args->irq >> 2, 'A' + (args->irq & 0x3), args->vector, 1096 vector)); 1097 args->vector = vector; 1098 } 1099 1100 int 1101 mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin) 1102 { 1103 struct pci_route_interrupt_args args; 1104 int slot; 1105 1106 /* Like ACPI, pin numbers are 0-3, not 1-4. */ 1107 pin--; 1108 KASSERT(pci0 != -1, ("do not know how to route PCI interrupts")); 1109 args.bus = pci_get_bus(dev) + pci0; 1110 slot = pci_get_slot(dev); 1111 1112 /* 1113 * PCI interrupt entries in the MP Table encode both the slot and 1114 * pin into the IRQ with the pin being the two least significant 1115 * bits, the slot being the next five bits, and the most significant 1116 * bit being reserved. 1117 */ 1118 args.irq = slot << 2 | pin; 1119 args.vector = -1; 1120 mptable_walk_table(mptable_pci_route_interrupt_handler, &args); 1121 if (args.vector < 0) { 1122 device_printf(pcib, "unable to route slot %d INT%c\n", slot, 1123 'A' + pin); 1124 return (PCI_INVALID_IRQ); 1125 } 1126 if (bootverbose) 1127 device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 1128 'A' + pin, args.vector); 1129 return (args.vector); 1130 } 1131 1132 #ifdef NEW_PCIB 1133 struct host_res_args { 1134 struct mptable_hostb_softc *sc; 1135 device_t dev; 1136 u_char bus; 1137 }; 1138 1139 /* 1140 * Initialize a Host-PCI bridge so it can restrict resource allocation 1141 * requests to the resources it actually decodes according to MP 1142 * config table extended entries. 1143 */ 1144 static void 1145 mptable_host_res_handler(ext_entry_ptr entry, void *arg) 1146 { 1147 struct host_res_args *args; 1148 cbasm_entry_ptr cbasm; 1149 sas_entry_ptr sas; 1150 const char *name; 1151 uint64_t start, end; 1152 int error, *flagp, flags, type; 1153 1154 args = arg; 1155 switch (entry->type) { 1156 case MPCT_EXTENTRY_SAS: 1157 sas = (sas_entry_ptr)entry; 1158 if (sas->bus_id != args->bus) 1159 break; 1160 switch (sas->address_type) { 1161 case SASENTRY_TYPE_IO: 1162 type = SYS_RES_IOPORT; 1163 flags = 0; 1164 break; 1165 case SASENTRY_TYPE_MEMORY: 1166 type = SYS_RES_MEMORY; 1167 flags = 0; 1168 break; 1169 case SASENTRY_TYPE_PREFETCH: 1170 type = SYS_RES_MEMORY; 1171 flags = RF_PREFETCHABLE; 1172 break; 1173 default: 1174 printf( 1175 "MPTable: Unknown systems address space type for bus %u: %d\n", 1176 sas->bus_id, sas->address_type); 1177 return; 1178 } 1179 start = sas->address_base; 1180 end = sas->address_base + sas->address_length - 1; 1181 #ifdef __i386__ 1182 if (start > ULONG_MAX) { 1183 device_printf(args->dev, 1184 "Ignoring %d range above 4GB (%#jx-%#jx)\n", 1185 type, (uintmax_t)start, (uintmax_t)end); 1186 break; 1187 } 1188 if (end > ULONG_MAX) { 1189 device_printf(args->dev, 1190 "Truncating end of %d range above 4GB (%#jx-%#jx)\n", 1191 type, (uintmax_t)start, (uintmax_t)end); 1192 end = ULONG_MAX; 1193 } 1194 #endif 1195 error = pcib_host_res_decodes(&args->sc->sc_host_res, type, 1196 start, end, flags); 1197 if (error) 1198 panic("Failed to manage %d range (%#jx-%#jx): %d", 1199 type, (uintmax_t)start, (uintmax_t)end, error); 1200 break; 1201 case MPCT_EXTENTRY_CBASM: 1202 cbasm = (cbasm_entry_ptr)entry; 1203 if (cbasm->bus_id != args->bus) 1204 break; 1205 switch (cbasm->predefined_range) { 1206 case CBASMENTRY_RANGE_ISA_IO: 1207 flagp = &args->sc->sc_decodes_isa_io; 1208 name = "ISA I/O"; 1209 break; 1210 case CBASMENTRY_RANGE_VGA_IO: 1211 flagp = &args->sc->sc_decodes_vga_io; 1212 name = "VGA I/O"; 1213 break; 1214 default: 1215 printf( 1216 "MPTable: Unknown compatiblity address space range for bus %u: %d\n", 1217 cbasm->bus_id, cbasm->predefined_range); 1218 return; 1219 } 1220 if (*flagp != 0) 1221 printf( 1222 "MPTable: Duplicate compatibility %s range for bus %u\n", 1223 name, cbasm->bus_id); 1224 switch (cbasm->address_mod) { 1225 case CBASMENTRY_ADDRESS_MOD_ADD: 1226 *flagp = 1; 1227 if (bootverbose) 1228 device_printf(args->dev, "decoding %s ports\n", 1229 name); 1230 break; 1231 case CBASMENTRY_ADDRESS_MOD_SUBTRACT: 1232 *flagp = -1; 1233 if (bootverbose) 1234 device_printf(args->dev, 1235 "not decoding %s ports\n", name); 1236 break; 1237 default: 1238 printf( 1239 "MPTable: Unknown compatibility address space modifier: %u\n", 1240 cbasm->address_mod); 1241 break; 1242 } 1243 break; 1244 } 1245 } 1246 1247 void 1248 mptable_pci_host_res_init(device_t pcib) 1249 { 1250 struct host_res_args args; 1251 1252 KASSERT(pci0 != -1, ("do not know how to map PCI bus IDs")); 1253 args.bus = pci_get_bus(pcib) + pci0; 1254 args.dev = pcib; 1255 args.sc = device_get_softc(pcib); 1256 if (pcib_host_res_init(pcib, &args.sc->sc_host_res) != 0) 1257 panic("failed to init hostb resources"); 1258 mptable_walk_extended_table(mptable_host_res_handler, &args); 1259 } 1260 #endif 1261