* Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
* %sccs.include.redist.c%
* @(#)init_main.c 8.12 (Berkeley) %G%
#include <sys/filedesc.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/syscallargs.h>
"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";
"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
/* Components of the first process -- never freed. */
struct filedesc0 filedesc0
;
struct proc
*curproc
= &proc0
;
struct proc
*initproc
, *pageproc
;
extern struct user
*proc0paddr
;
struct vnode
*rootvp
, *swapdev_vp
;
static void start_init
__P((struct proc
*p
, void *framep
));
* 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.
register struct filedesc0
*fdp
;
register struct pdevinit
*pdev
;
extern int (*mountroot
) __P((void));
extern struct pdevinit pdevinit
[];
extern void roundrobin
__P((void *));
extern void schedcpu
__P((void *));
* Initialize the current process pointer (curproc) before
* any possible traps/probes to simplify trap processing.
* Attempt to find console and initialize
* in case of early panic or other messages.
* Initialize process and pgrp structures.
* Create process 0 (the swapper).
LIST_INSERT_HEAD(&allproc
, p
, p_list
);
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0
, pg_hash
);
LIST_INIT(&pgrp0
.pg_members
);
LIST_INSERT_HEAD(&pgrp0
.pg_members
, p
, p_pglist
);
pgrp0
.pg_session
= &session0
;
p
->p_flag
= P_INMEM
| P_SYSTEM
;
bcopy("swapper", p
->p_comm
, sizeof ("swapper"));
/* Create credentials. */
p
->p_ucred
->cr_ngroups
= 1; /* group 0 */
/* Create the file descriptor table. */
fdp
->fd_fd
.fd_refcnt
= 1;
fdp
->fd_fd
.fd_cmask
= cmask
;
fdp
->fd_fd
.fd_ofiles
= fdp
->fd_dfiles
;
fdp
->fd_fd
.fd_ofileflags
= fdp
->fd_dfileflags
;
fdp
->fd_fd
.fd_nfiles
= NDFILE
;
/* Create the limits structures. */
for (i
= 0; i
< sizeof(p
->p_rlimit
)/sizeof(p
->p_rlimit
[0]); i
++)
limit0
.pl_rlimit
[i
].rlim_cur
=
limit0
.pl_rlimit
[i
].rlim_max
= RLIM_INFINITY
;
limit0
.pl_rlimit
[RLIMIT_NOFILE
].rlim_cur
= NOFILE
;
limit0
.pl_rlimit
[RLIMIT_NPROC
].rlim_cur
= MAXUPRC
;
i
= ptoa(cnt
.v_free_count
);
limit0
.pl_rlimit
[RLIMIT_RSS
].rlim_max
= i
;
limit0
.pl_rlimit
[RLIMIT_MEMLOCK
].rlim_max
= i
;
limit0
.pl_rlimit
[RLIMIT_MEMLOCK
].rlim_cur
= i
/ 3;
/* Allocate a prototype map so we have something to fork. */
p
->p_vmspace
= &vmspace0
;
pmap_pinit(&vmspace0
.vm_pmap
);
vm_map_init(&p
->p_vmspace
->vm_map
, round_page(VM_MIN_ADDRESS
),
trunc_page(VM_MAX_ADDRESS
), TRUE
);
vmspace0
.vm_map
.pmap
= &vmspace0
.vm_pmap
;
p
->p_addr
= proc0paddr
; /* XXX */
* We continue to place resource usage info and signal
* actions in the user struct so they're pageable.
p
->p_stats
= &p
->p_addr
->u_stats
;
p
->p_sigacts
= &p
->p_addr
->u_sigacts
;
* Charge root for one process.
/* Configure virtual memory system, set vm rlimits. */
/* Initialize the file systems. */
/* Start real time and statistics clocks. */
/* Initialize System V style shared memory. */
/* Attach pseudo-devices. */
for (pdev
= pdevinit
; pdev
->pdev_attach
!= NULL
; pdev
++)
(*pdev
->pdev_attach
)(pdev
->pdev_count
);
* Initialize protocols. Block reception of incoming packets
* until everything is ready.
/* Initialize kernel profiling. */
/* Kick off timeout driven events by calling first time. */
/* Mount the root file system. */
panic("cannot mount root");
/* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
if (VFS_ROOT(mountlist
.tqh_first
, &rootvnode
))
panic("cannot find root vnode");
fdp
->fd_fd
.fd_cdir
= rootvnode
;
VREF(fdp
->fd_fd
.fd_cdir
);
fdp
->fd_fd
.fd_rdir
= 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. */
/* Create process 1 (init(8)). */
start_init(curproc
, framep
);
/* Create process 2 (the pageout daemon). */
p
->p_flag
|= P_INMEM
| P_SYSTEM
; /* XXX */
bcopy("pagedaemon", curproc
->p_comm
, sizeof ("pagedaemon"));
/* The scheduler is an infinite loop. */
* List of paths to try when searching for "init".
static char *initpaths
[] = {
* Start the initial user process; try exec'ing each pathname in "initpaths".
* The program is invoked with one argument containing the boot flags.
syscallarg(char **) argp;
syscallarg(char **) envp;
char flags
[4] = "-", *flagsp
;
char **pathp
, *path
, *ucp
, **uap
, *arg0
, *arg1
;
* We need to set the system call frame as if we were entered through
* a syscall() so that when we call execve() below, it will be able
* to set the entry point (see setregs) when it tries to exec. The
* startup code in "locore.s" has allocated space for the frame and
* passed a pointer to that space as main's argument.
cpu_set_init_frame(p
, framep
);
* Need just enough stack to hold the faked-up "execve()" arguments.
addr
= trunc_page(VM_MAX_ADDRESS
- PAGE_SIZE
);
if (vm_allocate(&p
->p_vmspace
->vm_map
, &addr
, PAGE_SIZE
, FALSE
) != 0)
panic("init: couldn't allocate argument space");
p
->p_vmspace
->vm_maxsaddr
= (caddr_t
)addr
;
for (pathp
= &initpaths
[0]; (path
= *pathp
) != NULL
; pathp
++) {
* Construct the boot flag argument.
if (boothowto
& RB_SINGLE
) {
if (boothowto
& RB_FASTBOOT
) {
* Move out the flags (arg 1), if necessary.
(void)copyout((caddr_t
)flags
, (caddr_t
)(ucp
-= i
), i
);
* Move out the file name (also arg 0).
(void)copyout((caddr_t
)path
, (caddr_t
)(ucp
-= i
), i
);
* Move out the arg pointers.
uap
= (char **)((long)ucp
& ~ALIGNBYTES
);
(void)suword((caddr_t
)--uap
, 0); /* terminator */
(void)suword((caddr_t
)--uap
, (long)arg1
);
(void)suword((caddr_t
)--uap
, (long)arg0
);
* Point at the arguments.
SCARG(&args
, path
) = arg0
;
SCARG(&args
, argp
) = uap
;
SCARG(&args
, envp
) = NULL
;
* Now try to exec the program. If can't for any reason
* other than it doesn't exist, complain.
if ((error
= execve(p
, &args
, retval
)) == 0)
printf("exec %s: error %d\n", path
, error
);
printf("init: not found\n");