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 500 static void 501 mptable_setup_cpus_handler(u_char *entry, void *arg) 502 { 503 proc_entry_ptr proc; 504 u_int *cpu_mask; 505 506 switch (*entry) { 507 case MPCT_ENTRY_PROCESSOR: 508 proc = (proc_entry_ptr)entry; 509 if (proc->cpu_flags & PROCENTRY_FLAG_EN) { 510 lapic_create(proc->apic_id, proc->cpu_flags & 511 PROCENTRY_FLAG_BP); 512 if (proc->apic_id < MAX_LAPIC_ID) { 513 cpu_mask = (u_int *)arg; 514 *cpu_mask |= (1ul << proc->apic_id); 515 } 516 } 517 break; 518 } 519 } 520 521 static void 522 mptable_count_items_handler(u_char *entry, void *arg __unused) 523 { 524 io_apic_entry_ptr apic; 525 bus_entry_ptr bus; 526 527 switch (*entry) { 528 case MPCT_ENTRY_BUS: 529 bus = (bus_entry_ptr)entry; 530 mptable_nbusses++; 531 if (bus->bus_id > mptable_maxbusid) 532 mptable_maxbusid = bus->bus_id; 533 break; 534 case MPCT_ENTRY_IOAPIC: 535 apic = (io_apic_entry_ptr)entry; 536 if (apic->apic_flags & IOAPICENTRY_FLAG_EN) 537 mptable_nioapics++; 538 break; 539 } 540 } 541 542 /* 543 * Count items in the table. 544 */ 545 static void 546 mptable_count_items(void) 547 { 548 549 /* Is this a pre-defined config? */ 550 if (mpfps->config_type != 0) { 551 mptable_nioapics = 1; 552 switch (mpfps->config_type) { 553 case 1: 554 case 2: 555 case 3: 556 case 4: 557 mptable_nbusses = 1; 558 break; 559 case 5: 560 case 6: 561 case 7: 562 mptable_nbusses = 2; 563 break; 564 default: 565 panic("Unknown pre-defined MP Table config type %d", 566 mpfps->config_type); 567 } 568 mptable_maxbusid = mptable_nbusses - 1; 569 } else 570 mptable_walk_table(mptable_count_items_handler, NULL); 571 } 572 573 /* 574 * Add a bus or I/O APIC from an entry in the table. 575 */ 576 static void 577 mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused) 578 { 579 io_apic_entry_ptr apic; 580 bus_entry_ptr bus; 581 enum busTypes bus_type; 582 int i; 583 584 585 switch (*entry) { 586 case MPCT_ENTRY_BUS: 587 bus = (bus_entry_ptr)entry; 588 bus_type = lookup_bus_type(bus->bus_type); 589 if (bus_type == UNKNOWN_BUSTYPE) { 590 printf("MPTable: Unknown bus %d type \"", bus->bus_id); 591 for (i = 0; i < 6; i++) 592 printf("%c", bus->bus_type[i]); 593 printf("\"\n"); 594 } 595 busses[bus->bus_id].bus_id = bus->bus_id; 596 busses[bus->bus_id].bus_type = bus_type; 597 break; 598 case MPCT_ENTRY_IOAPIC: 599 apic = (io_apic_entry_ptr)entry; 600 if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN)) 601 break; 602 if (apic->apic_id > IOAPIC_MAX_ID) 603 panic("%s: I/O APIC ID %d too high", __func__, 604 apic->apic_id); 605 if (ioapics[apic->apic_id] != NULL) 606 panic("%s: Double APIC ID %d", __func__, 607 apic->apic_id); 608 ioapics[apic->apic_id] = ioapic_create(apic->apic_address, 609 apic->apic_id, -1); 610 break; 611 default: 612 break; 613 } 614 } 615 616 /* 617 * Enumerate I/O APIC's and buses. 618 */ 619 static void 620 mptable_parse_apics_and_busses(void) 621 { 622 623 /* Is this a pre-defined config? */ 624 if (mpfps->config_type != 0) { 625 ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0); 626 busses[0].bus_id = 0; 627 busses[0].bus_type = default_data[mpfps->config_type - 1][2]; 628 if (mptable_nbusses > 1) { 629 busses[1].bus_id = 1; 630 busses[1].bus_type = 631 default_data[mpfps->config_type - 1][4]; 632 } 633 } else 634 mptable_walk_table(mptable_parse_apics_and_busses_handler, 635 NULL); 636 } 637 638 /* 639 * Determine conforming polarity for a given bus type. 640 */ 641 static enum intr_polarity 642 conforming_polarity(u_char src_bus, u_char src_bus_irq) 643 { 644 645 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); 646 switch (busses[src_bus].bus_type) { 647 case ISA: 648 case EISA: 649 return (INTR_POLARITY_HIGH); 650 case PCI: 651 return (INTR_POLARITY_LOW); 652 default: 653 panic("%s: unknown bus type %d", __func__, 654 busses[src_bus].bus_type); 655 } 656 } 657 658 /* 659 * Determine conforming trigger for a given bus type. 660 */ 661 static enum intr_trigger 662 conforming_trigger(u_char src_bus, u_char src_bus_irq) 663 { 664 665 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus)); 666 switch (busses[src_bus].bus_type) { 667 case ISA: 668 if (elcr_found) 669 return (elcr_read_trigger(src_bus_irq)); 670 else 671 return (INTR_TRIGGER_EDGE); 672 case PCI: 673 return (INTR_TRIGGER_LEVEL); 674 675 case EISA: 676 KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq)); 677 KASSERT(elcr_found, ("Missing ELCR")); 678 return (elcr_read_trigger(src_bus_irq)); 679 680 default: 681 panic("%s: unknown bus type %d", __func__, 682 busses[src_bus].bus_type); 683 } 684 } 685 686 static enum intr_polarity 687 intentry_polarity(int_entry_ptr intr) 688 { 689 690 switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) { 691 case INTENTRY_FLAGS_POLARITY_CONFORM: 692 return (conforming_polarity(intr->src_bus_id, 693 intr->src_bus_irq)); 694 case INTENTRY_FLAGS_POLARITY_ACTIVEHI: 695 return (INTR_POLARITY_HIGH); 696 case INTENTRY_FLAGS_POLARITY_ACTIVELO: 697 return (INTR_POLARITY_LOW); 698 default: 699 panic("Bogus interrupt flags"); 700 } 701 } 702 703 static enum intr_trigger 704 intentry_trigger(int_entry_ptr intr) 705 { 706 707 switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) { 708 case INTENTRY_FLAGS_TRIGGER_CONFORM: 709 return (conforming_trigger(intr->src_bus_id, 710 intr->src_bus_irq)); 711 case INTENTRY_FLAGS_TRIGGER_EDGE: 712 return (INTR_TRIGGER_EDGE); 713 case INTENTRY_FLAGS_TRIGGER_LEVEL: 714 return (INTR_TRIGGER_LEVEL); 715 default: 716 panic("Bogus interrupt flags"); 717 } 718 } 719 720 /* 721 * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC. 722 */ 723 static void 724 mptable_parse_io_int(int_entry_ptr intr) 725 { 726 void *ioapic; 727 u_int pin, apic_id; 728 729 apic_id = intr->dst_apic_id; 730 if (intr->dst_apic_id == 0xff) { 731 /* 732 * An APIC ID of 0xff means that the interrupt is connected 733 * to the specified pin on all I/O APICs in the system. If 734 * there is only one I/O APIC, then use that APIC to route 735 * the interrupts. If there is more than one I/O APIC, then 736 * punt. 737 */ 738 if (mptable_nioapics == 1) { 739 apic_id = 0; 740 while (ioapics[apic_id] == NULL) 741 apic_id++; 742 } else { 743 printf( 744 "MPTable: Ignoring global interrupt entry for pin %d\n", 745 intr->dst_apic_int); 746 return; 747 } 748 } 749 if (apic_id > IOAPIC_MAX_ID) { 750 printf("MPTable: Ignoring interrupt entry for ioapic%d\n", 751 intr->dst_apic_id); 752 return; 753 } 754 ioapic = ioapics[apic_id]; 755 if (ioapic == NULL) { 756 printf( 757 "MPTable: Ignoring interrupt entry for missing ioapic%d\n", 758 apic_id); 759 return; 760 } 761 pin = intr->dst_apic_int; 762 switch (intr->int_type) { 763 case INTENTRY_TYPE_INT: 764 switch (busses[intr->src_bus_id].bus_type) { 765 case NOBUS: 766 panic("interrupt from missing bus"); 767 case ISA: 768 case EISA: 769 if (busses[intr->src_bus_id].bus_type == ISA) 770 ioapic_set_bus(ioapic, pin, APIC_BUS_ISA); 771 else 772 ioapic_set_bus(ioapic, pin, APIC_BUS_EISA); 773 if (intr->src_bus_irq == pin) 774 break; 775 ioapic_remap_vector(ioapic, pin, intr->src_bus_irq); 776 if (ioapic_get_vector(ioapic, intr->src_bus_irq) == 777 intr->src_bus_irq) 778 ioapic_disable_pin(ioapic, intr->src_bus_irq); 779 break; 780 case PCI: 781 ioapic_set_bus(ioapic, pin, APIC_BUS_PCI); 782 break; 783 default: 784 ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN); 785 break; 786 } 787 break; 788 case INTENTRY_TYPE_NMI: 789 ioapic_set_nmi(ioapic, pin); 790 break; 791 case INTENTRY_TYPE_SMI: 792 ioapic_set_smi(ioapic, pin); 793 break; 794 case INTENTRY_TYPE_EXTINT: 795 ioapic_set_extint(ioapic, pin); 796 break; 797 default: 798 panic("%s: invalid interrupt entry type %d\n", __func__, 799 intr->int_type); 800 } 801 if (intr->int_type == INTENTRY_TYPE_INT || 802 (intr->int_flags & INTENTRY_FLAGS_TRIGGER) != 803 INTENTRY_FLAGS_TRIGGER_CONFORM) 804 ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr)); 805 if (intr->int_type == INTENTRY_TYPE_INT || 806 (intr->int_flags & INTENTRY_FLAGS_POLARITY) != 807 INTENTRY_FLAGS_POLARITY_CONFORM) 808 ioapic_set_polarity(ioapic, pin, intentry_polarity(intr)); 809 } 810 811 /* 812 * Parse an interrupt entry for a local APIC LVT pin. 813 */ 814 static void 815 mptable_parse_local_int(int_entry_ptr intr) 816 { 817 u_int apic_id, pin; 818 819 if (intr->dst_apic_id == 0xff) 820 apic_id = APIC_ID_ALL; 821 else 822 apic_id = intr->dst_apic_id; 823 if (intr->dst_apic_int == 0) 824 pin = APIC_LVT_LINT0; 825 else 826 pin = APIC_LVT_LINT1; 827 switch (intr->int_type) { 828 case INTENTRY_TYPE_INT: 829 #if 1 830 printf( 831 "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n", 832 intr->dst_apic_int, intr->src_bus_irq); 833 return; 834 #else 835 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED); 836 break; 837 #endif 838 case INTENTRY_TYPE_NMI: 839 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI); 840 break; 841 case INTENTRY_TYPE_SMI: 842 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI); 843 break; 844 case INTENTRY_TYPE_EXTINT: 845 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT); 846 break; 847 default: 848 panic("%s: invalid interrupt entry type %d\n", __func__, 849 intr->int_type); 850 } 851 if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) != 852 INTENTRY_FLAGS_TRIGGER_CONFORM) 853 lapic_set_lvt_triggermode(apic_id, pin, 854 intentry_trigger(intr)); 855 if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) != 856 INTENTRY_FLAGS_POLARITY_CONFORM) 857 lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr)); 858 } 859 860 /* 861 * Parse interrupt entries. 862 */ 863 static void 864 mptable_parse_ints_handler(u_char *entry, void *arg __unused) 865 { 866 int_entry_ptr intr; 867 868 intr = (int_entry_ptr)entry; 869 switch (*entry) { 870 case MPCT_ENTRY_INT: 871 mptable_parse_io_int(intr); 872 break; 873 case MPCT_ENTRY_LOCAL_INT: 874 mptable_parse_local_int(intr); 875 break; 876 } 877 } 878 879 /* 880 * Configure interrupt pins for a default configuration. For details see 881 * Table 5-2 in Section 5 of the MP Table specification. 882 */ 883 static void 884 mptable_parse_default_config_ints(void) 885 { 886 struct INTENTRY entry; 887 int pin; 888 889 /* 890 * All default configs route IRQs from bus 0 to the first 16 pins 891 * of the first I/O APIC with an APIC ID of 2. 892 */ 893 entry.type = MPCT_ENTRY_INT; 894 entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | 895 INTENTRY_FLAGS_TRIGGER_CONFORM; 896 entry.src_bus_id = 0; 897 entry.dst_apic_id = 2; 898 899 /* Run through all 16 pins. */ 900 for (pin = 0; pin < 16; pin++) { 901 entry.dst_apic_int = pin; 902 switch (pin) { 903 case 0: 904 /* Pin 0 is an ExtINT pin. */ 905 entry.int_type = INTENTRY_TYPE_EXTINT; 906 break; 907 case 2: 908 /* IRQ 0 is routed to pin 2. */ 909 entry.int_type = INTENTRY_TYPE_INT; 910 entry.src_bus_irq = 0; 911 break; 912 default: 913 /* All other pins are identity mapped. */ 914 entry.int_type = INTENTRY_TYPE_INT; 915 entry.src_bus_irq = pin; 916 break; 917 } 918 mptable_parse_io_int(&entry); 919 } 920 921 /* Certain configs disable certain pins. */ 922 if (mpfps->config_type == 7) 923 ioapic_disable_pin(ioapics[2], 0); 924 if (mpfps->config_type == 2) { 925 ioapic_disable_pin(ioapics[2], 2); 926 ioapic_disable_pin(ioapics[2], 13); 927 } 928 } 929 930 /* 931 * Configure the interrupt pins 932 */ 933 static void 934 mptable_parse_ints(void) 935 { 936 937 /* Is this a pre-defined config? */ 938 if (mpfps->config_type != 0) { 939 /* Configure LINT pins. */ 940 lapic_set_lvt_mode(APIC_ID_ALL, APIC_LVT_LINT0, 941 APIC_LVT_DM_EXTINT); 942 lapic_set_lvt_mode(APIC_ID_ALL, APIC_LVT_LINT1, APIC_LVT_DM_NMI); 943 944 /* Configure I/O APIC pins. */ 945 mptable_parse_default_config_ints(); 946 } else 947 mptable_walk_table(mptable_parse_ints_handler, NULL); 948 } 949 950 #ifdef MPTABLE_FORCE_HTT 951 /* 952 * Perform a hyperthreading "fix-up" to enumerate any logical CPU's 953 * that aren't already listed in the table. 954 * 955 * XXX: We assume that all of the physical CPUs in the 956 * system have the same number of logical CPUs. 957 * 958 * XXX: We assume that APIC ID's are allocated such that 959 * the APIC ID's for a physical processor are aligned 960 * with the number of logical CPU's in the processor. 961 */ 962 static void 963 mptable_hyperthread_fixup(u_int id_mask) 964 { 965 u_int i, id, logical_cpus; 966 967 /* Nothing to do if there is no HTT support. */ 968 if ((cpu_feature & CPUID_HTT) == 0) 969 return; 970 logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; 971 if (logical_cpus <= 1) 972 return; 973 974 /* 975 * For each APIC ID of a CPU that is set in the mask, 976 * scan the other candidate APIC ID's for this 977 * physical processor. If any of those ID's are 978 * already in the table, then kill the fixup. 979 */ 980 for (id = 0; id <= MAX_LAPIC_ID; id++) { 981 if ((id_mask & 1 << id) == 0) 982 continue; 983 /* First, make sure we are on a logical_cpus boundary. */ 984 if (id % logical_cpus != 0) 985 return; 986 for (i = id + 1; i < id + logical_cpus; i++) 987 if ((id_mask & 1 << i) != 0) 988 return; 989 } 990 991 /* 992 * Ok, the ID's checked out, so perform the fixup by 993 * adding the logical CPUs. 994 */ 995 while ((id = ffs(id_mask)) != 0) { 996 id--; 997 for (i = id + 1; i < id + logical_cpus; i++) { 998 if (bootverbose) 999 printf( 1000 "MPTable: Adding logical CPU %d from main CPU %d\n", 1001 i, id); 1002 lapic_create(i, 0); 1003 } 1004 id_mask &= ~(1 << id); 1005 } 1006 } 1007 #endif /* MPTABLE_FORCE_HTT */ 1008 1009 /* 1010 * Support code for routing PCI interrupts using the MP Table. 1011 */ 1012 static void 1013 mptable_pci_setup(void) 1014 { 1015 int i; 1016 1017 /* 1018 * Find the first pci bus and call it 0. Panic if pci0 is not 1019 * bus zero and there are multiple PCI buses. 1020 */ 1021 for (i = 0; i <= mptable_maxbusid; i++) 1022 if (busses[i].bus_type == PCI) { 1023 if (pci0 == -1) 1024 pci0 = i; 1025 else if (pci0 != 0) 1026 panic( 1027 "MPTable contains multiple PCI buses but no PCI bus 0"); 1028 } 1029 } 1030 1031 static void 1032 mptable_pci_probe_table_handler(u_char *entry, void *arg) 1033 { 1034 struct pci_probe_table_args *args; 1035 int_entry_ptr intr; 1036 1037 if (*entry != MPCT_ENTRY_INT) 1038 return; 1039 intr = (int_entry_ptr)entry; 1040 args = (struct pci_probe_table_args *)arg; 1041 KASSERT(args->bus <= mptable_maxbusid, 1042 ("bus %d is too big", args->bus)); 1043 KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus")); 1044 if (intr->src_bus_id == args->bus) 1045 args->found = 1; 1046 } 1047 1048 int 1049 mptable_pci_probe_table(int bus) 1050 { 1051 struct pci_probe_table_args args; 1052 1053 if (bus < 0) 1054 return (EINVAL); 1055 if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid) 1056 return (ENXIO); 1057 if (busses[pci0 + bus].bus_type != PCI) 1058 return (ENXIO); 1059 args.bus = pci0 + bus; 1060 args.found = 0; 1061 mptable_walk_table(mptable_pci_probe_table_handler, &args); 1062 if (args.found == 0) 1063 return (ENXIO); 1064 return (0); 1065 } 1066 1067 static void 1068 mptable_pci_route_interrupt_handler(u_char *entry, void *arg) 1069 { 1070 struct pci_route_interrupt_args *args; 1071 int_entry_ptr intr; 1072 int vector; 1073 1074 if (*entry != MPCT_ENTRY_INT) 1075 return; 1076 intr = (int_entry_ptr)entry; 1077 args = (struct pci_route_interrupt_args *)arg; 1078 if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq) 1079 return; 1080 1081 /* Make sure the APIC maps to a known APIC. */ 1082 KASSERT(ioapics[intr->dst_apic_id] != NULL, 1083 ("No I/O APIC %d to route interrupt to", intr->dst_apic_id)); 1084 1085 /* 1086 * Look up the vector for this APIC / pin combination. If we 1087 * have previously matched an entry for this PCI IRQ but it 1088 * has the same vector as this entry, just return. Otherwise, 1089 * we use the vector for this APIC / pin combination. 1090 */ 1091 vector = ioapic_get_vector(ioapics[intr->dst_apic_id], 1092 intr->dst_apic_int); 1093 if (args->vector == vector) 1094 return; 1095 KASSERT(args->vector == -1, 1096 ("Multiple IRQs for PCI interrupt %d.%d.INT%c: %d and %d\n", 1097 args->bus, args->irq >> 2, 'A' + (args->irq & 0x3), args->vector, 1098 vector)); 1099 args->vector = vector; 1100 } 1101 1102 int 1103 mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin) 1104 { 1105 struct pci_route_interrupt_args args; 1106 int slot; 1107 1108 /* Like ACPI, pin numbers are 0-3, not 1-4. */ 1109 pin--; 1110 KASSERT(pci0 != -1, ("do not know how to route PCI interrupts")); 1111 args.bus = pci_get_bus(dev) + pci0; 1112 slot = pci_get_slot(dev); 1113 1114 /* 1115 * PCI interrupt entries in the MP Table encode both the slot and 1116 * pin into the IRQ with the pin being the two least significant 1117 * bits, the slot being the next five bits, and the most significant 1118 * bit being reserved. 1119 */ 1120 args.irq = slot << 2 | pin; 1121 args.vector = -1; 1122 mptable_walk_table(mptable_pci_route_interrupt_handler, &args); 1123 if (args.vector < 0) { 1124 device_printf(pcib, "unable to route slot %d INT%c\n", slot, 1125 'A' + pin); 1126 return (PCI_INVALID_IRQ); 1127 } 1128 if (bootverbose) 1129 device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 1130 'A' + pin, args.vector); 1131 return (args.vector); 1132 } 1133 1134 #ifdef NEW_PCIB 1135 struct host_res_args { 1136 struct mptable_hostb_softc *sc; 1137 device_t dev; 1138 u_char bus; 1139 }; 1140 1141 /* 1142 * Initialize a Host-PCI bridge so it can restrict resource allocation 1143 * requests to the resources it actually decodes according to MP 1144 * config table extended entries. 1145 */ 1146 static void 1147 mptable_host_res_handler(ext_entry_ptr entry, void *arg) 1148 { 1149 struct host_res_args *args; 1150 cbasm_entry_ptr cbasm; 1151 sas_entry_ptr sas; 1152 const char *name; 1153 uint64_t start, end; 1154 int error, *flagp, flags, type; 1155 1156 args = arg; 1157 switch (entry->type) { 1158 case MPCT_EXTENTRY_SAS: 1159 sas = (sas_entry_ptr)entry; 1160 if (sas->bus_id != args->bus) 1161 break; 1162 switch (sas->address_type) { 1163 case SASENTRY_TYPE_IO: 1164 type = SYS_RES_IOPORT; 1165 flags = 0; 1166 break; 1167 case SASENTRY_TYPE_MEMORY: 1168 type = SYS_RES_MEMORY; 1169 flags = 0; 1170 break; 1171 case SASENTRY_TYPE_PREFETCH: 1172 type = SYS_RES_MEMORY; 1173 flags = RF_PREFETCHABLE; 1174 break; 1175 default: 1176 printf( 1177 "MPTable: Unknown systems address space type for bus %u: %d\n", 1178 sas->bus_id, sas->address_type); 1179 return; 1180 } 1181 start = sas->address_base; 1182 end = sas->address_base + sas->address_length - 1; 1183 #ifdef __i386__ 1184 if (start > ULONG_MAX) { 1185 device_printf(args->dev, 1186 "Ignoring %d range above 4GB (%#jx-%#jx)\n", 1187 type, (uintmax_t)start, (uintmax_t)end); 1188 break; 1189 } 1190 if (end > ULONG_MAX) { 1191 device_printf(args->dev, 1192 "Truncating end of %d range above 4GB (%#jx-%#jx)\n", 1193 type, (uintmax_t)start, (uintmax_t)end); 1194 end = ULONG_MAX; 1195 } 1196 #endif 1197 error = pcib_host_res_decodes(&args->sc->sc_host_res, type, 1198 start, end, flags); 1199 if (error) 1200 panic("Failed to manage %d range (%#jx-%#jx): %d", 1201 type, (uintmax_t)start, (uintmax_t)end, error); 1202 break; 1203 case MPCT_EXTENTRY_CBASM: 1204 cbasm = (cbasm_entry_ptr)entry; 1205 if (cbasm->bus_id != args->bus) 1206 break; 1207 switch (cbasm->predefined_range) { 1208 case CBASMENTRY_RANGE_ISA_IO: 1209 flagp = &args->sc->sc_decodes_isa_io; 1210 name = "ISA I/O"; 1211 break; 1212 case CBASMENTRY_RANGE_VGA_IO: 1213 flagp = &args->sc->sc_decodes_vga_io; 1214 name = "VGA I/O"; 1215 break; 1216 default: 1217 printf( 1218 "MPTable: Unknown compatiblity address space range for bus %u: %d\n", 1219 cbasm->bus_id, cbasm->predefined_range); 1220 return; 1221 } 1222 if (*flagp != 0) 1223 printf( 1224 "MPTable: Duplicate compatibility %s range for bus %u\n", 1225 name, cbasm->bus_id); 1226 switch (cbasm->address_mod) { 1227 case CBASMENTRY_ADDRESS_MOD_ADD: 1228 *flagp = 1; 1229 if (bootverbose) 1230 device_printf(args->dev, "decoding %s ports\n", 1231 name); 1232 break; 1233 case CBASMENTRY_ADDRESS_MOD_SUBTRACT: 1234 *flagp = -1; 1235 if (bootverbose) 1236 device_printf(args->dev, 1237 "not decoding %s ports\n", name); 1238 break; 1239 default: 1240 printf( 1241 "MPTable: Unknown compatibility address space modifier: %u\n", 1242 cbasm->address_mod); 1243 break; 1244 } 1245 break; 1246 } 1247 } 1248 1249 void 1250 mptable_pci_host_res_init(device_t pcib) 1251 { 1252 struct host_res_args args; 1253 1254 KASSERT(pci0 != -1, ("do not know how to map PCI bus IDs")); 1255 args.bus = pci_get_bus(pcib) + pci0; 1256 args.dev = pcib; 1257 args.sc = device_get_softc(pcib); 1258 if (pcib_host_res_init(pcib, &args.sc->sc_host_res) != 0) 1259 panic("failed to init hostb resources"); 1260 mptable_walk_extended_table(mptable_host_res_handler, &args); 1261 } 1262 #endif 1263