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