mptable.c revision 25204
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 * $Id: mp_machdep.c,v 1.1 1997/04/26 11:45:15 peter Exp $ 26 */ 27 28#include "opt_smp.h" 29#include "opt_smp_invltlb.h" 30#if defined(APIC_IO) 31#if !defined(SMP_INVLTLB) 32#error you must define BOTH APIC_IO and SMP_INVLTLB or NEITHER 33#endif 34#else /* APIC_IO */ 35#if defined(SMP_INVLTLB) 36#error you must define BOTH APIC_IO and SMP_INVLTLB or NEITHER 37#endif 38#endif /* APIC_IO */ 39#define FIX_MP_TABLE_WORKS_NOT 40 41#include "opt_serial.h" 42 43#include <sys/param.h> /* for KERNBASE */ 44#include <sys/types.h> 45#include <sys/sysproto.h> 46#include <sys/time.h> 47#include <sys/systm.h> 48 49#include <vm/vm.h> /* for KERNBASE */ 50#include <vm/vm_param.h> /* for KERNBASE */ 51#include <vm/pmap.h> /* for KERNBASE */ 52#include <machine/pmap.h> /* for KERNBASE */ 53 54#include <machine/smp.h> 55#include <machine/apic.h> 56#include <machine/mpapic.h> 57#include <machine/cpufunc.h> 58#include <machine/segments.h> 59#include <machine/smptests.h> /** TEST_UPPERPRIO, TEST_DEFAULT_CONFIG */ 60 61#include <i386/i386/cons.h> /* cngetc() */ 62 63#if defined(SMP_INVLTLB) 64#include <i386/isa/icu.h> 65#endif /* SMP_INVLTLB */ 66 67#define WARMBOOT_TARGET 0 68#define WARMBOOT_OFF (KERNBASE + 0x0467) 69#define WARMBOOT_SEG (KERNBASE + 0x0469) 70 71#define BIOS_BASE (0xf0000) 72#define BIOS_SIZE (0x10000) 73#define BIOS_COUNT (BIOS_SIZE/4) 74 75#define CMOS_REG (0x70) 76#define CMOS_DATA (0x71) 77#define BIOS_RESET (0x0f) 78#define BIOS_WARM (0x0a) 79 80/* 81 * this code MUST be enabled here and in mpboot.s. 82 * it follows the very early stages of AP boot by placing values in CMOS ram. 83 * it NORMALLY will never be needed and thus the primitive method for enabling. 84 * 85#define CHECK_POINTS 86 */ 87 88#if defined(CHECK_POINTS) 89#define CHECK_READ(A) (outb(CMOS_REG, (A)), inb(CMOS_DATA)) 90#define CHECK_WRITE(A,D) (outb(CMOS_REG, (A)), outb(CMOS_DATA, (D))) 91 92#define CHECK_INIT(D); \ 93 CHECK_WRITE(0x34, (D)); \ 94 CHECK_WRITE(0x35, (D)); \ 95 CHECK_WRITE(0x36, (D)); \ 96 CHECK_WRITE(0x37, (D)); \ 97 CHECK_WRITE(0x38, (D)); \ 98 CHECK_WRITE(0x39, (D)); 99 100#define CHECK_PRINT(S); \ 101 printf("%s: %d, %d, %d, %d, %d, %d\n", \ 102 (S), \ 103 CHECK_READ(0x34), \ 104 CHECK_READ(0x35), \ 105 CHECK_READ(0x36), \ 106 CHECK_READ(0x37), \ 107 CHECK_READ(0x38), \ 108 CHECK_READ(0x39)); 109 110#else /* CHECK_POINTS */ 111 112#define CHECK_INIT(D) 113#define CHECK_PRINT(S) 114 115#endif /* CHECK_POINTS */ 116 117 118/** FIXME: what system files declare these??? */ 119extern struct region_descriptor r_gdt, r_idt; 120 121/* global data */ 122struct proc *SMPcurproc[NCPU]; 123struct pcb *SMPcurpcb[NCPU]; 124struct timeval SMPruntime[NCPU]; 125 126int mp_ncpus; /* # of CPUs, including BSP */ 127int mp_naps; /* # of Applications processors */ 128int mp_nbusses; /* # of busses */ 129int mp_napics; /* # of IO APICs */ 130int mpenabled; 131int boot_cpu_id; /* designated BSP */ 132vm_offset_t cpu_apic_address; 133vm_offset_t io_apic_address[NAPIC]; 134 135u_int32_t cpu_apic_versions[NCPU]; 136u_int32_t io_apic_versions[NAPIC]; 137 138/* 139 * APIC ID logical/physical mapping structures 140 */ 141int cpu_num_to_apic_id[NCPU]; 142int io_num_to_apic_id[NAPIC]; 143int apic_id_to_logical[NAPICID]; 144 145/* 146 * look for MP compliant motherboard. 147 */ 148 149static u_int boot_address; 150static u_int base_memory; 151 152static int picmode; /* 0: virtual wire mode, 1: PIC mode */ 153static u_int mpfps; 154static int search_for_sig(u_int32_t target, int count); 155static int mp_probe(u_int base_top); 156static void mp_enable(u_int boot_addr); 157 158 159/* 160 * calculate usable address in base memory for AP trampoline code 161 */ 162u_int 163mp_bootaddress(u_int basemem) 164{ 165 base_memory = basemem * 1024; /* convert to bytes */ 166 167 boot_address = base_memory & ~0xfff; /* round down to 4k boundary */ 168 if ((base_memory - boot_address) < bootMP_size) 169 boot_address -= 4096; /* not enough, lower by 4k */ 170 171 return boot_address; 172} 173 174 175/* 176 * startup the SMP processors 177 */ 178void 179mp_start(void) 180{ 181 /* look for MP capable motherboard */ 182 if (mp_probe(base_memory)) 183 mp_enable(boot_address); 184 else { 185 printf("MP FPS NOT FOUND, suggest use of 'mptable' program\n"); 186 panic("can't continue!\n"); 187 } 188 189 /* finish pmap initialization - turn off V==P mapping at zero */ 190 pmap_bootstrap2(); 191} 192 193 194/* 195 * print various information about the SMP system hardware and setup 196 */ 197void 198mp_announce(void) 199{ 200 int x; 201 202 printf("FreeBSD/SMP: Multiprocessor motherboard\n"); 203 printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0)); 204 printf(", version: 0x%08x\n", cpu_apic_versions[0]); 205 for (x = 1; x <= mp_naps; ++x) { 206 printf(" cpu%d (AP): apic id: %d", x, CPU_TO_ID(x)); 207 printf(", version: 0x%08x\n", cpu_apic_versions[x]); 208 } 209 210#if defined(APIC_IO) 211 for (x = 0; x < mp_napics; ++x) { 212 printf(" io%d (APIC): apic id: %d", x, IO_TO_ID(x)); 213 printf(", version: 0x%08x\n", io_apic_versions[x]); 214 } 215#else 216 printf(" Warning: APIC I/O disabled\n"); 217#endif /* APIC_IO */ 218} 219 220 221/* 222 * AP cpu's call this to sync up protected mode. 223 */ 224void 225init_secondary(void) 226{ 227 int gsel_tss, slot; 228 229 r_gdt.rd_limit = sizeof(gdt[0]) * (NGDT + NCPU) - 1; 230 r_gdt.rd_base = (int) gdt; 231 lgdt(&r_gdt); /* does magic intra-segment return */ 232 lidt(&r_idt); 233 lldt(_default_ldt); 234 235 slot = NGDT + cpunumber(); 236 gsel_tss = GSEL(slot, SEL_KPL); 237 gdt[slot].sd.sd_type = SDT_SYS386TSS; 238 ltr(gsel_tss); 239 240 load_cr0(0x8005003b); /* XXX! */ 241} 242 243 244#if defined(APIC_IO) 245void 246configure_local_apic(void) 247{ 248 u_char byte; 249 u_int32_t temp; 250 251 if (picmode) { 252 outb(0x22, 0x70); /* select IMCR */ 253 byte = inb(0x23); /* current contents */ 254 byte |= 0x01; /* mask external INTR */ 255 outb(0x23, byte); /* disconnect 8259s/NMI */ 256 } 257 /* mask the LVT1 */ 258 temp = apic_base[APIC_LVT1]; 259 temp |= APIC_LVT_M; 260 apic_base[APIC_LVT1] = temp; 261} 262#endif /* APIC_IO */ 263 264 265/******************************************************************* 266 * local functions and data 267 */ 268 269static int 270mp_probe(u_int base_top) 271{ 272 int x; 273 u_long segment; 274 u_int32_t target; 275 276 /* see if EBDA exists */ 277 if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) { 278 /* search first 1K of EBDA */ 279 target = (u_int32_t) (segment << 4); 280 if ((x = search_for_sig(target, 1024 / 4)) >= 0) 281 goto found; 282 } else { 283 /*last 1K of base memory, effective 'top of base' is passed in*/ 284 target = (u_int32_t) (base_top - 0x400); 285 if ((x = search_for_sig(target, 1024 / 4)) >= 0) 286 goto found; 287 } 288 289 /* search the BIOS */ 290 target = (u_int32_t) BIOS_BASE; 291 if ((x = search_for_sig(target, BIOS_COUNT)) >= 0) 292 goto found; 293 294 /* nothing found */ 295 mpfps = mpenabled = 0; 296 return 0; 297 298found: /* please forgive the 'goto'! */ 299 /* flag fact that we are running multiple processors */ 300 mpfps = x; 301 mpenabled = 1; 302 return 1; 303} 304 305 306/* 307 * start the SMP system 308 */ 309static int parse_mp_table(void); 310static void default_mp_table(int type); 311static int start_all_aps(u_int boot_addr); 312 313#if defined(APIC_IO) 314#include <i386/include/md_var.h> /* setidt() */ 315#include <i386/isa/isa_device.h> /* Xinvltlb() */ 316#endif /* APIC_IO */ 317 318static void 319mp_enable(u_int boot_addr) 320{ 321 int x; 322#if defined(APIC_IO) 323 int apic; 324 u_int ux; 325#if defined(TEST_UPPERPRIO) 326 u_char select; /* the select register is 8 bits */ 327 u_int32_t flags; /* the window register is 32 bits */ 328#endif /* TEST_UPPERPRIO */ 329#endif /* APIC_IO */ 330 331 /* examine the MP table for needed info */ 332 x = parse_mp_table(); 333 334 /* create pages for (address common) cpu APIC and each IO APIC */ 335 pmap_bootstrap_apics(); 336 337 /* can't process default configs till the CPU APIC is pmapped */ 338 if (x) 339 default_mp_table(x); 340 341#if defined(APIC_IO) 342 /* fill the LOGICAL io_apic_versions table */ 343 for (apic = 0; apic < mp_napics; ++apic) { 344 ux = io_apic_read(apic, IOAPIC_VER); 345 io_apic_versions[apic] = ux; 346 } 347 348 /* 349 */ 350 for (apic = 0; apic < mp_napics; ++apic) 351 if (io_apic_setup(apic) < 0) 352 panic("IO APIC setup failure\n"); 353 354 /* install an inter-CPU IPI for TLB invalidation */ 355 setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb, 356 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 357 358#if defined(TEST_UPPERPRIO) 359 360#if 1 361 printf("special IRQ10\n"); 362 select = IOAPIC_REDTBL10; /** HARD_VECTORXXX: */ 363 flags = io_apic_read(0, select); 364 flags &= ~0xff; /** clear vector */ 365 flags |= 64; 366 io_apic_write(0, select, flags); 367#else 368 printf("special IRQ10\n"); 369 cngetc(); 370 select = IOAPIC_REDTBL10; /** HARD_VECTORXXX: */ 371 flags = io_apic_read(0, select); 372 flags &= ~IOART_DELMOD; /* FIXED mode */ 373 io_apic_write(0, select, flags); 374 io_apic_write(0, select + 1, boot_cpu_id << 24); 375#endif /** 0/1 */ 376 377#endif /* TEST_UPPERPRIO */ 378 379#endif /* APIC_IO */ 380 381 /* start each Application Processor */ 382 start_all_aps(boot_addr); 383} 384 385 386/* 387 * look for the MP spec signature 388 */ 389 390/* string defined by the Intel MP Spec as identifying the MP table */ 391#define MP_SIG 0x5f504d5f /* _MP_ */ 392#define NEXT(X) ((X) += 4) 393static int 394search_for_sig(u_int32_t target, int count) 395{ 396 int x; 397 u_int32_t *addr = (u_int32_t *) (KERNBASE + target); 398 399 for (x = 0; x < count; NEXT(x)) 400 if (addr[x] == MP_SIG) 401 /* make array index a byte index */ 402 return (target + (x * sizeof(u_int32_t))); 403 404 return -1; 405} 406 407 408#define PROCENTRY_FLAG_EN 0x01 409#define PROCENTRY_FLAG_BP 0x02 410#define IOAPICENTRY_FLAG_EN 0x01 411 412/* MP Floating Pointer Structure */ 413typedef struct MPFPS { 414 char signature[4]; 415 void *pap; 416 u_char length; 417 u_char spec_rev; 418 u_char checksum; 419 u_char mpfb1; 420 u_char mpfb2; 421 u_char mpfb3; 422 u_char mpfb4; 423 u_char mpfb5; 424} *mpfps_t; 425/* MP Configuration Table Header */ 426typedef struct MPCTH { 427 char signature[4]; 428 u_short base_table_length; 429 u_char spec_rev; 430 u_char checksum; 431 u_char oem_id[8]; 432 u_char product_id[12]; 433 void *oem_table_pointer; 434 u_short oem_table_size; 435 u_short entry_count; 436 void *apic_address; 437 u_short extended_table_length; 438 u_char extended_table_checksum; 439 u_char reserved; 440} *mpcth_t; 441 442 443typedef struct PROCENTRY { 444 u_char type; 445 u_char apic_id; 446 u_char apic_version; 447 u_char cpu_flags; 448 u_long cpu_signature; 449 u_long feature_flags; 450 u_long reserved1; 451 u_long reserved2; 452} *proc_entry_ptr; 453 454typedef struct BUSENTRY { 455 u_char type; 456 u_char bus_id; 457 char bus_type[6]; 458} *bus_entry_ptr; 459 460typedef struct IOAPICENTRY { 461 u_char type; 462 u_char apic_id; 463 u_char apic_version; 464 u_char apic_flags; 465 void *apic_address; 466} *io_apic_entry_ptr; 467 468typedef struct INTENTRY { 469 u_char type; 470 u_char int_type; 471 u_short int_flags; 472 u_char src_bus_id; 473 u_char src_bus_irq; 474 u_char dst_apic_id; 475 u_char dst_apic_int; 476} *int_entry_ptr; 477/* descriptions of MP basetable entries */ 478typedef struct BASETABLE_ENTRY { 479 u_char type; 480 u_char length; 481 char name[16]; 482} basetable_entry; 483 484static basetable_entry basetable_entry_types[] = 485{ 486 {0, 20, "Processor"}, 487 {1, 8, "Bus"}, 488 {2, 8, "I/O APIC"}, 489 {3, 8, "I/O INT"}, 490 {4, 8, "Local INT"} 491}; 492 493typedef struct BUSDATA { 494 u_char bus_id; 495 enum busTypes bus_type; 496} bus_datum; 497 498typedef struct INTDATA { 499 u_char int_type; 500 u_short int_flags; 501 u_char src_bus_id; 502 u_char src_bus_irq; 503 u_char dst_apic_id; 504 u_char dst_apic_int; 505} io_int, local_int; 506 507typedef struct BUSTYPENAME { 508 u_char type; 509 char name[7]; 510} bus_type_name; 511 512static bus_type_name bus_type_table[] = 513{ 514 {CBUS, "CBUS"}, 515 {CBUSII, "CBUSII"}, 516 {EISA, "EISA"}, 517 {UNKNOWN_BUSTYPE, "---"}, 518 {UNKNOWN_BUSTYPE, "---"}, 519 {ISA, "ISA"}, 520 {UNKNOWN_BUSTYPE, "---"}, 521 {UNKNOWN_BUSTYPE, "---"}, 522 {UNKNOWN_BUSTYPE, "---"}, 523 {UNKNOWN_BUSTYPE, "---"}, 524 {UNKNOWN_BUSTYPE, "---"}, 525 {UNKNOWN_BUSTYPE, "---"}, 526 {PCI, "PCI"}, 527 {UNKNOWN_BUSTYPE, "---"}, 528 {UNKNOWN_BUSTYPE, "---"}, 529 {UNKNOWN_BUSTYPE, "---"}, 530 {UNKNOWN_BUSTYPE, "---"}, 531 {XPRESS, "XPRESS"}, 532 {UNKNOWN_BUSTYPE, "---"} 533}; 534/* from MP spec v1.4, table 5-1 */ 535static int default_data[7][5] = 536{ 537/* nbus, id0, type0, id1, type1 */ 538 {1, 0, ISA, 255, 255}, 539 {1, 0, EISA, 255, 255}, 540 {1, 0, EISA, 255, 255}, 541 {0, 255, 255, 255, 255},/* MCA not supported */ 542 {2, 0, ISA, 1, PCI}, 543 {2, 0, EISA, 1, PCI}, 544 {0, 255, 255, 255, 255} /* MCA not supported */ 545}; 546 547 548/* the bus data */ 549bus_datum bus_data[NBUS]; 550 551/* the IO INT data, one entry per possible APIC INTerrupt */ 552io_int io_apic_ints[NINTR]; 553 554static int nintrs; 555 556#if defined(FIX_MP_TABLE_WORKS) 557static void fix_mp_table __P((void)); 558#endif /* FIX_MP_TABLE_WORKS */ 559 560static void processor_entry __P((proc_entry_ptr entry, int *cpu)); 561static void io_apic_entry __P((io_apic_entry_ptr entry, int *apic)); 562static void bus_entry __P((bus_entry_ptr entry, int *bus)); 563static void int_entry __P((int_entry_ptr entry, int *intr)); 564static int lookup_bus_type __P((char *name)); 565 566 567/* 568 * parse an Intel MP specification table 569 */ 570static int 571parse_mp_table(void) 572{ 573 int x; 574 mpfps_t fps; 575 mpcth_t cth; 576 int totalSize; 577 void *position; 578 int count; 579 int type; 580 int apic, bus, cpu, intr; 581 582 /* clear physical APIC ID to logical CPU/IO table */ 583 for (x = 0; x < NAPICID; ++x) 584 ID_TO_IO(x) = -1; 585 586 /* clear logical CPU to APIC ID table */ 587 for (x = 0; x < NCPU; ++x) 588 CPU_TO_ID(x) = -1; 589 590 /* clear logical IO to APIC ID table */ 591 for (x = 0; x < NAPIC; ++x) 592 IO_TO_ID(x) = -1; 593 594 /* clear IO APIC address table */ 595 for (x = 0; x < NAPIC; ++x) 596 io_apic_address[x] = ~0; 597 598 /* clear bus data table */ 599 for (x = 0; x < NBUS; ++x) 600 bus_data[x].bus_id = 0xff; 601 602 /* clear IO APIC INT table */ 603 for (x = 0; x < NINTR; ++x) 604 io_apic_ints[x].int_type = 0xff; 605 nintrs = 0; 606 607 /* count the BSP */ 608 mp_ncpus = 1; 609 610 /* setup the cpu/apic mapping arrays */ 611 boot_cpu_id = -1; 612 613 /* local pointer */ 614 fps = (mpfps_t) mpfps; 615 616 /* record whether PIC or virtual-wire mode */ 617 picmode = (fps->mpfb2 & 0x80) ? 1 : 0; 618 619 /* check for use of 'default' configuration */ 620#if defined(TEST_DEFAULT_CONFIG) 621 /* use default addresses */ 622 cpu_apic_address = DEFAULT_APIC_BASE; 623 io_apic_address[0] = DEFAULT_IO_APIC_BASE; 624 625 /* return default configuration type */ 626 return TEST_DEFAULT_CONFIG; 627#else 628 if (fps->mpfb1 != 0) { 629 /* use default addresses */ 630 cpu_apic_address = DEFAULT_APIC_BASE; 631 io_apic_address[0] = DEFAULT_IO_APIC_BASE; 632 633 /* return default configuration type */ 634 return fps->mpfb1; 635 } 636#endif /* TEST_DEFAULT_CONFIG */ 637 638 if ((cth = fps->pap) == 0) 639 panic("MP Configuration Table Header MISSING!\n"); 640 641 cpu_apic_address = (vm_offset_t) cth->apic_address; 642 643 totalSize = cth->base_table_length - sizeof(struct MPCTH); 644 position = (u_char *) cth + sizeof(struct MPCTH); 645 count = cth->entry_count; 646 647 apic = 0; /* logical apic# start @ 0 */ 648 bus = 0; /* logical bus# start @ 0 */ 649 cpu = 1; /* logical cpu# start @ 0, BUT reserve 0 for */ 650 /* BSP */ 651 intr = 0; /* unknown */ 652 653 /* walk the table, recording info of interest */ 654 while (count--) { 655 switch (type = *(u_char *) position) { 656 case 0: 657 processor_entry(position, &cpu); 658 break; 659 case 1: 660 bus_entry(position, &bus); 661 break; 662 case 2: 663 io_apic_entry(position, &apic); 664 break; 665 case 3: 666 int_entry(position, &intr); 667 break; 668 case 4: 669 /* int_entry(position); */ 670 break; 671 default: 672 panic("mpfps Base Table HOSED!\n"); 673 /* NOTREACHED */ 674 } 675 676 totalSize -= basetable_entry_types[type].length; 677 (u_char *) position += basetable_entry_types[type].length; 678 } 679 680 if (boot_cpu_id == -1) 681 panic("NO BSP found!\n"); 682 683 /* record # of APs found */ 684 mp_naps = (cpu - 1); 685 686 /* record # of busses found */ 687 mp_nbusses = bus; 688 689 /* record # of IO APICs found */ 690 mp_napics = apic; 691 692 /* record # of IO APICs found */ 693 nintrs = intr; 694 695#if defined(FIX_MP_TABLE_WORKS) 696 /* post scan cleanup */ 697 fix_mp_table(); 698#endif /* FIX_MP_TABLE_WORKS */ 699 700 /* report fact that its NOT a default configuration */ 701 return 0; 702} 703 704 705/* 706 * parse an Intel MP specification table 707 */ 708#if defined(FIX_MP_TABLE_WORKS) 709static void 710fix_mp_table(void) 711{ 712 int x; 713 int y; 714 int num_pci_bus; 715 bus_datum bus_record; 716 717 /* 718 * Fix mis-numbering of the PCI bus and its INT entries if the BIOS 719 * did it wrong. The MP spec says that when more than 1 PCI bus 720 * exists the BIOS must begin with bus entries for the PCI bus and use 721 * actual PCI bus numbering. This implies that when only 1 PCI bus 722 * exists the BIOS can choose to ignore this ordering, and indeed many 723 * MP motherboards do ignore it. This causes a problem when the PCI 724 * sub-system makes requests of the MP sub-system based on PCI bus 725 * numbers. So here we look for the situation and renumber the 726 * busses and associated INTs in an effort to "make it right". 727 */ 728 729 /* count the number of PCI busses */ 730 for (num_pci_bus = 0, x = 0; x < mp_nbusses; ++x) { 731 if (bus_data[x].bus_type == PCI) 732 ++num_pci_bus; 733 } 734 735 /* check the 1 PCI bus case for sanity */ 736 if (num_pci_bus == 1) { 737 738 /* if its in the first slot all is well */ 739 if (bus_data[0].bus_type == PCI) 740 return; 741 742 /* mis-numbered, swap with whichever bus uses slot 0 */ 743 744 /* locate the entry holding the PCI bus */ 745 for (x = 1; x < mp_nbusses; ++x) { 746 if (bus_data[x].bus_type == PCI) 747 break; 748 } 749 750 /* swap the bus entry records */ 751 bus_record = bus_data[0]; 752 bus_data[0] = bus_data[x]; 753 bus_data[x] = bus_record; 754 755 /* swap each relavant INTerrupt entry */ 756 for (y = 0; y < nintrs; ++y) { 757 if (io_apic_ints[y].src_bus_id == x) 758 io_apic_ints[y].src_bus_id = 0; 759 else 760 if (io_apic_ints[y].src_bus_id == 0) 761 io_apic_ints[y].src_bus_id = x; 762 } 763 } 764 /* sanity check if more than 1 PCI bus */ 765 else 766 if (num_pci_bus > 1) { 767 for (x = 0; x < num_pci_bus; ++x) { 768 if (bus_data[x].bus_type != PCI) { 769 printf("bad PCI bus numbering\n"); 770 panic("\n"); 771 } 772 } 773 } 774} 775#endif /* FIX_MP_TABLE_WORKS */ 776 777 778static void 779processor_entry(proc_entry_ptr entry, int *cpu) 780{ 781 int x = *cpu; 782 783 /* check for usability */ 784 if (!(entry->cpu_flags & PROCENTRY_FLAG_EN)) 785 return; 786 787 /* check for BSP flag */ 788 if (entry->cpu_flags & PROCENTRY_FLAG_BP) { 789 /* always give boot CPU the logical value of 0 */ 790 x = 0; 791 boot_cpu_id = entry->apic_id; 792 } else { 793 /* add another AP to list, if less than max number of CPUs */ 794 if (x == NCPU) { 795 printf("Warning: only using %d of the available CPUs!\n", x); 796 return; 797 } 798 ++(*cpu); 799 } 800 801 CPU_TO_ID(x) = entry->apic_id; 802 ID_TO_CPU(entry->apic_id) = x; 803} 804 805 806static void 807bus_entry(bus_entry_ptr entry, int *bus) 808{ 809 int x, y; 810 char name[8]; 811 char c; 812 813 if ((x = (*bus)++) == NBUS) 814 panic("too many busses, increase 'NBUS'\n"); 815 816 /* encode the name into an index */ 817 for (y = 0; y < 6; ++y) { 818 if ((c = entry->bus_type[y]) == ' ') 819 break; 820 name[y] = c; 821 } 822 name[y] = '\0'; 823 824 if ((y = lookup_bus_type(name)) == UNKNOWN_BUSTYPE) 825 panic("unknown bus type: '%s'\n", name); 826 827 bus_data[x].bus_id = entry->bus_id; 828 bus_data[x].bus_type = y; 829} 830 831 832static void 833io_apic_entry(io_apic_entry_ptr entry, int *apic) 834{ 835 int x; 836 837 if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN)) 838 return; 839 840 if ((x = (*apic)++) == NAPIC) 841 panic("too many APICs, increase 'NAPIC'\n"); 842 843 IO_TO_ID(x) = entry->apic_id; 844 ID_TO_IO(entry->apic_id) = x; 845 846 io_apic_address[x] = (vm_offset_t) entry->apic_address; 847} 848 849 850static int 851lookup_bus_type(char *name) 852{ 853 int x; 854 855 for (x = 0; x < MAX_BUSTYPE; ++x) 856 if (strcmp(bus_type_table[x].name, name) == 0) 857 return bus_type_table[x].type; 858 859 return UNKNOWN_BUSTYPE; 860} 861 862 863static void 864int_entry(int_entry_ptr entry, int *intr) 865{ 866 int x; 867 868 if ((x = (*intr)++) == NINTR) 869 panic("too many INTs, increase 'NINTR'\n"); 870 871 io_apic_ints[x].int_type = entry->int_type; 872 io_apic_ints[x].int_flags = entry->int_flags; 873 io_apic_ints[x].src_bus_id = entry->src_bus_id; 874 io_apic_ints[x].src_bus_irq = entry->src_bus_irq; 875 io_apic_ints[x].dst_apic_id = entry->dst_apic_id; 876 io_apic_ints[x].dst_apic_int = entry->dst_apic_int; 877} 878 879 880static int 881apic_int_is_bus_type(int intr, int bus_type) 882{ 883 int bus; 884 885 for (bus = 0; bus < mp_nbusses; ++bus) 886 if ((bus_data[bus].bus_id == io_apic_ints[intr].src_bus_id) 887 && ((int) bus_data[bus].bus_type == bus_type)) 888 return 1; 889 890 return 0; 891} 892 893 894/* 895 * determine which APIC pin an ISA INT is attached to. 896 */ 897#define INTTYPE(I) (io_apic_ints[(I)].int_type) 898#define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) 899 900#define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) 901int 902get_isa_apic_irq(int isaIRQ) 903{ 904 int intr; 905 906#if defined(SMP_TIMER_NC) 907 if (isaIRQ == 0) 908 return -1; 909#endif /* SMP_TIMER_NC */ 910 911 for (intr = 0; intr < nintrs; ++intr) /* search each INT record */ 912 if ((INTTYPE(intr) == 0) 913 && (SRCBUSIRQ(intr) == isaIRQ)) /* a candidate IRQ */ 914 if (apic_int_is_bus_type(intr, ISA)) /* check bus match */ 915 return INTPIN(intr); /* exact match */ 916 917 return -1; /* NOT found */ 918} 919#undef SRCBUSIRQ 920 921 922/* 923 * determine which APIC pin an EISA INT is attached to. 924 */ 925#define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) 926int 927get_eisa_apic_irq(int eisaIRQ) 928{ 929 int intr; 930 931#if defined(SMP_TIMER_NC) 932 if (eisaIRQ == 0) 933 return -1; 934#endif /* SMP_TIMER_NC */ 935 936 for (intr = 0; intr < nintrs; ++intr) /* search each INT record */ 937 if ((INTTYPE(intr) == 0) 938 && (SRCBUSIRQ(intr) == eisaIRQ)) /* a candidate IRQ */ 939 if (apic_int_is_bus_type(intr, EISA)) /* check bus match */ 940 return INTPIN(intr); /* exact match */ 941 942 return -1; /* NOT found */ 943} 944#undef SRCBUSIRQ 945 946 947/* 948 * determine which APIC pin a PCI INT is attached to. 949 */ 950#define SRCBUSID(I) (io_apic_ints[(I)].src_bus_id) 951#define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) 952#define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) 953int 954get_pci_apic_irq(int pciBus, int pciDevice, int pciInt) 955{ 956 int intr; 957 958 --pciInt; /* zero based */ 959 960 for (intr = 0; intr < nintrs; ++intr) /* search each record */ 961 if ((INTTYPE(intr) == 0) 962#if defined(FIX_MP_TABLE_WORKS) 963 && (SRCBUSID(intr) == pciBus) 964#endif /* FIX_MP_TABLE_WORKS */ 965 && (SRCBUSDEVICE(intr) == pciDevice) 966 && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ 967 if (apic_int_is_bus_type(intr, PCI)) /* check bus match */ 968 return INTPIN(intr); /* exact match */ 969 970 return -1; /* NOT found */ 971} 972#undef SRCBUSLINE 973#undef SRCBUSDEVICE 974#undef SRCBUSID 975 976#undef INTPIN 977#undef INTTYPE 978 979 980int 981undirect_pci_irq(int rirq) 982{ 983#if defined(READY) 984 printf("Freeing irq %d for ISA cards.\n", rirq); 985 /** FIXME: tickle the MB redirector chip */ 986 return ???; 987#else 988 printf("Freeing (NOT implimented) irq %d for ISA cards.\n", rirq); 989 return 0; 990#endif /* READY */ 991} 992 993 994/* 995 * given a bus ID, return: 996 * the bus type if found 997 * -1 if NOT found 998 */ 999int 1000apic_bus_type(int id) 1001{ 1002 int x; 1003 1004 for (x = 0; x < mp_nbusses; ++x) 1005 if (bus_data[x].bus_id == id) 1006 return bus_data[x].bus_type; 1007 1008 return -1; 1009} 1010 1011 1012/* 1013 * given a LOGICAL APIC# and pin#, return: 1014 * the associated src bus ID if found 1015 * -1 if NOT found 1016 */ 1017int 1018apic_src_bus_id(int apic, int pin) 1019{ 1020 int x; 1021 1022 /* search each of the possible INTerrupt sources */ 1023 for (x = 0; x < nintrs; ++x) 1024 if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && 1025 (pin == io_apic_ints[x].dst_apic_int)) 1026 return (io_apic_ints[x].src_bus_id); 1027 1028 return -1; /* NOT found */ 1029} 1030 1031 1032/* 1033 * given a LOGICAL APIC# and pin#, return: 1034 * the associated src bus IRQ if found 1035 * -1 if NOT found 1036 */ 1037int 1038apic_src_bus_irq(int apic, int pin) 1039{ 1040 int x; 1041 1042 for (x = 0; x < nintrs; x++) 1043 if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && 1044 (pin == io_apic_ints[x].dst_apic_int)) 1045 return (io_apic_ints[x].src_bus_irq); 1046 1047 return -1; /* NOT found */ 1048} 1049 1050 1051/* 1052 * given a LOGICAL APIC# and pin#, return: 1053 * the associated INTerrupt type if found 1054 * -1 if NOT found 1055 */ 1056int 1057apic_int_type(int apic, int pin) 1058{ 1059 int x; 1060 1061 /* search each of the possible INTerrupt sources */ 1062 for (x = 0; x < nintrs; ++x) 1063 if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && 1064 (pin == io_apic_ints[x].dst_apic_int)) 1065 return (io_apic_ints[x].int_type); 1066 1067 return -1; /* NOT found */ 1068} 1069 1070 1071/* 1072 * given a LOGICAL APIC# and pin#, return: 1073 * the associated trigger mode if found 1074 * -1 if NOT found 1075 */ 1076int 1077apic_trigger(int apic, int pin) 1078{ 1079 int x; 1080 1081 /* search each of the possible INTerrupt sources */ 1082 for (x = 0; x < nintrs; ++x) 1083 if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && 1084 (pin == io_apic_ints[x].dst_apic_int)) 1085 return ((io_apic_ints[x].int_flags >> 2) & 0x03); 1086 1087 return -1; /* NOT found */ 1088} 1089 1090 1091/* 1092 * given a LOGICAL APIC# and pin#, return: 1093 * the associated 'active' level if found 1094 * -1 if NOT found 1095 */ 1096int 1097apic_polarity(int apic, int pin) 1098{ 1099 int x; 1100 1101 /* search each of the possible INTerrupt sources */ 1102 for (x = 0; x < nintrs; ++x) 1103 if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && 1104 (pin == io_apic_ints[x].dst_apic_int)) 1105 return (io_apic_ints[x].int_flags & 0x03); 1106 1107 return -1; /* NOT found */ 1108} 1109 1110 1111/* 1112 * set data according to MP defaults 1113 * FIXME: probably not complete yet... 1114 */ 1115static void 1116default_mp_table(int type) 1117{ 1118 int ap_cpu_id; 1119#if defined(APIC_IO) 1120 u_int32_t ux; 1121 int io_apic_id; 1122 int pin; 1123#endif /* APIC_IO */ 1124 1125#if 0 1126 printf(" MP default config type: %d\n", type); 1127 switch (type) { 1128 case 1: 1129 printf(" bus: ISA, APIC: 82489DX\n"); 1130 break; 1131 case 2: 1132 printf(" bus: EISA, APIC: 82489DX\n"); 1133 break; 1134 case 3: 1135 printf(" bus: EISA, APIC: 82489DX\n"); 1136 break; 1137 case 4: 1138 printf(" bus: MCA, APIC: 82489DX\n"); 1139 break; 1140 case 5: 1141 printf(" bus: ISA+PCI, APIC: Integrated\n"); 1142 break; 1143 case 6: 1144 printf(" bus: EISA+PCI, APIC: Integrated\n"); 1145 break; 1146 case 7: 1147 printf(" bus: MCA+PCI, APIC: Integrated\n"); 1148 break; 1149 default: 1150 printf(" future type\n"); 1151 break; 1152 /* NOTREACHED */ 1153 } 1154#endif /* 0 */ 1155 1156 boot_cpu_id = (apic_base[APIC_ID] & APIC_ID_MASK) >> 24; 1157 ap_cpu_id = (boot_cpu_id == 0) ? 1 : 0; 1158 1159 /* BSP */ 1160 CPU_TO_ID(0) = boot_cpu_id; 1161 ID_TO_CPU(boot_cpu_id) = 0; 1162 1163 /* one and only AP */ 1164 CPU_TO_ID(1) = ap_cpu_id; 1165 ID_TO_CPU(ap_cpu_id) = 1; 1166 mp_naps = 1; 1167 1168 /* one and only IO APIC */ 1169#if defined(APIC_IO) 1170 io_apic_id = (io_apic_read(0, IOAPIC_ID) & APIC_ID_MASK) >> 24; 1171 1172 /* 1173 * sanity check, refer to MP spec section 3.6.6, last paragraph 1174 * necessary as some hardware isn't properly setting up the IO APIC 1175 */ 1176#if defined(REALLY_ANAL_IOAPICID_VALUE) 1177 if (io_apic_id != 2) { 1178#else 1179 if ((io_apic_id == 0) || (io_apic_id == 1) || (io_apic_id == 15)) { 1180#endif /* REALLY_ANAL_IOAPICID_VALUE */ 1181 ux = io_apic_read(0, IOAPIC_ID); /* get current contents */ 1182 ux &= ~APIC_ID_MASK; /* clear the ID field */ 1183 ux |= 0x02000000; /* set it to '2' */ 1184 io_apic_write(0, IOAPIC_ID, ux); /* write new value */ 1185 ux = io_apic_read(0, IOAPIC_ID); /* re-read && test */ 1186 if ((ux & APIC_ID_MASK) != 0x02000000) 1187 panic("Problem: can't control IO APIC ID, reg: 0x%08x\n", ux); 1188 io_apic_id = 2; 1189 } 1190 IO_TO_ID(0) = io_apic_id; 1191 ID_TO_IO(io_apic_id) = 0; 1192 mp_napics = 1; 1193#else 1194 mp_napics = 0; 1195#endif /* APIC_IO */ 1196 1197 /* fill out bus entries */ 1198 switch (type) { 1199 case 1: 1200 case 2: 1201 case 3: 1202 case 5: 1203 case 6: 1204 mp_nbusses = default_data[type - 1][0]; 1205 bus_data[0].bus_id = default_data[type - 1][1]; 1206 bus_data[0].bus_type = default_data[type - 1][2]; 1207 bus_data[1].bus_id = default_data[type - 1][3]; 1208 bus_data[1].bus_type = default_data[type - 1][4]; 1209 break; 1210 1211 /* case 4: case 7: MCA NOT supported */ 1212 default: /* illegal/reserved */ 1213 panic("BAD default MP config: %d\n", type); 1214 } 1215 1216#if defined(APIC_IO) 1217 /* general cases from MP v1.4, table 5-2 */ 1218 for (pin = 0; pin < 16; ++pin) { 1219 io_apic_ints[pin].int_type = 0; 1220 io_apic_ints[pin].int_flags = 0x05; /* edge-triggered/active-hi */ 1221 io_apic_ints[pin].src_bus_id = 0; 1222 io_apic_ints[pin].src_bus_irq = pin; /* IRQ2 is caught below */ 1223 io_apic_ints[pin].dst_apic_id = io_apic_id; 1224 io_apic_ints[pin].dst_apic_int = pin; /* 1-to-1 correspondence */ 1225 } 1226 1227 /* special cases from MP v1.4, table 5-2 */ 1228 if (type == 2) { 1229 io_apic_ints[2].int_type = 0xff; /* N/C */ 1230 io_apic_ints[13].int_type = 0xff; /* N/C */ 1231#if !defined(APIC_MIXED_MODE) 1232 /** FIXME: ??? */ 1233 panic("sorry, can't support type 2 default yet\n"); 1234#endif /* APIC_MIXED_MODE */ 1235 } else 1236 io_apic_ints[2].src_bus_irq = 0; /* ISA IRQ0 is on APIC INT 2 */ 1237 1238 if (type == 7) 1239 io_apic_ints[0].int_type = 0xff; /* N/C */ 1240 else 1241 io_apic_ints[0].int_type = 3; /* vectored 8259 */ 1242 1243 nintrs = 16; 1244#endif /* APIC_IO */ 1245} 1246 1247 1248static void install_ap_tramp(u_int boot_addr); 1249static int start_ap(int logicalCpu, u_int boot_addr); 1250 1251/* 1252 * start each AP in our list 1253 */ 1254static int 1255start_all_aps(u_int boot_addr) 1256{ 1257 int x; 1258 u_char mpbiosreason; 1259 u_long mpbioswarmvec; 1260 1261 /** 1262 * NOTE: this needs further thought: 1263 * where does it get released? 1264 * should it be set to empy? 1265 * 1266 * get the initial mp_lock with a count of 1 for the BSP 1267 */ 1268 mp_lock = (apic_base[APIC_ID] & APIC_ID_MASK) + 1; 1269 1270 /* initialize BSP's local APIC */ 1271 apic_initialize(1); 1272 1273 /* install the AP 1st level boot code */ 1274 install_ap_tramp(boot_addr); 1275 1276 /* save the current value of the warm-start vector */ 1277 mpbioswarmvec = *((u_long *) WARMBOOT_OFF); 1278 outb(CMOS_REG, BIOS_RESET); 1279 mpbiosreason = inb(CMOS_DATA); 1280 1281 /* start each AP */ 1282 for (x = 1; x <= mp_naps; ++x) { 1283 1284 /* setup a vector to our boot code */ 1285 *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET; 1286 *((volatile u_short *) WARMBOOT_SEG) = (boot_addr >> 4); 1287 outb(CMOS_REG, BIOS_RESET); 1288 outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */ 1289 1290 /* attempt to start the Application Processor */ 1291 CHECK_INIT(99); /* setup checkpoints */ 1292 if (!start_ap(x, boot_addr)) { 1293 printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x)); 1294 CHECK_PRINT("trace"); /* show checkpoints */ 1295 /* 1296 * better panic as the AP may be running loose 1297 * somewhere 1298 */ 1299 printf("panic y/n? [n] "); 1300 if (cngetc() != 'n') 1301 panic("bye-bye\n"); 1302 } 1303 CHECK_PRINT("trace"); /* show checkpoints */ 1304 1305 /* record its version info */ 1306 cpu_apic_versions[x] = cpu_apic_versions[0]; 1307 } 1308 1309 /* fill in our (BSP) APIC version */ 1310 cpu_apic_versions[0] = apic_base[APIC_VER]; 1311 1312 /* restore the warmstart vector */ 1313 *(u_long *) WARMBOOT_OFF = mpbioswarmvec; 1314 outb(CMOS_REG, BIOS_RESET); 1315 outb(CMOS_DATA, mpbiosreason); 1316 1317 /* number of APs actually started */ 1318 return mp_ncpus - 1; 1319} 1320 1321 1322/* 1323 * load the 1st level AP boot code into base memory. 1324 */ 1325 1326/* targets for relocation */ 1327extern void bigJump(void); 1328extern void bootCodeSeg(void); 1329extern void bootDataSeg(void); 1330extern void MPentry(void); 1331extern u_int MP_GDT; 1332extern u_int mp_gdtbase; 1333 1334static void 1335install_ap_tramp(u_int boot_addr) 1336{ 1337 int x; 1338 int size = *(int *) ((u_long) & bootMP_size); 1339 u_char *src = (u_char *) ((u_long) bootMP); 1340 u_char *dst = (u_char *) boot_addr + KERNBASE; 1341 u_int boot_base = (u_int) bootMP; 1342 u_int8_t *dst8; 1343 u_int16_t *dst16; 1344 u_int32_t *dst32; 1345 1346 for (x = 0; x < size; ++x) 1347 *dst++ = *src++; 1348 1349 /* 1350 * modify addresses in code we just moved to basemem. unfortunately we 1351 * need fairly detailed info about mpboot.s for this to work. changes 1352 * to mpboot.s might require changes here. 1353 */ 1354 1355 /* boot code is located in KERNEL space */ 1356 dst = (u_char *) boot_addr + KERNBASE; 1357 1358 /* modify the lgdt arg */ 1359 dst32 = (u_int32_t *) (dst + ((u_int) & mp_gdtbase - boot_base)); 1360 *dst32 = boot_addr + ((u_int) & MP_GDT - boot_base); 1361 1362 /* modify the ljmp target for MPentry() */ 1363 dst32 = (u_int32_t *) (dst + ((u_int) bigJump - boot_base) + 1); 1364 *dst32 = ((u_int) MPentry - KERNBASE); 1365 1366 /* modify the target for boot code segment */ 1367 dst16 = (u_int16_t *) (dst + ((u_int) bootCodeSeg - boot_base)); 1368 dst8 = (u_int8_t *) (dst16 + 1); 1369 *dst16 = (u_int) boot_addr & 0xffff; 1370 *dst8 = ((u_int) boot_addr >> 16) & 0xff; 1371 1372 /* modify the target for boot data segment */ 1373 dst16 = (u_int16_t *) (dst + ((u_int) bootDataSeg - boot_base)); 1374 dst8 = (u_int8_t *) (dst16 + 1); 1375 *dst16 = (u_int) boot_addr & 0xffff; 1376 *dst8 = ((u_int) boot_addr >> 16) & 0xff; 1377} 1378 1379 1380/* 1381 * this function starts the AP (application processor) identified 1382 * by the APIC ID 'physicalCpu'. It does quite a "song and dance" 1383 * to accomplish this. This is necessary because of the nuances 1384 * of the different hardware we might encounter. It ain't pretty, 1385 * but it seems to work. 1386 */ 1387static int 1388start_ap(int logical_cpu, u_int boot_addr) 1389{ 1390 int physical_cpu; 1391 int vector; 1392 int cpus; 1393 u_long icr_lo, icr_hi; 1394 1395 /* get the PHYSICAL APIC ID# */ 1396 physical_cpu = CPU_TO_ID(logical_cpu); 1397 1398 /* calculate the vector */ 1399 vector = (boot_addr >> 12) & 0xff; 1400 1401 /* used as a watchpoint to signal AP startup */ 1402 cpus = mp_ncpus; 1403 1404 /* 1405 * first we do an INIT/RESET IPI this INIT IPI might be run, reseting 1406 * and running the target CPU. OR this INIT IPI might be latched (P5 1407 * bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be 1408 * ignored. 1409 */ 1410 1411 /* setup the address for the target AP */ 1412 icr_hi = apic_base[APIC_ICR_HI] & ~APIC_ID_MASK; 1413 icr_hi |= (physical_cpu << 24); 1414 apic_base[APIC_ICR_HI] = icr_hi; 1415 1416 /* do an INIT IPI: assert RESET */ 1417 icr_lo = apic_base[APIC_ICR_LOW] & 0xfff00000; 1418 apic_base[APIC_ICR_LOW] = icr_lo | 0x0000c500; 1419 1420 /* wait for pending status end */ 1421 while (apic_base[APIC_ICR_LOW] & APIC_DELSTAT_MASK) 1422 /* spin */ ; 1423 1424 /* do an INIT IPI: deassert RESET */ 1425 apic_base[APIC_ICR_LOW] = icr_lo | 0x00008500; 1426 1427 /* wait for pending status end */ 1428 u_sleep(10000); /* wait ~10mS */ 1429 while (apic_base[APIC_ICR_LOW] & APIC_DELSTAT_MASK) 1430 /* spin */ ; 1431 1432 /* 1433 * next we do a STARTUP IPI: the previous INIT IPI might still be 1434 * latched, (P5 bug) this 1st STARTUP would then terminate 1435 * immediately, and the previously started INIT IPI would continue. OR 1436 * the previous INIT IPI has already run. and this STARTUP IPI will 1437 * run. OR the previous INIT IPI was ignored. and this STARTUP IPI 1438 * will run. 1439 */ 1440 1441 /* do a STARTUP IPI */ 1442 apic_base[APIC_ICR_LOW] = icr_lo | 0x00000600 | vector; 1443 while (apic_base[APIC_ICR_LOW] & APIC_DELSTAT_MASK) 1444 /* spin */ ; 1445 u_sleep(200); /* wait ~200uS */ 1446 1447 /* 1448 * finally we do a 2nd STARTUP IPI: this 2nd STARTUP IPI should run IF 1449 * the previous STARTUP IPI was cancelled by a latched INIT IPI. OR 1450 * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is 1451 * recognized after hardware RESET or INIT IPI. 1452 */ 1453 1454 apic_base[APIC_ICR_LOW] = icr_lo | 0x00000600 | vector; 1455 while (apic_base[APIC_ICR_LOW] & APIC_DELSTAT_MASK) 1456 /* spin */ ; 1457 u_sleep(200); /* wait ~200uS */ 1458 1459 /* wait for it to start */ 1460 set_apic_timer(5000000);/* == 5 seconds */ 1461 while (read_apic_timer()) 1462 if (mp_ncpus > cpus) 1463 return 1; /* return SUCCESS */ 1464 1465 return 0; /* return FAILURE */ 1466} 1467 1468 1469#ifdef SMP_INVLTLB 1470/* 1471 * Flush the TLB on all other CPU's 1472 * 1473 * XXX: Needs to handshake and wait for completion before proceding. 1474 */ 1475 1476void 1477smp_invltlb() 1478{ 1479 if (smp_active) { 1480 if (invldebug & 2) 1481 all_but_self_ipi(ICU_OFFSET + 32); 1482 } 1483} 1484 1485void 1486invlpg(u_int addr) 1487{ 1488 __asm __volatile("invlpg (%0)"::"r"(addr):"memory"); 1489 smp_invltlb(); 1490} 1491 1492void 1493invltlb(void) 1494{ 1495 u_long temp; 1496 /* 1497 * This should be implemented as load_cr3(rcr3()) when load_cr3() is 1498 * inlined. 1499 */ 1500 __asm __volatile("movl %%cr3, %0; movl %0, %%cr3":"=r"(temp) :: "memory"); 1501 smp_invltlb(); 1502} 1503/* 1504 * Handles recieving an "IRQ 27", the invalidate tlb IPI.. 1505 */ 1506void 1507ipi_invltlb(void) 1508{ 1509 u_long temp; 1510 1511 if (invldebug & 4) { 1512 /* 1513 * This should be implemented as load_cr3(rcr3()) when 1514 * load_cr3() is inlined. 1515 */ 1516 __asm __volatile("movl %%cr3, %0; movl %0, %%cr3":"=r"(temp) 1517 :: "memory"); 1518 1519 } 1520} 1521#endif /* SMP_INVLTLB */ 1522