diff options
Diffstat (limited to 'sys/kern/init_main.c')
-rw-r--r-- | sys/kern/init_main.c | 404 |
1 files changed, 269 insertions, 135 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 854b6ca..b38b25a 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,7 @@ /* + * Copyright (c) 1995 Terrence R. Lambert + * All rights reserved. + * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. @@ -72,13 +75,6 @@ #include <vm/vm.h> #include <vm/vm_pageout.h> -#ifdef HPFPLIB -char copyright[] = -"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n"; -#else -char copyright[] = -"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; -#endif /* Components of the first process -- never freed. */ struct session session0; @@ -89,7 +85,7 @@ struct filedesc0 filedesc0; struct plimit limit0; struct vmspace vmspace0; struct proc *curproc = &proc0; -struct proc *initproc, *pageproc, *updateproc, *vmproc; +struct proc *initproc; int cmask = CMASK; extern struct user *proc0paddr; @@ -99,51 +95,212 @@ int boothowto; struct timeval boottime; struct timeval runtime; -static void start_init __P((struct proc *p, void *framep)); +/* + * Promiscuous argument pass for start_init() + * + * This is a kludge because we use a return from main() rather than a call + * to a new reoutine in locore.s to kick the kernel alive from locore.s. + */ +static void *init_framep; + #if __GNUC__ >= 2 void __main() {} #endif + /* - * This table is filled in by the linker with functions that need to be - * called to initialize various pseudo-devices and whatnot. + * This ensures that there is at least one entry so that the sysinit_set + * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never + * executed. */ +SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL) -static void dummyinit() {} -TEXT_SET(pseudo_set, dummyinit); - -typedef void (*pseudo_func_t)(void); -extern const struct linker_set pseudo_set; -static const pseudo_func_t *pseudos = - (const pseudo_func_t *)&pseudo_set.ls_items[0]; /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. + * + * This allows simple addition of new kernel subsystems that require + * boot time initialization. It also allows substitution of subsystem + * (for instance, a scheduler, kernel profiler, or VM system) by object + * module. Finally, it allows for optional "kernel threads", like an LFS + * cleaner. */ void main(framep) void *framep; { - register struct proc *p; - register struct filedesc0 *fdp; + + register struct sysinit **sipp; /* system initialization*/ + register struct sysinit **xipp; /* interior loop of sort*/ + register struct sysinit *save; /* bubble*/ + int rval[2]; /* SI_TYPE_KTHREAD support*/ + + extern struct linker_set sysinit_set; + + /* + * Save the locore.s frame pointer for start_init(). + */ + init_framep = framep; + + /* + * Perform a bubble sort of the system initialization objects by + * their subsystem (primary key) and order (secondary key). + * + * Since some things care about execution order, this is the + * operation which ensures continued function. + */ + for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { + for( xipp = sipp + 1; *xipp; xipp++) { + if( (*sipp)->subsystem < (*xipp)->subsystem || + ( (*sipp)->subsystem == (*xipp)->subsystem && + (*sipp)->order < (*xipp)->order)) + continue; /* skip*/ + save = *sipp; + *sipp = *xipp; + *xipp = save; + } + } + + /* + * Traverse the (now) ordered list of system initialization tasks. + * Perform each task, and continue on to the next task. + * + * The last item on the list is expected to be the scheduler, + * which will not return. + */ + for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { + if( (*sipp)->subsystem == SI_SUB_DUMMY) + continue; /* skip dummy task(s)*/ + + switch( (*sipp)->type) { + case SI_TYPE_DEFAULT: + /* no special processing*/ + (*((*sipp)->func))( (*sipp)->udata); + break; + + case SI_TYPE_KTHREAD: + /* kernel thread*/ + if (fork(&proc0, NULL, rval)) + panic("fork kernel process"); + if (rval[1]) { + (*((*sipp)->func))( (*sipp)->udata); + /* + * The call to start "init" returns + * here after the scheduler has been + * started, and returns to the caller + * in i386/i386/locore.s. This is a + * necessary part of initialization + * and is rather non-obvious. + * + * No other "kernel threads" should + * return here. Call panic() instead. + */ + return; + } + break; + + default: + panic( "init_main: unrecognized init type"); + } + } + + /* NOTREACHED*/ +} + + +/* + * Start a kernel process. This is called after a fork() call in + * main() in the file kern/init_main.c. + * + * This function is used to start "internal" daemons. + */ +/* ARGSUSED*/ +void +kproc_start( udata) +caddr_t udata; /* not used*/ +{ + struct kproc_desc *kp = (struct kproc_desc *)udata; + struct proc *p = curproc; + + /* save a global descriptor, if desired*/ + if( kp->global_procpp != NULL) + *kp->global_procpp = p; + + /* this is a non-swapped system process*/ + p->p_flag |= P_INMEM | P_SYSTEM; + + /* set up arg0 for 'ps', et al*/ + strcpy( p->p_comm, kp->arg0); + + /* call the processes' main()...*/ + (*kp->func)(); + + /* NOTREACHED */ + panic( "kproc_start: %s", kp->arg0); +} + + +/* + *************************************************************************** + **** + **** The following SYSINIT's belong elsewhere, but have not yet + **** been moved. + **** + *************************************************************************** + */ +#ifdef OMIT +/* + * Handled by vfs_mountroot (bad idea) at this time... should be + * done the same as 4.4Lite2. + */ +SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL) +#endif /* OMIT*/ + +/* + * Should get its own file... + */ +#ifdef HPFPLIB +char copyright[] = +"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n"; +#else +char copyright[] = +"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; +#endif +SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, printf, (caddr_t)copyright) + + +/* + *************************************************************************** + **** + **** The two following SYSINT's are proc0 specific glue code. I am not + **** convinced that they can not be safely combined, but their order of + **** operation has been maintained as the same as the original init_main.c + **** for right now. + **** + **** These probably belong in init_proc.c or kern_proc.c, since they + **** deal with proc0 (the fork template process). + **** + *************************************************************************** + */ +/* ARGSUSED*/ +void +proc0_init( udata) +caddr_t udata; /* not used*/ +{ + register struct proc *p; + register struct filedesc0 *fdp; register int i; - int s, rval[2]; /* * Initialize the current process pointer (curproc) before * any possible traps/probes to simplify trap processing. */ p = &proc0; - curproc = p; - printf(copyright); - - vm_mem_init(); - kmeminit(); - cpu_startup(); + curproc = p; /* XXX redundant*/ /* * Create process 0 (the swapper). @@ -204,13 +361,16 @@ main(framep) vmspace0.vm_map.pmap = &vmspace0.vm_pmap; p->p_addr = proc0paddr; /* XXX */ +#define INCOMPAT_LITES2 +#ifdef INCOMPAT_LITES2 /* * proc0 needs to have a coherent frame base, too. * This probably makes the identical call for the init proc * that happens later unnecessary since it should inherit * it during the fork. */ - cpu_set_init_frame(p, framep); /* XXX! */ + cpu_set_init_frame(p, init_framep); /* XXX! */ +#endif /* INCOMPAT_LITES2*/ /* * We continue to place resource usage info and signal @@ -225,67 +385,66 @@ main(framep) */ usrinfoinit(); (void)chgproccnt(0, 1); +} +SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) - rqinit(); - - /* Configure virtual memory system, set vm rlimits. */ - vm_init_limits(p); - - /* Initialize the file systems. */ - vfsinit(); - - /* Start real time and statistics clocks. */ - initclocks(); - - /* Initialize mbuf's. */ - mbinit(); - - /* Initialize clists. */ - clist_init(); - -#ifdef SYSVSHM - /* Initialize System V style shared memory. */ - shminit(); -#endif - -#ifdef SYSVSEM - /* Initialize System V style semaphores. */ - seminit(); -#endif - -#ifdef SYSVMSG - /* Initialize System V style message queues. */ - msginit(); -#endif - +/* ARGSUSED*/ +void +proc0_post( udata) +caddr_t udata; /* not used*/ +{ /* - * Attach pseudo-devices. + * Now can look at time, having had a chance to verify the time + * from the file system. Reset p->p_rtime as it may have been + * munched in mi_switch() after the time got set. */ - while(*pseudos) { - (**pseudos++)(); - } + proc0.p_stats->p_start = runtime = mono_time = boottime = time; + proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0; + + /* Initialize signal state for process 0. */ + siginit(&proc0); +} +SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) - /* - * Initialize protocols. Block reception of incoming packets - * until everything is ready. - */ - s = splimp(); - ifinit(); - domaininit(); - splx(s); -#ifdef GPROF - /* Initialize kernel profiling. */ - kmstartup(); -#endif + +/* + *************************************************************************** + **** + **** The following SYSINIT's and glue code should be moved to the + **** respective files on a per subsystem basis. + **** + *************************************************************************** + */ +/* ARGSUSED*/ +void +sched_setup( udata) +caddr_t udata; /* not used*/ +{ /* Kick off timeout driven events by calling first time. */ roundrobin(NULL); schedcpu(NULL); +} +SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) +/* ARGSUSED*/ +void +xxx_vfs_mountroot( udata) +caddr_t udata; /* not used*/ +{ /* Mount the root file system. */ - if ((*mountroot)()) + if ((*mountroot)( (caddr_t)mountrootvfsops)) panic("cannot mount root"); +} +SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, NULL) + +/* ARGSUSED*/ +void +xxx_vfs_root_fdtab( udata) +caddr_t udata; /* not used*/ +{ + register struct filedesc0 *fdp = &filedesc0; /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) @@ -294,74 +453,46 @@ main(framep) VREF(fdp->fd_fd.fd_cdir); VOP_UNLOCK(rootvnode); fdp->fd_fd.fd_rdir = NULL; +} +SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL) - /* - * Now can look at time, having had a chance to verify the time - * from the file system. Reset p->p_rtime as it may have been - * munched in mi_switch() after the time got set. - */ - p->p_stats->p_start = runtime = mono_time = boottime = time; - p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; - /* Initialize signal state for process 0. */ - siginit(p); +/* + *************************************************************************** + **** + **** The following code probably belongs in another file, like + **** kern/init_init.c. It is here for two reasons only: + **** + **** 1) This code returns to startup the system; this is + **** abnormal for a kernel thread. + **** 2) This code promiscuously uses init_frame + **** + *************************************************************************** + */ - /* Create process 1 (init(8)). */ - if (fork(p, NULL, rval)) - panic("fork init"); - if (rval[1]) { - start_init(curproc, framep); - return; - } +static void kthread_init __P(( caddr_t udata)); +SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL) - /* Create process 2 (the pageout daemon). */ - if (fork(p, NULL, rval)) - panic("fork pager"); - if (rval[1]) { - /* - * Now in process 2. - */ - p = curproc; - pageproc = p; - p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ - bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); - vm_pageout(); - /* NOTREACHED */ - } - /* - * Start high level vm daemon (process 3). - */ - if (fork(p, (void *) NULL, rval)) - panic("failed fork vm daemon"); - if (rval[1]) { - p = curproc; - vmproc = p; - p->p_flag |= P_INMEM | P_SYSTEM; - bcopy("vmdaemon", p->p_comm, sizeof("vmdaemon")); - vm_daemon(); - /*NOTREACHED*/ - } +static void start_init __P((struct proc *p, void *framep)); + +/* ARGSUSED*/ +static void +kthread_init( udata) +caddr_t udata; /* not used*/ +{ + + /* Create process 1 (init(8)). */ + start_init(curproc, init_framep); /* - * Start update daemon (process 4). + * This is the only kernel thread allowed to return yo the + * caller!!! */ - if (fork(p, (void *) NULL, rval)) - panic("failed fork update daemon"); - if (rval[1]) { - p = curproc; - updateproc = p; - p->p_flag |= P_INMEM | P_SYSTEM; - bcopy("update", p->p_comm, sizeof("update")); - vfs_update(); - /*NOTREACHED*/ - } - - /* The scheduler is an infinite loop. */ - scheduler(); - /* NOTREACHED */ + return; } + /* * List of paths to try when searching for "init". */ @@ -459,6 +590,9 @@ start_init(p, framep) /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. + * + * Otherwise return to main() which returns to btext + * which completes the system startup. */ if ((error = execve(p, &args, &retval[0])) == 0) return; |