|
|
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.