|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: ! 51: /* ! 52: */ ! 53: ! 54: /* ! 55: * File: model_dep.c ! 56: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 57: * ! 58: * Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young ! 59: * ! 60: * Basic initialization for I386 - ISA bus machines. ! 61: */ ! 62: ! 63: #include <cpus.h> ! 64: #include <platforms.h> ! 65: #include <mp_v1_1.h> ! 66: #include <mach_kdb.h> ! 67: #include <himem.h> ! 68: #include <fast_idle.h> ! 69: ! 70: #include <mach/i386/vm_param.h> ! 71: ! 72: #include <string.h> ! 73: #include <mach/vm_param.h> ! 74: #include <mach/vm_prot.h> ! 75: #include <mach/machine.h> ! 76: #include <mach/time_value.h> ! 77: #include <kern/etap_macros.h> ! 78: #include <kern/spl.h> ! 79: #include <kern/assert.h> ! 80: #include <kern/debug.h> ! 81: #include <kern/misc_protos.h> ! 82: #include <kern/startup.h> ! 83: #include <kern/clock.h> ! 84: #include <kern/time_out.h> ! 85: #include <kern/xpr.h> ! 86: #include <kern/cpu_data.h> ! 87: #include <vm/vm_page.h> ! 88: #include <vm/pmap.h> ! 89: #include <vm/vm_kern.h> ! 90: #include <i386/fpu.h> ! 91: #include <i386/pmap.h> ! 92: #include <i386/ipl.h> ! 93: #include <i386/pio.h> ! 94: #include <i386/misc_protos.h> ! 95: #include <i386/cpuid.h> ! 96: #include <i386/rtclock_entries.h> ! 97: #include <i386/AT386/mp/mp.h> ! 98: #if MACH_KDB ! 99: #include <ddb/db_aout.h> ! 100: #endif /* MACH_KDB */ ! 101: #include <ddb/tr.h> ! 102: #ifdef __MACHO__ ! 103: #include <i386/AT386/kernBootStruct.h> ! 104: #include <mach/boot_info.h> ! 105: #include <mach/thread_status.h> ! 106: #endif ! 107: ! 108: #if NCPUS > 1 ! 109: #include <i386/mp_desc.h> ! 110: #endif /* NCPUS */ ! 111: ! 112: #if MP_V1_1 ! 113: #include <i386/AT386/mp/mp_v1_1.h> ! 114: #endif /* MP_V1_1 */ ! 115: ! 116: vm_size_t mem_size = 0; ! 117: vm_offset_t first_addr = 0; /* set by start.s - keep out of bss */ ! 118: vm_offset_t first_avail = 0;/* first after page tables */ ! 119: vm_offset_t last_addr; ! 120: ! 121: vm_offset_t avail_start, avail_end; ! 122: vm_offset_t virtual_avail, virtual_end; ! 123: vm_offset_t hole_start, hole_end; ! 124: vm_offset_t avail_next; ! 125: unsigned int avail_remaining; ! 126: ! 127: /* parameters passed from bootstrap loader */ ! 128: int cnvmem = 0; /* must be in .data section */ ! 129: int extmem = 0; ! 130: ! 131: /* FIXME!! REMOVE WHEN OSFMK DEVICES ARE COMPLETELY PULLED OUT */ ! 132: int dev_name_count = 0; ! 133: int dev_name_list = 0; ! 134: ! 135: #ifndef __MACHO__ ! 136: extern char edata, end; ! 137: #endif ! 138: ! 139: extern char version[]; ! 140: ! 141: int rebootflag = 0; /* exported to kdintr */ ! 142: ! 143: ! 144: void parse_arguments(void); ! 145: const char *getenv(const char *); ! 146: ! 147: #define BOOT_LINE_LENGTH 160 ! 148: char boot_string_store[BOOT_LINE_LENGTH] = {0}; ! 149: char *boot_string = (char *)0; ! 150: int boot_string_sz = BOOT_LINE_LENGTH; ! 151: int boottype = 0; ! 152: ! 153: #if __MACHO__ ! 154: #include <mach-o/loader.h> ! 155: vm_offset_t edata, etext, end; ! 156: ! 157: extern struct mach_header _mh_execute_header; ! 158: void *sectTEXTB; int sectSizeTEXT; ! 159: void *sectDATAB; int sectSizeDATA; ! 160: void *sectOBJCB; int sectSizeOBJC; ! 161: void *sectLINKB; int sectSizeLINK; ! 162: ! 163: /* Kernel boot information */ ! 164: KERNBOOTSTRUCT kernBootStructData; ! 165: KERNBOOTSTRUCT *kernBootStruct; ! 166: #endif ! 167: ! 168: extern vm_offset_t kern_args_start; ! 169: extern vm_size_t kern_args_size; ! 170: ! 171: #ifdef __MACHO__ ! 172: ! 173: unsigned long ! 174: i386_preinit() ! 175: { ! 176: int i; ! 177: struct segment_command *sgp; ! 178: struct section *sp; ! 179: ! 180: sgp = (struct segment_command *) getsegbyname("__DATA"); ! 181: if (sgp) { ! 182: sp = (struct section *) firstsect(sgp); ! 183: if (sp) { ! 184: do { ! 185: if (sp->flags & S_ZEROFILL) ! 186: bzero((char *) sp->addr, sp->size); ! 187: } while (sp = (struct section *)nextsect(sgp, sp)); ! 188: } ! 189: } ! 190: ! 191: ! 192: bcopy((char *) KERNSTRUCT_ADDR, (char *) &kernBootStructData, ! 193: sizeof(kernBootStructData)); ! 194: ! 195: kernBootStruct = &kernBootStructData; ! 196: ! 197: end = getlastaddr(); ! 198: ! 199: for (i = 0; i < kernBootStruct->numBootDrivers; i++) ! 200: end += kernBootStruct->driverConfig[i].size; ! 201: ! 202: end = round_page(end); ! 203: ! 204: return end; ! 205: } ! 206: #endif ! 207: ! 208: /* ! 209: * Cpu initialization. Running virtual, but without MACH VM ! 210: * set up. First C routine called. ! 211: */ ! 212: void ! 213: machine_startup(void) ! 214: { ! 215: ! 216: #ifdef __MACHO__ ! 217: ! 218: ! 219: /* Now copy over various bits.. */ ! 220: cnvmem = kernBootStruct->convmem; ! 221: extmem = kernBootStruct->extmem; ! 222: kern_args_start = (vm_offset_t) kernBootStruct->bootString; ! 223: kern_args_size = strlen(kernBootStruct->bootString); ! 224: boottype = kernBootStruct->rootdev; ! 225: ! 226: /* Now retrieve addresses for end, edata, and etext ! 227: * from MACH-O headers. ! 228: */ ! 229: ! 230: sectTEXTB = (void *) getsegdatafromheader( ! 231: &_mh_execute_header, "__TEXT", §SizeTEXT); ! 232: sectDATAB = (void *) getsegdatafromheader( ! 233: &_mh_execute_header, "__DATA", §SizeDATA); ! 234: sectOBJCB = (void *) getsegdatafromheader( ! 235: &_mh_execute_header, "__OBJC", §SizeOBJC); ! 236: sectLINKB = (void *) getsegdatafromheader( ! 237: &_mh_execute_header, "__LINKEDIT", §SizeLINK); ! 238: ! 239: etext = (vm_offset_t) sectTEXTB + sectSizeTEXT; ! 240: edata = (vm_offset_t) sectDATAB + sectSizeDATA; ! 241: #endif ! 242: ! 243: /* ! 244: * Parse startup arguments ! 245: */ ! 246: parse_arguments(); ! 247: ! 248: disableDebugOuput = FALSE; ! 249: debug_mode = TRUE; ! 250: ! 251: PE_init_platform(FALSE, kernBootStruct); ! 252: PE_init_kprintf(FALSE); ! 253: PE_init_printf(FALSE); ! 254: ! 255: /* ! 256: * Do basic VM initialization ! 257: */ ! 258: i386_init(); ! 259: ! 260: PE_init_platform(TRUE, kernBootStruct); ! 261: PE_init_kprintf(TRUE); ! 262: PE_init_printf(TRUE); ! 263: ! 264: #if MACH_KDB ! 265: ! 266: /* ! 267: * Initialize the kernel debugger. ! 268: */ ! 269: ddb_init(); ! 270: ! 271: /* ! 272: * Cause a breakpoint trap to the debugger before proceeding ! 273: * any further if the proper option bit was specified in ! 274: * the boot flags. ! 275: * ! 276: * XXX use -a switch to invoke kdb, since there's no ! 277: * boot-program switch to turn on RB_HALT! ! 278: */ ! 279: ! 280: if (halt_in_debugger) { ! 281: printf("inline call to debugger(machine_startup)\n"); ! 282: Debugger("inline call"); ! 283: } ! 284: #endif /* MACH_KDB */ ! 285: TR_INIT(); ! 286: ! 287: printf(version); ! 288: ! 289: machine_slot[0].is_cpu = TRUE; ! 290: machine_slot[0].running = TRUE; ! 291: #ifdef MACH_BSD ! 292: /* FIXME */ ! 293: machine_slot[0].cpu_type = CPU_TYPE_I386; ! 294: machine_slot[0].cpu_subtype = CPU_SUBTYPE_PENTPRO; ! 295: #else ! 296: machine_slot[0].cpu_type = cpuid_cputype(0); ! 297: machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386; ! 298: #endif ! 299: ! 300: /* ! 301: * Start the system. ! 302: */ ! 303: #if NCPUS > 1 ! 304: mp_desc_init(0); ! 305: #endif /* NCPUS */ ! 306: ! 307: setup_main(); ! 308: } ! 309: ! 310: ! 311: extern vm_offset_t env_start; ! 312: extern vm_size_t env_size; ! 313: /* ! 314: * Parse command line arguments. ! 315: */ ! 316: void ! 317: parse_arguments(void) ! 318: { ! 319: char *p = (char *) kern_args_start; ! 320: char *endp = (char *) kern_args_start + kern_args_size - 1; ! 321: char ch; ! 322: ! 323: if (kern_args_start == 0) ! 324: return; ! 325: while (p < endp) { ! 326: if (*p++ != '-') { ! 327: while (*p++ != '\0') ! 328: ; ! 329: continue; ! 330: } ! 331: while (ch = *p++) { ! 332: switch (ch) { ! 333: case 'h': ! 334: halt_in_debugger = 1; ! 335: break; ! 336: case 'm': /* -m??: memory size Mbytes*/ ! 337: mem_size = atoi_term(p, &p)*1024*1024; ! 338: break; ! 339: case 'k': /* -k??: memory size Kbytes */ ! 340: mem_size = atoi_term(p, &p)*1024; ! 341: break; ! 342: default: ! 343: #if NCPUS > 1 && AT386 ! 344: if (ch > '0' && ch <= '9') ! 345: wncpu = ch - '0'; ! 346: #endif /* NCPUS > 1 && AT386 */ ! 347: break; ! 348: } ! 349: } ! 350: } ! 351: } ! 352: ! 353: const char * ! 354: getenv(const char *name) ! 355: { ! 356: int len = strlen(name); ! 357: const char *p = (const char *)env_start; ! 358: const char *endp = p + env_size; ! 359: ! 360: while (p < endp) { ! 361: if (len >= endp - p) ! 362: break; ! 363: if (strncmp(name, p, len) == 0 && *(p + len) == '=') ! 364: return p + len + 1; ! 365: while (*p++) ! 366: ; ! 367: } ! 368: return NULL; ! 369: } ! 370: ! 371: extern void ! 372: calibrate_delay(void); ! 373: ! 374: /* ! 375: * Find devices. The system is alive. ! 376: */ ! 377: void ! 378: machine_init(void) ! 379: { ! 380: int unit; ! 381: const char *p; ! 382: int n; ! 383: ! 384: /* ! 385: * Adjust delay count before entering drivers ! 386: */ ! 387: ! 388: calibrate_delay(); ! 389: ! 390: /* ! 391: * Display CPU identification ! 392: */ ! 393: cpuid_cpu_display("CPU identification", 0); ! 394: cpuid_cache_display("CPU configuration", 0); ! 395: ! 396: #if MP_V1_1 ! 397: mp_v1_1_init(); ! 398: #endif /* MP_V1_1 */ ! 399: ! 400: /* ! 401: * Set up to use floating point. ! 402: */ ! 403: init_fpu(); ! 404: ! 405: #if 0 ! 406: #if NPCI > 0 ! 407: dma_zones_init(); ! 408: #endif /* NPCI > 0 */ ! 409: #endif ! 410: ! 411: /* ! 412: * Configure clock devices. ! 413: */ ! 414: clock_config(); ! 415: } ! 416: ! 417: /* ! 418: * Halt a cpu. ! 419: */ ! 420: void ! 421: halt_cpu(void) ! 422: { ! 423: halt_all_cpus(FALSE); ! 424: } ! 425: ! 426: int reset_mem_on_reboot = 1; ! 427: ! 428: /* ! 429: * Halt the system or reboot. ! 430: */ ! 431: void ! 432: halt_all_cpus( ! 433: boolean_t reboot) ! 434: { ! 435: if (reboot) { ! 436: /* ! 437: * Tell the BIOS not to clear and test memory. ! 438: */ ! 439: if (! reset_mem_on_reboot) ! 440: *(unsigned short *)phystokv(0x472) = 0x1234; ! 441: ! 442: kdreboot(); ! 443: } ! 444: else { ! 445: rebootflag = 1; ! 446: printf("In tight loop: hit ctl-alt-del to reboot\n"); ! 447: (void) spllo(); ! 448: } ! 449: for (;;) ! 450: continue; ! 451: } ! 452: ! 453: ! 454: /* ! 455: * Basic VM initialization. ! 456: */ ! 457: ! 458: void ! 459: i386_init(void) ! 460: { ! 461: int i,j; /* Standard index vars. */ ! 462: vm_size_t bios_hole_size; ! 463: ! 464: #ifndef __MACHO__ ! 465: /* ! 466: * Zero the BSS. ! 467: */ ! 468: ! 469: bzero((char *)&edata,(unsigned)(&end - &edata)); ! 470: #endif ! 471: ! 472: boot_string = &boot_string_store[0]; ! 473: ! 474: /* ! 475: * Initialize the pic prior to any possible call to an spl. ! 476: */ ! 477: ! 478: set_cpu_model(); ! 479: vm_set_page_size(); ! 480: ! 481: /* ! 482: * Initialize the Event Trace Analysis Package ! 483: * Static Phase: 1 of 2 ! 484: */ ! 485: etap_init_phase1(); ! 486: ! 487: /* ! 488: * Compute the memory size. ! 489: */ ! 490: ! 491: #if 1 ! 492: /* FIXME ! 493: * fdisk needs to change to use a sysctl instead of ! 494: * opening /dev/kmem and reading out the kernboot structure ! 495: */ ! 496: ! 497: first_addr = 0x11000 + sizeof(KERNBOOTSTRUCT); ! 498: #else ! 499: #if NCPUS > 1 ! 500: first_addr = 0x1000; ! 501: #else ! 502: /* First two pages are used to boot the other cpus. */ ! 503: /* TODO - reclaim pages after all cpus have booted */ ! 504: ! 505: first_addr = 0x3000; ! 506: #endif ! 507: #endif ! 508: ! 509: /* BIOS leaves data in low memory */ ! 510: last_addr = 1024*1024 + extmem*1024; ! 511: /* extended memory starts at 1MB */ ! 512: ! 513: bios_hole_size = 1024*1024 - trunc_page((vm_offset_t)(1024 * cnvmem)); ! 514: ! 515: /* ! 516: * Initialize for pmap_free_pages and pmap_next_page. ! 517: * These guys should be page-aligned. ! 518: */ ! 519: ! 520: hole_start = trunc_page((vm_offset_t)(1024 * cnvmem)); ! 521: hole_end = round_page((vm_offset_t)first_avail); ! 522: ! 523: /* ! 524: * compute mem_size ! 525: */ ! 526: ! 527: if (mem_size != 0) { ! 528: if (mem_size < (last_addr) - bios_hole_size) ! 529: last_addr = mem_size + bios_hole_size; ! 530: } ! 531: ! 532: first_addr = round_page(first_addr); ! 533: last_addr = trunc_page(last_addr); ! 534: mem_size = last_addr - bios_hole_size; ! 535: ! 536: avail_start = first_addr; ! 537: avail_end = last_addr; ! 538: avail_next = avail_start; ! 539: ! 540: /* ! 541: * Initialize kernel physical map, mapping the ! 542: * region from loadpt to avail_start. ! 543: * Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS. ! 544: */ ! 545: ! 546: ! 547: #if NCPUS > 1 && AT386 ! 548: /* ! 549: * Must Allocate interrupt stacks before kdb is called and also ! 550: * before vm is initialized. Must find out number of cpus first. ! 551: */ ! 552: /* ! 553: * Get number of cpus to boot, passed as an optional argument ! 554: * boot: mach [-sah#] # from 0 to 9 is the number of cpus to boot ! 555: */ ! 556: if (wncpu == -1) { ! 557: /* ! 558: * "-1" check above is to allow for old boot loader to pass ! 559: * wncpu through boothowto. New boot loader uses environment. ! 560: */ ! 561: const char *cpus; ! 562: if ((cpus = getenv("cpus")) != NULL) { ! 563: /* only a single digit for now */ ! 564: if ((*cpus > '0') && (*cpus <= '9')) ! 565: wncpu = *cpus - '0'; ! 566: } else ! 567: wncpu = NCPUS; ! 568: } ! 569: mp_probe_cpus(); ! 570: interrupt_stack_alloc(); ! 571: ! 572: #endif /* NCPUS > 1 && AT386 */ ! 573: ! 574: pmap_bootstrap(0); ! 575: ! 576: avail_remaining = atop((avail_end - avail_start) - ! 577: (hole_end - hole_start)); ! 578: } ! 579: ! 580: unsigned int ! 581: pmap_free_pages(void) ! 582: { ! 583: return avail_remaining; ! 584: } ! 585: ! 586: boolean_t ! 587: pmap_next_page( ! 588: vm_offset_t *addrp) ! 589: { ! 590: if (avail_next == avail_end) ! 591: return FALSE; ! 592: ! 593: /* skip the hole */ ! 594: ! 595: if (avail_next == hole_start) ! 596: avail_next = hole_end; ! 597: ! 598: *addrp = avail_next; ! 599: avail_next += PAGE_SIZE; ! 600: avail_remaining--; ! 601: ! 602: return TRUE; ! 603: } ! 604: ! 605: boolean_t ! 606: pmap_valid_page( ! 607: vm_offset_t x) ! 608: { ! 609: return ((avail_start <= x) && (x < avail_end)); ! 610: } ! 611: ! 612: /*XXX*/ ! 613: void fc_get(mach_timespec_t *ts); ! 614: #include <kern/clock.h> ! 615: #include <i386/rtclock_entries.h> ! 616: extern kern_return_t sysclk_gettime( ! 617: mach_timespec_t *cur_time); ! 618: void fc_get(mach_timespec_t *ts) { ! 619: (void )sysclk_gettime(ts); ! 620: } ! 621: ! 622: void ! 623: Debugger( ! 624: const char *message) ! 625: { ! 626: printf("Debugger called: <%s>\n", message); ! 627: ! 628: __asm__("int3"); ! 629: } ! 630: ! 631: void ! 632: display_syscall(int syscall) ! 633: { ! 634: printf("System call happened %d\n", syscall); ! 635: } ! 636: ! 637: #if XPR_DEBUG && (NCPUS == 1 || MP_V1_1) ! 638: ! 639: extern kern_return_t sysclk_gettime_interrupts_disabled( ! 640: mach_timespec_t *cur_time); ! 641: ! 642: int xpr_time(void) ! 643: { ! 644: mach_timespec_t time; ! 645: ! 646: sysclk_gettime_interrupts_disabled(&time); ! 647: return(time.tv_sec*1000000 + time.tv_nsec/1000); ! 648: } ! 649: #endif /* XPR_DEBUG && (NCPUS == 1 || MP_V1_1) */ ! 650: ! 651: enable_bluebox() ! 652: { ! 653: } ! 654: disable_bluebox() ! 655: { ! 656: } ! 657: ! 658: char * ! 659: machine_boot_info(char *buf, vm_size_t size) ! 660: { ! 661: *buf ='\0'; ! 662: return buf; ! 663: } ! 664:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.