|
|
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) 1982, 1986, 1989, 1991, 1992, 1993
27: * The Regents of the University of California. All rights reserved.
28: * (c) UNIX System Laboratories, Inc.
29: * All or some portions of this file are derived from material licensed
30: * to the University of California by American Telephone and Telegraph
31: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
32: * the permission of UNIX System Laboratories, Inc.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: * 3. All advertising materials mentioning features or use of this software
43: * must display the following acknowledgement:
44: * This product includes software developed by the University of
45: * California, Berkeley and its contributors.
46: * 4. Neither the name of the University nor the names of its contributors
47: * may be used to endorse or promote products derived from this software
48: * without specific prior written permission.
49: *
50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60: * SUCH DAMAGE.
61: *
62: * @(#)init_main.c 8.16 (Berkeley) 5/14/95
63: */
64:
65: /*
66: *
67: * Mach Operating System
68: * Copyright (c) 1987 Carnegie-Mellon University
69: * All rights reserved. The CMU software License Agreement specifies
70: * the terms and conditions for use and redistribution.
71: */
72: /*
73: * HISTORY
74: * 02-Jul-97 Umesh Vaishampayan at Apple
75: * Cleanup.
76: *
77: * 06-Jan-93 Mac Gillon at NeXT
78: * POSIX support
79: *
80: * 20-Apr-90 Doug Mitchell at NeXT
81: * Started up reaper_thread() before mounting root.
82: *
83: * 19-Mar-90 Gregg Kellogg (gk) at NeXT
84: * NeXT doesn't use schedcpu.
85: * Move kallocinit() to vm/vm_init.c
86: *
87: * 14-Feb-90 Gregg Kellogg (gk) at NeXT
88: * Changes for new scheduler:
89: * Initialize scheduler
90: * use newproc() to start ux_handler.
91: * Remove process lock initialization.
92: * Remove obsolete service_timers() kickoff
93: * do callout_lock initialization in kern_synch.c/rqinit.
94: *
95: * 17-Jan-90 Morris Meyer (mmeyer) at NeXT
96: * NFS 4.0 Changes: Minimal cleanup. Removed ihinit.
97: *
98: * 07-Nov-88 Avadis Tevanian (avie) at NeXT
99: * Removed code to use transparent addresses since it only works
100: * when we have fully populated buffers (which is a bad assumption).
101: *
102: * 13-Aug-88 Avadis Tevanian (avie) at NeXT
103: * Removed dependencies on proc table.
104: *
105: * 4-May-88 David Black (dlb) at Carnegie-Mellon University
106: * MACH_TIME_NEW is now standard.
107: *
108: * 21-Apr-88 David Black (dlb) at Carnegie-Mellon University
109: * Set kernel_only for kernel task.
110: *
111: * 10-Apr-88 John Seamons (jks) at NeXT
112: * NeXT: Improve TLB performance for buffers by using the
113: * transparently translated virtual address for single page sized bufs.
114: *
115: * 07-Apr-88 John Seamons (jks) at NeXT
116: * NeXT: reduced the allocation size of various zones to save space.
117: *
118: * 3-Apr-88 Michael Young (mwyoung) at Carnegie-Mellon University
119: * Force the vm_map for the inode_ and device_ pager tasks to
120: * be the kernel map.
121: *
122: * 25-Jan-88 Richard Sanzi (sanzi) at Carnegie-Mellon University
123: * Moved float_init() call to configure() in autoconf.c
124: *
125: * 21-Jan-88 David Golub (dbg) at Carnegie-Mellon University
126: * Neither task_create nor thread_create return the data port
127: * any longer.
128: *
129: * 29-Dec-87 David Golub (dbg) at Carnegie-Mellon University
130: * Removed code to shuffle initial processes for idle threads;
131: * MACH doesn't need to make extra processes for them.
132: * Delinted.
133: *
134: * 12-Dec-87 Michael Young (mwyoung) at Carnegie-Mellon University
135: * Added device_pager startup. Moved setting of ipc_kernel and
136: * kernel_only flags here.
137: *
138: * 9-Dec-87 David Golub (dbg) at Carnegie-Mellon University
139: * Follow thread_terminate with thread_halt_self for new thread
140: * termination logic; extra reference no longer necessary.
141: *
142: * 9-Dec-87 David Black (dlb) at Carnegie-Mellon University
143: * Grab extra reference to first thread before terminating it.
144: *
145: * 4-Dec-87 David Black (dlb) at Carnegie-Mellon University
146: * Name changes for exc interface. set ipc_kernel in first thread
147: * for paranoia purposes.
148: *
149: * 19-Nov-87 Avadis Tevanian (avie) at Carnegie-Mellon University
150: * Eliminated MACH conditionals, purged history.
151: *
152: * 5-Nov-87 David Golub (dbg) at Carnegie-Mellon University
153: * start up network service thread.
154: *
155: * 9-Sep-87 Peter King (king) at NeXT
156: * SUN_VFS: Add a call to vfs_init() in setup_main().
157: *
158: * 17-Aug-87 Peter King (king) at NeXT
159: * SUN_VFS: Support credentials record in u.
160: * Convert to Sun quota system.
161: * Add call to dnlc_init(). Remove nchinit() call.
162: * Call swapconf() in binit().
163: */
164:
165: #import <mach_xp.h>
166: #import <quota.h>
167: #import <cpus.h>
168: #import <cputypes.h>
169: #import <mach_old_vm_copy.h>
170:
171:
172: #import <sys/param.h>
173: #import <sys/filedesc.h>
174: #import <sys/kernel.h>
175: #import <sys/mount.h>
176: #import <sys/proc.h>
177: #import <sys/systm.h>
178: #import <sys/vnode.h>
179: #import <sys/conf.h>
180: #import <sys/buf.h>
181: #import <sys/clist.h>
182: #import <sys/user.h>
183:
184: #import <ufs/ufs/quota.h>
185:
186: #import <machine/cpu.h>
187:
188: #import <sys/malloc.h>
189: #import <sys/dkstat.h>
190: #import <machine/reg.h>
191: #import <machine/spl.h>
192:
193: #import <kern/thread.h>
194: #import <kern/task.h>
195: #import <mach/machine.h>
196: #import <kern/timer.h>
197: #import <sys/version.h>
198: #import <machdep/machine/pmap.h>
199: #import <mach/vm_param.h>
200: #import <vm/vm_page.h>
201: #import <vm/vm_map.h>
202: #import <vm/vm_kern.h>
203: #import <vm/vm_object.h>
204: #import <mach/boolean.h>
205: #import <kern/sched_prim.h>
206: #import <kern/zalloc.h>
207: #if MACH_XP
208: #import <vm/vnode_pager.h>
209: #import <vm/device_pager.h>
210: #endif /* MACH_XP */
211:
212: #import <mach/task_special_ports.h>
213: #import <sys/ux_exception.h>
214: #import <sys/reboot.h>
215: #import "kernobjc.h"
216: #import "driverkit.h"
217:
218: #if NeXT
219: #import <kern/power.h>
220: #import <kern/parallel.h>
221: #endif /* NeXT */
222:
223: char copyright[] =
224: "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
225:
226: extern void ux_handler();
227:
228: /* Components of the first process -- never freed. */
229: struct proc proc0;
230: struct session session0;
231: struct pgrp pgrp0;
232: struct pcred cred0;
233: struct filedesc filedesc0;
234: struct plimit limit0;
235: struct pstats pstats0;
236: struct sigacts sigacts0;
237: struct proc *kernproc, *initproc;
238:
239:
240: long cp_time[CPUSTATES];
241: long dk_seek[DK_NDRIVE];
242: long dk_time[DK_NDRIVE];
243: long dk_wds[DK_NDRIVE];
244: long dk_wpms[DK_NDRIVE];
245: long dk_xfer[DK_NDRIVE];
246: long dk_bps[DK_NDRIVE];
247:
248: int dk_busy;
249: int dk_ndrive;
250:
251: long tk_cancc;
252: long tk_nin;
253: long tk_nout;
254: long tk_rawcc;
255:
256: #if NeXT
257: thread_t pageoutThread;
258: /* Global variables to make pstat happy. We do swapping differently */
259: int nswdev, nswap;
260: int nswapmap;
261: void *swapmap;
262: struct swdevt swdevt[1];
263: #endif /* NeXT */
264:
265: dev_t rootdev; /* device of the root */
266: dev_t dumpdev; /* device to take dumps on */
267: long dumplo; /* offset into dumpdev */
268: extern int show_space;
269: long hostid;
270: char hostname[MAXHOSTNAMELEN];
271: int hostnamelen;
272: char domainname[MAXDOMNAMELEN];
273: int domainnamelen;
274:
275: struct timeval boottime; /* GRODY! This has to go... */
276: struct timeval time;
277:
278: #ifdef KMEMSTATS
279: struct kmemstats kmemstats[M_LAST];
280: #endif
281:
282: int lbolt; /* awoken once a second */
283: struct vnode *rootvp;
284:
285: vm_map_t kernel_pageable_map;
286: vm_map_t mb_map;
287:
288: int cmask = CMASK;
289: /*
290: * Initialization code.
291: * Called from cold start routine as
292: * soon as a stack and segmentation
293: * have been established.
294: * Functions:
295: * clear and free user core
296: * turn on clock
297: * hand craft 0th process
298: * call all initialization routines
299: * fork - process 0 to schedule
300: * - process 1 execute bootstrap
301: * - process 2 to page out
302: */
303:
304: /*
305: * Sets the name for the given task.
306: */
307: void task_name(s, p)
308: char *s;
309: struct proc *p;
310: {
311: int length = strlen(s);
312:
313: bcopy(s, p->p_comm,
314: length >= sizeof(p->p_comm) ? sizeof(p->p_comm) :
315: length + 1);
316: }
317:
318: #if KERNOBJC
319: static int kernDefaultClassHandler(const char *className)
320: {
321: return 0;
322: }
323: #endif /* KERNOBJC */
324:
325: /* To allow these values to be patched, they're globals here */
326: #import <machine/vmparam.h>
327: struct rlimit vm_initial_limit_stack = { DFLSSIZ, MAXSSIZ };
328: struct rlimit vm_initial_limit_data = { DFLDSIZ, MAXDSIZ };
329: struct rlimit vm_initial_limit_core = { DFLCSIZ, MAXCSIZ };
330:
331: extern thread_t first_thread;
332:
333: #define SPL_DEBUG 0
334: #if SPL_DEBUG
335: #define dprintf(x) printf x
336: #else SPL_DEBUG
337: #define dprintf(x)
338: #endif /* SPL_DEBUG */
339:
340: void
341: main()
342: {
343: register struct proc *p;
344: extern struct ucred *rootcred;
345: register int i;
346: int s;
347: thread_t th;
348: extern void idle_thread(), init_task(), vm_pageout();
349: extern void reaper_thread(), swapin_thread();
350: extern void netisr_thread(), sched_thread();
351: #if NeXT
352: extern int power_callout(void *, void *);
353: #endif /* NeXT */
354:
355: #if PRELOAD
356: extern void prepagein_thread();
357: #endif
358: #if NCPUS > 1
359: extern void action_thread();
360: #endif /* NCPUS > 1 */
361: #if MACH_XP
362: thread_t inode_th;
363: thread_t device_th;
364: #endif /* MACH_XP */
365: void lightning_bolt(void *, void *);
366: extern thread_t cloneproc();
367:
368: extern int (*mountroot) __P((void));
369:
370: dprintf(("main entry: curspl=0x%x\n", curspl()));
371:
372: printf(copyright);
373:
374: kmeminit();
375:
376: /*
377: * Initialize process and pgrp structures.
378: */
379: procinit();
380:
381: kernproc = &proc0;
382:
383: p = kernproc;
384: kernel_task->proc = kernproc;
385: p->p_pid = 0;
386:
387: /*
388: * Create process 0.
389: */
390: LIST_INSERT_HEAD(&allproc, p, p_list);
391: p->p_pgrp = &pgrp0;
392: LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
393: LIST_INIT(&pgrp0.pg_members);
394: LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
395:
396: pgrp0.pg_session = &session0;
397: session0.s_count = 1;
398: session0.s_leader = p;
399:
400: p->task = kernel_task;
401: /*
402: * Now in thread context, switch to thread timer.
403: */
404: s = splhigh();
405: dprintf(("main splhigh: curspl=0x%x\n", curspl()));
406: timer_switch(¤t_thread()->system_timer);
407: splx(s);
408: dprintf(("main splx: curspl=0x%x\n", curspl()));
409:
410: thread_call_init();
411:
412: p->p_stat = SRUN;
413: p->p_flag = P_INMEM|P_SYSTEM;
414: p->p_nice = NZERO;
415: p->p_pptr = p;
416: simple_lock_init(&p->siglock);
417: p->sigwait = FALSE;
418: p->sigwait_thread = THREAD_NULL;
419: p->exit_thread = THREAD_NULL;
420:
421: /* Create credentials. */
422: lockinit(&cred0.pc_lock, PLOCK, "proc0 cred", 0, 0);
423: cred0.p_refcnt = 1;
424: p->p_cred = &cred0;
425: p->p_ucred = crget();
426: p->p_ucred->cr_ngroups = 1; /* group 0 */
427:
428: /* Create the file descriptor table. */
429: filedesc0.fd_refcnt = 1;
430: p->p_fd = &filedesc0;
431: filedesc0.fd_cmask = cmask;
432:
433: /* Create the limits structures. */
434: p->p_limit = &limit0;
435: for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
436: limit0.pl_rlimit[i].rlim_cur =
437: limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
438: limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
439: limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
440: limit0.pl_rlimit[RLIMIT_STACK] = vm_initial_limit_stack;
441: limit0.pl_rlimit[RLIMIT_DATA] = vm_initial_limit_data;
442: limit0.pl_rlimit[RLIMIT_CORE] = vm_initial_limit_core;
443: limit0.p_refcnt = 1;
444:
445: p->p_stats = &pstats0;
446: p->p_sigacts = &sigacts0;
447:
448: /*
449: * Charge root for one process.
450: */
451: (void)chgproccnt(0, 1);
452:
453: /*
454: * Allocate a kernel submap for pageable memory
455: * for temporary copying (table(), execve()).
456: */
457: {
458: vm_offset_t min, max;
459:
460: kernel_pageable_map = kmem_suballoc(kernel_map,
461: &min, &max,
462: 512*1024,
463: TRUE);
464: #if MACH_OLD_VM_COPY
465: #else MACH_OLD_VM_COPY
466: kernel_pageable_map->wait_for_space = TRUE;
467: #endif /* MACH_OLD_VM_COPY */
468: }
469:
470: hardclock_init();
471:
472: mapfs_init();
473:
474: /* Initialize the file systems. */
475: vfsinit();
476:
477: /* Initialize mbuf's. */
478: mbinit();
479:
480: /* Initialize syslog */
481: log_init();
482:
483: /*
484: * Initialize protocols. Block reception of incoming packets
485: * until everything is ready.
486: */
487: s = splimp();
488: ifinit();
489: socketinit();
490: domaininit();
491: splx(s);
492:
493: /*
494: * Create kernel idle cpu processes. This must be done
495: * before a context switch can occur (and hence I/O can
496: * happen in the binit() call).
497: */
498: p->p_fd->fd_cdir = NULL;
499: p->p_fd->fd_rdir = NULL;
500:
501: for (i = 0; i < NCPUS; i++) {
502: if (machine_slot[i].is_cpu == FALSE)
503: continue;
504: (void) thread_create(kernel_task, &th);
505: thread_bind(th, cpu_to_processor(i));
506: thread_start(th, idle_thread);
507: thread_doswapin(th);
508: (void) thread_resume(th);
509: }
510:
511: #ifdef GPROF
512: /* Initialize kernel profiling. */
513: kmstartup();
514: #endif
515:
516: /* kick off timeout driven events by calling first time */
517: lightning_bolt(0, 0);
518:
519: /*
520: * Start up netisr thread now in case we are doing an nfs_mountroot.
521: */
522: (void) kernel_thread(kernel_task, reaper_thread, (void *)0);
523: (void) kernel_thread(kernel_task, swapin_thread, (void *)0);
524: (void) kernel_thread(kernel_task, sched_thread, (void *)0);
525: #if NCPUS > 1
526: (void) kernel_thread(kernel_task, action_thread, (void *)0);
527: #endif /* NCPUS > 1 */
528: (void) kernel_thread(kernel_task, netisr_thread, (void *)0);
529:
530: #if KERNOBJC
531: _objcInit();
532: objc_setClassHandler(kernDefaultClassHandler);
533: #endif /* KERNOBJC */
534:
535: #ifdef DRIVERKIT
536: /* Spin cursor in a fashion vaguely similar to 68k boot ROM.
537: * Eventually this will be the same on all architectures.
538: */
539: kmEnableAnimation();
540: #if defined(ppc)
541: /* this is temporary - until driver kit works */
542: #warning this is temporary too
543: bsd_autoconf();
544: #endif
545:
546: autoconf();
547:
548: #elif /* DRIVERKIT */
549: #warning this is temporary
550: /* this is temporary - until driver kit works */
551: bsd_autoconf();
552: #endif /* DRIVERKIT */
553:
554: /*
555: * We attach the loopback interface *way* down here to ensure
556: * it happens after autoconf(), otherwise it becomes the
557: * "primary" interface.
558: */
559: #import <loop.h>
560: #if NLOOP > 0
561: loopattach(); /* XXX */
562: #endif
563:
564: /* Mount the root file system. */
565: while( TRUE) {
566: int err;
567:
568: setconf();
569: if (0 == (err = vfs_mountroot()))
570: break;
571: printf("cannot mount root, errno = %d\n", err);
572: boothowto |= RB_ASKNAME;
573: }
574:
575: mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
576:
577: /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
578: if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
579: panic("cannot find root vnode");
580: filedesc0.fd_cdir = rootvnode;
581: VREF(rootvnode);
582: VOP_UNLOCK(rootvnode, 0, p);
583:
584: /*
585: * Now can look at time, having had a chance to verify the time
586: * from the file system. Reset p->p_rtime as it may have been
587: * munched in mi_switch() after the time got set.
588: */
589: p->p_stats->p_start = boottime = time;
590: p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
591:
592: /* Initialize signal state for process 0. */
593: siginit(p);
594:
595: /*
596: * make init process
597: */
598:
599: th = cloneproc(kernproc);
600: th->task->kernel_privilege = FALSE; /* XXX cleaner way to do this?
601: */
602: #if NeXT
603: initproc = pfind(1); /* now that it is set */
604: #endif /* NeXT */
605: /*
606: * After calling start_init,
607: * machine-dependent code must
608: * set up stack as though a system
609: * call trap occurred, then call
610: * load_init_program.
611: */
612:
613: /*
614: * Start up unix exception server
615: */
616: ux_handler_init();
617: port_reference(ux_exception_port);
618: (void) task_set_exception_port(th->task, ux_exception_port);
619:
620: thread_start(th, init_task);
621: (void) thread_resume(th);
622:
623: /*
624: * Kernel daemon threads that don't need their own tasks
625: */
626:
627: /*
628: * Initialize power management
629: */
630: power_init();
631:
632: pageoutThread = kernel_thread(kernel_task, vm_pageout, (void *)0);
633:
634: /*
635: * vol driver and notification server startup
636: */
637: #if NeXT
638: vol_start_thread();
639: pnotify_start();
640: #endif /* NeXT */
641:
642: #if NeXT && NCPUS > 1
643: /*
644: * The CMU VAX code does this from the start_init() code,
645: * but that seems like an "unusual" place to do it. (Like
646: * I didn't look there right away :-). Doing this here isn't
647: * much better, but it is one of the places I looked. This
648: * can't be done until the idle threads are created for each
649: * cpu (see about 50 lines above).
650: */
651: start_other_cpus();
652: #endif /* NeXT && NCPUS > 1 */
653:
654: task_name("kernel idle", p);
655: (void) thread_terminate(current_thread());
656: thread_halt_self();
657: /*NOTREACHED*/
658: }
659:
660: void
661: init_task()
662: {
663: struct proc *p = current_proc();
664:
665: task_name("init", p);
666:
667: current_thread()->_uthread->uu_ar0 = (void *)USER_REGS(current_thread());
668:
669: load_init_program(p);
670:
671: thread_exception_return();
672: /*NOTREACHED*/
673: }
674:
675: void
676: lightning_bolt(
677: thread_call_spec_t argument,
678: thread_call_t callout
679: )
680: {
681: thread_wakeup(&lbolt);
682:
683: if (!callout)
684: callout = thread_call_allocate(lightning_bolt, 0);
685:
686: thread_call_enter_delayed(callout,
687: deadline_from_interval((tvalspec_t) { 1, 0 } ));
688: }
689:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.