* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)init_main.c 7.37 (Berkeley) %G%
* Components of process 0;
struct filedesc0 filedesc0
;
struct proc
*curproc
= &proc0
;
struct proc
*initproc
, *pageproc
;
extern caddr_t proc0paddr
;
extern int (*mountroot
)();
* 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
register struct filedesc0
*fdp
;
* Initialize curproc before any possible traps/probes
* to simplify trap processing.
* Attempt to find console and initialize
* in case of early panic or other messages.
* set up system process 0 (swapper)
pgrp0
.pg_session
= &session0
;
bcopy("swapper", p
->p_comm
, sizeof ("swapper"));
p
->p_ucred
->cr_ngroups
= 1; /* group 0 */
* Create the file descriptor table for process 0.
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
;
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_OFILE
].rlim_cur
= NOFILE
;
limit0
.pl_rlimit
[RLIMIT_NPROC
].rlim_cur
= MAXUPRC
;
* 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
= &((struct user
*)p
->p_addr
)->u_stats
;
p
->p_sigacts
= &((struct user
*)p
->p_addr
)->u_sigacts
;
* configure virtual memory system,
* Initialize the file systems.
* Get vnodes for swapdev, argdev, and rootdev.
if (bdevvp(swapdev
, &swapdev_vp
) ||
bdevvp(argdev
, &argdev_vp
) ||
bdevvp(rootdev
, &rootvp
))
panic("can't setup bdevvp's");
* Initialize tables, protocols, and set up well-known inodes.
* Block reception of incoming packets
* until protocols have been initialized.
/* kick off timeout driven events by calling first time */
enablertclock(); /* enable realtime clock interrupts */
* Set up the root file system and vnode.
panic("cannot mount root");
* Setup rootdir and fdp->fd_fd.fd_cdir to point to it.
if (VFS_ROOT(rootfs
, &rootdir
))
panic("cannot find root vnode");
fdp
->fd_fd
.fd_cdir
= rootdir
;
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.
boottime
= p
->p_stats
->p_start
= time
;
if (fork(p
, (void *) NULL
, rval
))
static char initflags
[] = "-sf";
char *ip
= initflags
+ 1;
* Now in process 1. Set init flags into icode,
* get a minimal address space, copy out "icode",
* and return to it to do an exec of init.
if (boothowto
&RB_FASTBOOT
)
if (vm_allocate(&p
->p_vmspace
->vm_map
, &addr
,
round_page(szicode
+ sizeof(initflags
)), FALSE
) != 0 ||
panic("init: couldn't allocate at zero");
/* need just enough stack to exec from */
addr
= trunc_page(VM_MAX_ADDRESS
- PAGE_SIZE
);
if (vm_allocate(&p
->p_vmspace
->vm_map
, &addr
,
PAGE_SIZE
, FALSE
) != KERN_SUCCESS
)
panic("vm_allocate init stack");
p
->p_vmspace
->vm_maxsaddr
= (caddr_t
)addr
;
(void) copyout((caddr_t
)icode
, (caddr_t
)0, (unsigned)szicode
);
(void) copyout(initflags
, (caddr_t
)szicode
, sizeof(initflags
));
return; /* returns to icode */
* Start up pageout daemon (process 2).
if (fork(p
, (void *) NULL
, rval
))
p
->p_flag
|= SLOAD
|SSYS
; /* XXX */
bcopy("pagedaemon", curproc
->p_comm
, sizeof ("pagedaemon"));
/* MOVE TO vfs_bio.c (bufinit) XXX */
* Initialize buffers and hash links for buffers.
register struct buf
*bp
, *dp
;
register struct bufhd
*hp
;
for (hp
= bufhash
, i
= 0; i
< BUFHSZ
; i
++, hp
++)
hp
->b_forw
= hp
->b_back
= (struct buf
*)hp
;
for (dp
= bfreelist
; dp
< &bfreelist
[BQUEUES
]; dp
++) {
dp
->b_forw
= dp
->b_back
= dp
->av_forw
= dp
->av_back
= dp
;
residual
= bufpages
% nbuf
;
for (i
= 0; i
< nbuf
; i
++) {
bp
->b_un
.b_addr
= buffers
+ i
* MAXBSIZE
;
bp
->b_bufsize
= (base
+ 1) * CLBYTES
;
bp
->b_bufsize
= base
* CLBYTES
;
binshash(bp
, &bfreelist
[BQ_AGE
]);
bp
->b_flags
= B_BUSY
|B_INVAL
;