|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1992, 1993, 1994 NeXT Computer, Inc. ! 27: * ! 28: * Early machine initialization. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 20 May 1992 ? at NeXT ! 33: * Created. ! 34: */ ! 35: ! 36: #import <mach/mach_types.h> ! 37: ! 38: #import <kern/mach_header.h> ! 39: ! 40: #import <vm/vm_page.h> ! 41: ! 42: #import <machdep/i386/cpu_inline.h> ! 43: ! 44: #import <machdep/i386/pmap.h> ! 45: #import <machdep/i386/gdt.h> ! 46: #import <machdep/i386/idt.h> ! 47: #import <machdep/i386/configure.h> ! 48: #import <machdep/i386/kernBootStruct.h> ! 49: #include <sys/reboot.h> ! 50: #include <sys/errno.h> ! 51: #import "uxpr.h" ! 52: #import "xpr_debug.h" ! 53: ! 54: extern char rootdevice[]; ! 55: extern int nbuf; ! 56: extern int srv; ! 57: extern int ncl; ! 58: static unsigned int maxmem; ! 59: static int subtype = 0; ! 60: ! 61: struct kernargs { ! 62: char *name; ! 63: int *i_ptr; ! 64: } kernargs[] = { ! 65: "nbuf", &nbuf, ! 66: "rootdev", (int*) rootdevice, ! 67: "maxmem", &maxmem, ! 68: "subtype", &subtype, ! 69: "srv", &srv, ! 70: "ncl", &ncl, ! 71: 0,0, ! 72: }; ! 73: ! 74: #define NBOOTFILE 64 ! 75: char boot_file[NBOOTFILE + 1]; ! 76: ! 77: int master_cpu; ! 78: cpu_conf_t cpu_config; ! 79: ! 80: static vm_offset_t first_addr, last_addr; ! 81: static vm_offset_t first_addr0, last_addr0; ! 82: ! 83: vm_offset_t virtual_avail, virtual_end; ! 84: ! 85: struct mem_region mem_region[2]; ! 86: int num_regions; ! 87: ! 88: vm_size_t mem_size; ! 89: ! 90: /* parameters passed from bootstrap loader */ ! 91: int cnvmem = 0; /* must be in .data section */ ! 92: int extmem = 0; ! 93: ! 94: #import <sys/msgbuf.h> ! 95: ! 96: static void zero_fill_data(void), size_memory(void), ! 97: machine_configure(void), idt_page_protect(void); ! 98: ! 99: vm_offset_t alloc_cnvmem( ! 100: vm_size_t size, ! 101: vm_offset_t align); ! 102: ! 103: thread_saved_state_t *___xxx_state; /* Just a placeholder */ ! 104: ! 105: /* ! 106: * Called from Protected mode, ! 107: * flat 3G segmentation, paging disabled, ! 108: * interrupts disabled. ! 109: */ ! 110: i386_init(void) ! 111: { ! 112: register mem_region_t rp; ! 113: KERNBOOTSTRUCT *kernBootStruct = KERNSTRUCT_ADDR; ! 114: ! 115: cnvmem = kernBootStruct->convmem; ! 116: extmem = kernBootStruct->extmem; ! 117: ! 118: // Clear "zero fill" data sections. ! 119: ! 120: zero_fill_data(); ! 121: ! 122: getargs(kernBootStruct->bootString); ! 123: ! 124: // Figure out what kind of cpu is present ! 125: ! 126: machine_configure(); ! 127: ! 128: // Initialize the interrupt system. ! 129: ! 130: intr_initialize(); ! 131: ! 132: // Calibrate the constant for us_spin(). ! 133: ! 134: us_spin_calibrate(); ! 135: ! 136: // Set the MI system page size ! 137: ! 138: page_size = 2*I386_PGBYTES; ! 139: vm_set_page_size(); ! 140: ! 141: // Enable DDM tracing ! 142: #if UXPR && XPR_DEBUG ! 143: IOInitDDM(512); ! 144: #endif UXPR && XPR_DEBUG ! 145: ! 146: // Figure out how much extended memory the system contains. ! 147: ! 148: size_memory(); ! 149: ! 150: // Configure memory regions. ! 151: ! 152: num_regions = 1; ! 153: ! 154: rp = (mem_region_t) &mem_region[0]; ! 155: rp->base_phys_addr = ! 156: rp->first_phys_addr = first_addr; ! 157: rp->last_phys_addr = last_addr; ! 158: ! 159: /* ! 160: * Place the idt on its own page to ! 161: * enable working around the 'f00f' bug. ! 162: */ ! 163: idt_copy(alloc_cnvmem(I386_PGBYTES, I386_PGBYTES), I386_PGBYTES); ! 164: ! 165: // Initialize kernel physical map. ! 166: ! 167: pmap_bootstrap(mem_region, num_regions, &virtual_avail, &virtual_end); ! 168: ! 169: // ! 170: // Relocate the GDT & IDT ! 171: // to reside in the kernel ! 172: // address space. ! 173: ! 174: locate_gdt((vm_offset_t) gdt + KERNEL_LINEAR_BASE); ! 175: locate_idt((vm_offset_t) idt + KERNEL_LINEAR_BASE); ! 176: ! 177: // ! 178: // Set up the handler ! 179: // for double bus faults ! 180: ! 181: dbf_init(); ! 182: ! 183: /* ! 184: * Write protect the page containing ! 185: * the IDT as part of the 'f00f' ! 186: * hack/workaround. ! 187: */ ! 188: idt_page_protect(); ! 189: ! 190: // Specify address of console message buffer. ! 191: ! 192: mem_region[0].last_phys_addr -= round_page(sizeof (struct msgbuf)); ! 193: msgbufp = ! 194: (struct msgbuf *)pmap_phys_to_kern(mem_region[0].last_phys_addr); ! 195: } ! 196: ! 197: static void ! 198: idt_page_protect(void) ! 199: { ! 200: pt_entry_t *pte = pmap_pt_entry(kernel_pmap, (vm_offset_t) idt); ! 201: ! 202: pte->prot = PT_PROT_KR; ! 203: flush_cache(); flush_tlb(); ! 204: } ! 205: ! 206: static ! 207: void ! 208: zero_fill_data(void) ! 209: { ! 210: struct segment_command *sgp; ! 211: struct section *sp; ! 212: ! 213: sgp = getsegbyname("__DATA"); ! 214: if (!sgp) ! 215: return; ! 216: ! 217: sp = firstsect(sgp); ! 218: if (!sp) ! 219: return; ! 220: ! 221: do { ! 222: if (sp->flags & S_ZEROFILL) ! 223: bzero(sp->addr, sp->size); ! 224: } while (sp = nextsect(sgp, sp)); ! 225: } ! 226: ! 227: static inline ! 228: boolean_t ! 229: is486_or_higher(void) ! 230: { ! 231: unsigned int efl; ! 232: ! 233: efl = eflags(); ! 234: ! 235: efl |= EFL_AC; ! 236: set_eflags(efl); ! 237: ! 238: if ((efl & EFL_AC) == 0) ! 239: return (FALSE); ! 240: ! 241: efl &= ~EFL_AC; ! 242: set_eflags(efl); ! 243: ! 244: return (TRUE); ! 245: } ! 246: ! 247: /* ! 248: * This stuff belongs elsewhere ! 249: * (.h files), but I can't put ! 250: * it there due to the confidentiality ! 251: * of P5 information. ! 252: * - 17 September 92 ! 253: */ ! 254: typedef struct _cpuid { ! 255: unsigned int step :4, ! 256: model :4, ! 257: family :4, ! 258: type :2, ! 259: :18; ! 260: } cpuid_t; ! 261: ! 262: static ! 263: cpuid_t ! 264: cpuid(void) ! 265: { ! 266: cpuid_t value; ! 267: ! 268: asm volatile( ! 269: "movl $1,%%eax; cpuid" ! 270: : "=a" (value) ! 271: : ! 272: : "ebx", "ecx", "edx"); ! 273: ! 274: return (value); ! 275: } ! 276: ! 277: #define EFL_ID 0x200000 /* P5 specific */ ! 278: ! 279: static ! 280: cpuid_t ! 281: get_cpuid(void) ! 282: { ! 283: unsigned int efl; ! 284: cpuid_t pid = { 0 }; ! 285: ! 286: if (subtype != 0) { ! 287: /* ! 288: * This is a hack, intended only ! 289: * for testing purposes. ! 290: */ ! 291: pid.family = CPU_SUBTYPE_INTEL_FAMILY(subtype); ! 292: pid.model = CPU_SUBTYPE_INTEL_MODEL(subtype); ! 293: ! 294: return pid; ! 295: } ! 296: ! 297: efl = eflags(); ! 298: ! 299: efl |= EFL_ID; ! 300: set_eflags(efl); ! 301: ! 302: efl = eflags(); ! 303: ! 304: if ((efl & EFL_ID) == 0) ! 305: return pid; ! 306: ! 307: pid = cpuid(); ! 308: ! 309: efl &= ~EFL_ID; ! 310: set_eflags(efl); ! 311: ! 312: return pid; ! 313: } ! 314: ! 315: char cpu_model[65]; ! 316: char machine[65]; ! 317: ! 318: static ! 319: void ! 320: machine_configure(void) ! 321: { ! 322: cpuid_t pid; ! 323: ! 324: while (!is486_or_higher()) ! 325: asm volatile("hlt"); ! 326: ! 327: enable_cache(); ! 328: ! 329: fp_configure(); ! 330: ! 331: machine_slot[0].is_cpu = TRUE; ! 332: machine_slot[0].running = TRUE; ! 333: ! 334: machine_slot[0].cpu_type = CPU_TYPE_I386; ! 335: (void) strcpy(machine, "i386"); ! 336: ! 337: pid = get_cpuid(); ! 338: switch (pid.family) { ! 339: ! 340: case 0: ! 341: if (cpu_config.fpu_type == FPU_HDW) { ! 342: machine_slot[0].cpu_subtype = CPU_SUBTYPE_486; ! 343: (void) strcpy(cpu_model, "486"); ! 344: } ! 345: else { ! 346: machine_slot[0].cpu_subtype = CPU_SUBTYPE_486SX; ! 347: (void) strcpy(cpu_model, "486SX"); ! 348: } ! 349: break; ! 350: ! 351: case 5: ! 352: machine_slot[0].cpu_subtype = CPU_SUBTYPE_586; ! 353: (void) strcpy(cpu_model, "586"); ! 354: break; ! 355: ! 356: default: ! 357: machine_slot[0].cpu_subtype = CPU_SUBTYPE_INTEL(pid.family, pid.model); ! 358: (void) sprintf(cpu_model, "i86 family %d, model %d", ! 359: pid.family, pid.model); ! 360: break; ! 361: } ! 362: } ! 363: ! 364: static ! 365: void ! 366: size_memory(void) ! 367: { ! 368: KERNBOOTSTRUCT *kernBootStruct = (KERNBOOTSTRUCT *)KERNSTRUCT_ADDR; ! 369: vm_offset_t end_of_image, end_of_memory; ! 370: int i; ! 371: #define KB(x) ((x)*1024) ! 372: ! 373: end_of_image = getlastaddr(); ! 374: ! 375: for (i=0; i < kernBootStruct->numBootDrivers; i++) ! 376: end_of_image += kernBootStruct->driverConfig[i].size; ! 377: ! 378: if (maxmem) ! 379: end_of_memory = KB(maxmem); ! 380: else ! 381: end_of_memory = KB(extmem); ! 382: ! 383: /* ! 384: * This is the Mach notion of ! 385: * how much physical memory the ! 386: * machine contains. This value ! 387: * is only used for informational ! 388: * purposes. ! 389: */ ! 390: ! 391: mem_size = end_of_memory; ! 392: ! 393: first_addr0 = round_page(kernBootStruct->first_addr0); ! 394: last_addr0 = trunc_page(KB(cnvmem)); ! 395: ! 396: first_addr = round_page(end_of_image); ! 397: last_addr = trunc_page(end_of_memory); ! 398: #undef KB ! 399: } ! 400: ! 401: vm_offset_t ! 402: bios_extdata_addr(void) ! 403: { ! 404: return (cnvmem * 1024); ! 405: } ! 406: ! 407: vm_offset_t ! 408: alloc_cnvmem( ! 409: vm_size_t size, ! 410: vm_offset_t align ! 411: ) ! 412: { ! 413: static vm_offset_t free_ptr, end_ptr; ! 414: vm_offset_t p; ! 415: ! 416: if (!free_ptr) { ! 417: free_ptr = pmap_phys_to_kern(first_addr0); ! 418: end_ptr = pmap_phys_to_kern(last_addr0); ! 419: } ! 420: ! 421: p = (free_ptr + (align - 1)) & ~(align - 1); ! 422: if ((p + size) > end_ptr) ! 423: return ((vm_offset_t) 0); ! 424: ! 425: free_ptr = (p + size); ! 426: ! 427: return (p); ! 428: } ! 429: ! 430: vm_offset_t ! 431: alloc_pages( ! 432: vm_size_t size ! 433: ) ! 434: { ! 435: vm_offset_t p; ! 436: ! 437: { /* XXX */ ! 438: extern boolean_t pmap_initialized; ! 439: ! 440: if (pmap_initialized) ! 441: panic("alloc_pages"); ! 442: ! 443: /* XXX */ ! 444: } ! 445: ! 446: size = round_page(size); ! 447: p = pmap_phys_to_kern(mem_region[0].first_phys_addr); ! 448: mem_region[0].first_phys_addr += size; ! 449: ! 450: return (p); ! 451: } ! 452: ! 453: #define NUM 0 ! 454: #define STR 1 ! 455: ! 456: getargs(char *args) ! 457: { ! 458: extern char init_args[]; ! 459: char *cp, c; ! 460: char *namep; ! 461: struct kernargs *kp; ! 462: extern int boothowto; ! 463: int i; ! 464: int val; ! 465: ! 466: KERNBOOTSTRUCT *kernBootStruct = (KERNBOOTSTRUCT *)KERNSTRUCT_ADDR; ! 467: strncpy(boot_file, kernBootStruct->boot_file, NBOOTFILE); ! 468: ! 469: if (*args == 0) return 1; ! 470: ! 471: while(isargsep(*args)) args++; ! 472: ! 473: while (*args) ! 474: { ! 475: if (*args == '-') ! 476: { ! 477: char *ia = init_args; ! 478: ! 479: argstrcpy(args, init_args); ! 480: do { ! 481: switch (*ia) { ! 482: case 'a': ! 483: boothowto |= RB_ASKNAME; ! 484: break; ! 485: case 's': ! 486: boothowto |= RB_SINGLE; ! 487: break; ! 488: case 'd': ! 489: boothowto |= RB_KDB; ! 490: break; ! 491: case 'f': ! 492: #define RB_NOFP 0x00200000 /* don't use floating point */ ! 493: boothowto |= RB_NOFP; ! 494: break; ! 495: } ! 496: } while (*ia && !isargsep(*ia++)); ! 497: } ! 498: else ! 499: { ! 500: cp = args; ! 501: while (!isargsep (*cp) && *cp != '=') ! 502: cp++; ! 503: if (*cp != '=') ! 504: goto gotit; ! 505: ! 506: c = *cp; ! 507: for(kp=kernargs;kp->name;kp++) { ! 508: i = cp-args; ! 509: if (strncmp(args, kp->name, i)) ! 510: continue; ! 511: while (isargsep (*cp)) ! 512: cp++; ! 513: if (*cp == '=' && c != '=') { ! 514: args = cp+1; ! 515: goto gotit; ! 516: } ! 517: ! 518: switch (getval(cp, &val)) ! 519: { ! 520: case NUM: ! 521: *kp->i_ptr = val; ! 522: break; ! 523: case STR: ! 524: argstrcpy(++cp, kp->i_ptr); ! 525: break; ! 526: } ! 527: goto gotit; ! 528: } ! 529: } ! 530: gotit: ! 531: /* Skip over current arg */ ! 532: while(!isargsep(*args)) args++; ! 533: ! 534: /* Skip leading white space (catch end of args) */ ! 535: while(*args && isargsep(*args)) args++; ! 536: } ! 537: ! 538: return 0; ! 539: } ! 540: ! 541: isargsep(c) ! 542: char c; ! 543: { ! 544: if (c == ' ' || c == '\0' || c == '\t' || c == ',') ! 545: return(1); ! 546: else ! 547: return(0); ! 548: } ! 549: ! 550: argstrcpy(from, to) ! 551: char *from, *to; ! 552: { ! 553: int i = 0; ! 554: ! 555: while (!isargsep(*from)) { ! 556: i++; ! 557: *to++ = *from++; ! 558: } ! 559: *to = 0; ! 560: return(i); ! 561: } ! 562: ! 563: getval(s, val) ! 564: register char *s; ! 565: int *val; ! 566: { ! 567: register unsigned radix, intval; ! 568: register unsigned char c; ! 569: int sign = 1; ! 570: ! 571: if (*s == '=') { ! 572: s++; ! 573: if (*s == '-') ! 574: sign = -1, s++; ! 575: intval = *s++-'0'; ! 576: radix = 10; ! 577: if (intval == 0) ! 578: switch(*s) { ! 579: ! 580: case 'x': ! 581: radix = 16; ! 582: s++; ! 583: break; ! 584: ! 585: case 'b': ! 586: radix = 2; ! 587: s++; ! 588: break; ! 589: ! 590: case '0': case '1': case '2': case '3': ! 591: case '4': case '5': case '6': case '7': ! 592: intval = *s-'0'; ! 593: s++; ! 594: radix = 8; ! 595: break; ! 596: ! 597: default: ! 598: if (!isargsep(*s)) ! 599: return (STR); ! 600: } ! 601: for(;;) { ! 602: if (((c = *s++) >= '0') && (c <= '9')) ! 603: c -= '0'; ! 604: else if ((c >= 'a') && (c <= 'f')) ! 605: c -= 'a' - 10; ! 606: else if ((c >= 'A') && (c <= 'F')) ! 607: c -= 'A' - 10; ! 608: else if (isargsep(c)) ! 609: break; ! 610: else ! 611: return (STR); ! 612: if (c >= radix) ! 613: return (STR); ! 614: intval *= radix; ! 615: intval += c; ! 616: } ! 617: *val = intval * sign; ! 618: return (NUM); ! 619: } ! 620: *val = 1; ! 621: return (NUM); ! 622: } ! 623: ! 624: /* i386 specific sysctl calls */ ! 625: int ! 626: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) ! 627: int *name; ! 628: u_int namelen; ! 629: void *oldp; ! 630: size_t *oldlenp; ! 631: void *newp; ! 632: size_t newlen; ! 633: struct proc *p; ! 634: { ! 635: /* ! 636: * nothing defined yet ! 637: */ ! 638: return (EOPNOTSUPP); ! 639: } ! 640:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.