xref: /csrg-svn/sys/kern/init_main.c (revision 56935)
123364Smckusick /*
247543Skarels  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
347817Skarels  * All rights reserved.
423364Smckusick  *
547817Skarels  * %sccs.include.redist.c%
647817Skarels  *
7*56935Smckusick  *	@(#)init_main.c	7.57 (Berkeley) 12/01/92
823364Smckusick  */
926Sbill 
1056934Smckusick #include <sys/param.h>
1156934Smckusick #include <sys/filedesc.h>
1256934Smckusick #include <sys/kernel.h>
1356934Smckusick #include <sys/mount.h>
1456934Smckusick #include <sys/map.h>
1556934Smckusick #include <sys/proc.h>
1656934Smckusick #include <sys/resourcevar.h>
1756934Smckusick #include <sys/signalvar.h>
1856934Smckusick #include <sys/systm.h>
1956934Smckusick #include <sys/vnode.h>
2056934Smckusick #include <sys/conf.h>
2156934Smckusick #include <sys/buf.h>
2256934Smckusick #include <sys/clist.h>
2356934Smckusick #include <sys/protosw.h>
2456934Smckusick #include <sys/reboot.h>
2556934Smckusick #include <sys/user.h>
2647654Skarels 
2756934Smckusick #include <ufs/ufs/quota.h>
2826Sbill 
2956934Smckusick #include <machine/cpu.h>
3037522Smckusick 
3156934Smckusick #include <vm/vm.h>
3245724Smckusick 
3355399Smckusick #ifdef HPFPLIB
3449382Skarels char	copyright[] =
3555399Smckusick "Copyright (c) 1982,1986,1989,1991 The Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n";
3655399Smckusick #else
3755399Smckusick char	copyright[] =
3849382Skarels "Copyright (c) 1982,1986,1989,1991 The Regents of the University of California.\nAll rights reserved.\n\n";
3955399Smckusick #endif
4049382Skarels 
4147543Skarels /*
4247543Skarels  * Components of process 0;
4347543Skarels  * never freed.
4447543Skarels  */
4547543Skarels struct	session session0;
4647543Skarels struct	pgrp pgrp0;
4747543Skarels struct	proc proc0;
4847543Skarels struct	pcred cred0;
4947654Skarels struct	filedesc0 filedesc0;
5047543Skarels struct	plimit limit0;
5147543Skarels struct	vmspace vmspace0;
5247654Skarels struct	proc *curproc = &proc0;
5347543Skarels struct	proc *initproc, *pageproc;
5447543Skarels 
5516807Skarels int	cmask = CMASK;
5648981Skarels extern	struct user *proc0paddr;
5737610Smckusick extern	int (*mountroot)();
5845880Swilliam 
5949382Skarels struct	vnode *rootvp, *swapdev_vp;
6049382Skarels int	boothowto;
6153009Ssklower struct	timeval boottime;
6254781Storek struct	timeval runtime;
6349382Skarels 
6426Sbill /*
6547543Skarels  * System startup; initialize the world, create process 0,
6647543Skarels  * mount root filesystem, and fork to create init and pagedaemon.
6747543Skarels  * Most of the hard work is done in the lower-level initialization
6847543Skarels  * routines including startup(), which does memory initialization
6947543Skarels  * and autoconfiguration.
7026Sbill  */
7149533Skarels main()
7226Sbill {
73361Sbill 	register int i;
742451Swnj 	register struct proc *p;
7547654Skarels 	register struct filedesc0 *fdp;
7647543Skarels 	int s, rval[2];
7754781Storek 	extern void roundrobin __P((void *));
7854781Storek 	extern void schedcpu __P((void *));
7926Sbill 
8045880Swilliam 	/*
8147543Skarels 	 * Initialize curproc before any possible traps/probes
8247543Skarels 	 * to simplify trap processing.
8345880Swilliam 	 */
8447543Skarels 	p = &proc0;
8547543Skarels 	curproc = p;
8645724Smckusick 	/*
8747543Skarels 	 * Attempt to find console and initialize
8847543Skarels 	 * in case of early panic or other messages.
8945724Smckusick 	 */
9047543Skarels 	consinit();
9149382Skarels 	printf(copyright);
9247543Skarels 
9345724Smckusick 	vm_mem_init();
9445724Smckusick 	kmeminit();
9549533Skarels 	cpu_startup();
9626Sbill 
9726Sbill 	/*
9826Sbill 	 * set up system process 0 (swapper)
9926Sbill 	 */
10047543Skarels 	p = &proc0;
10147543Skarels 	curproc = p;
10247543Skarels 
10354781Storek 	allproc = (volatile struct proc *)p;
10454781Storek 	p->p_prev = (struct proc **)&allproc;
10547543Skarels 	p->p_pgrp = &pgrp0;
10647543Skarels 	pgrphash[0] = &pgrp0;
10747543Skarels 	pgrp0.pg_mem = p;
10847543Skarels 	pgrp0.pg_session = &session0;
10947543Skarels 	session0.s_count = 1;
11047543Skarels 	session0.s_leader = p;
11147543Skarels 
11247543Skarels 	p->p_flag = SLOAD|SSYS;
1132451Swnj 	p->p_stat = SRUN;
1142451Swnj 	p->p_nice = NZERO;
11547543Skarels 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
11647543Skarels 
11745724Smckusick 	/*
11847543Skarels 	 * Setup credentials
11945724Smckusick 	 */
12049745Smckusick 	cred0.p_refcnt = 1;
12147543Skarels 	p->p_cred = &cred0;
12247543Skarels 	p->p_ucred = crget();
12347543Skarels 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
12429946Skarels 
12545914Smckusick 	/*
12645914Smckusick 	 * Create the file descriptor table for process 0.
12745914Smckusick 	 */
12847543Skarels 	fdp = &filedesc0;
12947654Skarels 	p->p_fd = &fdp->fd_fd;
13047654Skarels 	fdp->fd_fd.fd_refcnt = 1;
13147654Skarels 	fdp->fd_fd.fd_cmask = cmask;
13247654Skarels 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
13347654Skarels 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
13447654Skarels 	fdp->fd_fd.fd_nfiles = NDFILE;
13547543Skarels 
13618278Smckusick 	/*
13747543Skarels 	 * Set initial limits
13847543Skarels 	 */
13947543Skarels 	p->p_limit = &limit0;
14047543Skarels 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
14147543Skarels 		limit0.pl_rlimit[i].rlim_cur =
14247543Skarels 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
143*56935Smckusick 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
14447543Skarels 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
14547543Skarels 	limit0.p_refcnt = 1;
14647543Skarels 
14747543Skarels 	/*
14847543Skarels 	 * Allocate a prototype map so we have something to fork
14947543Skarels 	 */
15047543Skarels 	p->p_vmspace = &vmspace0;
15147543Skarels 	vmspace0.vm_refcnt = 1;
15247543Skarels 	pmap_pinit(&vmspace0.vm_pmap);
15347543Skarels 	vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS),
15447543Skarels 	    trunc_page(VM_MAX_ADDRESS), TRUE);
15547543Skarels 	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
15647543Skarels 	p->p_addr = proc0paddr;				/* XXX */
15747543Skarels 
15847543Skarels 	/*
15947543Skarels 	 * We continue to place resource usage info
16047543Skarels 	 * and signal actions in the user struct so they're pageable.
16147543Skarels 	 */
16248981Skarels 	p->p_stats = &p->p_addr->u_stats;
16348981Skarels 	p->p_sigacts = &p->p_addr->u_sigacts;
16447543Skarels 
16555406Smckusick 	/*
16655406Smckusick 	 * Initialize per uid information structure and charge
16755406Smckusick 	 * root for one process.
16855406Smckusick 	 */
16955406Smckusick 	usrinfoinit();
17055406Smckusick 	(void)chgproccnt(0, 1);
17155406Smckusick 
17247543Skarels 	rqinit();
17347543Skarels 
17447543Skarels 	/*
17523534Skarels 	 * configure virtual memory system,
17623534Skarels 	 * set vm rlimits
17718278Smckusick 	 */
17847543Skarels 	vm_init_limits(p);
17923534Skarels 
18037610Smckusick 	/*
18139431Smckusick 	 * Initialize the file systems.
18237610Smckusick 	 */
18339431Smckusick 	vfsinit();
18437610Smckusick 
18554781Storek 	/*
18654781Storek 	 * Start real time and statistics clocks.
18754781Storek 	 */
18854781Storek 	initclocks();
18926Sbill 
19026Sbill 	/*
1914821Swnj 	 * Initialize tables, protocols, and set up well-known inodes.
19226Sbill 	 */
1934821Swnj 	mbinit();
19421103Skarels 	cinit();
19541565Smckusick #ifdef SYSVSHM
19641565Smckusick 	shminit();
19741565Smckusick #endif
19826137Skarels #include "sl.h"
19926137Skarels #if NSL > 0
20026137Skarels 	slattach();			/* XXX */
20126137Skarels #endif
20241565Smckusick #include "loop.h"
2035855Swnj #if NLOOP > 0
2045855Swnj 	loattach();			/* XXX */
2055855Swnj #endif
2069156Ssam 	/*
2079156Ssam 	 * Block reception of incoming packets
2089156Ssam 	 * until protocols have been initialized.
2099156Ssam 	 */
2109156Ssam 	s = splimp();
2115227Swnj 	ifinit();
2128969Sroot 	domaininit();
2139156Ssam 	splx(s);
21447543Skarels 
2157419Sroot #ifdef GPROF
2167419Sroot 	kmstartup();
2177419Sroot #endif
2187189Sroot 
21947543Skarels 	/* kick off timeout driven events by calling first time */
22054781Storek 	roundrobin(NULL);
22154781Storek 	schedcpu(NULL);
2228096Sroot 
22347543Skarels 	/*
22447543Skarels 	 * Set up the root file system and vnode.
22547543Skarels 	 */
22637610Smckusick 	if ((*mountroot)())
22737610Smckusick 		panic("cannot mount root");
22837610Smckusick 	/*
22937610Smckusick 	 * Get vnode for '/'.
23047654Skarels 	 * Setup rootdir and fdp->fd_fd.fd_cdir to point to it.
23137610Smckusick 	 */
23237610Smckusick 	if (VFS_ROOT(rootfs, &rootdir))
23337610Smckusick 		panic("cannot find root vnode");
23447654Skarels 	fdp->fd_fd.fd_cdir = rootdir;
23547654Skarels 	VREF(fdp->fd_fd.fd_cdir);
23637726Smckusick 	VOP_UNLOCK(rootdir);
23747654Skarels 	fdp->fd_fd.fd_rdir = NULL;
23847543Skarels 	swapinit();
23926Sbill 
24026Sbill 	/*
24155796Smckusick 	 * Now can look at time, having had a chance to verify the time
24255796Smckusick 	 * from the file system.  Reset p->p_rtime as it may have been
24355796Smckusick 	 * munched in swtch() after the time got set.
24447543Skarels 	 */
24554943Storek 	p->p_stats->p_start = runtime = mono_time = boottime = time;
24655796Smckusick 	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
24747543Skarels 
24847543Skarels 	/*
24916807Skarels 	 * make init process
25016807Skarels 	 */
25147543Skarels 	siginit(p);
25252504Sbostic 	if (fork(p, NULL, rval))
25347543Skarels 		panic("fork init");
25447543Skarels 	if (rval[1]) {
25549382Skarels 		extern int icode[];		/* user init code */
25649382Skarels 		extern int szicode;		/* size of icode */
25752504Sbostic 		static char initflags[] = "-sf";
25852504Sbostic 		vm_offset_t addr;
25952504Sbostic 		char *ip;
26045724Smckusick 
26147543Skarels 		/*
26252504Sbostic 		 * Now in process 1.  Set init flags into icode, get a minimal
26352504Sbostic 		 * address space, copy out "icode", and return to it to do an
26452504Sbostic 		 * exec of init.
26547543Skarels 		 */
26652504Sbostic 		ip = initflags + 1;
26747543Skarels 		if (boothowto&RB_SINGLE)
26847543Skarels 			*ip++ = 's';
26947543Skarels #ifdef notyet
27047543Skarels 		if (boothowto&RB_FASTBOOT)
27147543Skarels 			*ip++ = 'f';
27247689Skarels #endif
27352504Sbostic 		if (ip == initflags + 1)
27452504Sbostic 			*ip++ = '-';
27547543Skarels 		*ip++ = '\0';
27647543Skarels 
27752505Storek 		addr = VM_MIN_ADDRESS;
27852504Sbostic 		initproc = p = curproc;
27947543Skarels 		if (vm_allocate(&p->p_vmspace->vm_map, &addr,
28047689Skarels 		    round_page(szicode + sizeof(initflags)), FALSE) != 0 ||
28152505Storek 		    addr != VM_MIN_ADDRESS)
28245724Smckusick 			panic("init: couldn't allocate at zero");
28345724Smckusick 
28445724Smckusick 		/* need just enough stack to exec from */
28548981Skarels 		addr = trunc_page(USRSTACK - PAGE_SIZE);
28647543Skarels 		if (vm_allocate(&p->p_vmspace->vm_map, &addr,
28747543Skarels 		    PAGE_SIZE, FALSE) != KERN_SUCCESS)
28847543Skarels 			panic("vm_allocate init stack");
28947543Skarels 		p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
29052505Storek 		(void)copyout((caddr_t)icode, (caddr_t)VM_MIN_ADDRESS,
29152505Storek 		    (u_int)szicode);
29252505Storek 		(void)copyout(initflags, (caddr_t)(VM_MIN_ADDRESS + szicode),
29352505Storek 		    sizeof(initflags));
29447543Skarels 		return;			/* returns to icode */
29516807Skarels 	}
29647543Skarels 
29716807Skarels 	/*
29845724Smckusick 	 * Start up pageout daemon (process 2).
29926Sbill 	 */
30052504Sbostic 	if (fork(p, NULL, rval))
30147543Skarels 		panic("fork pager");
30247543Skarels 	if (rval[1]) {
30347543Skarels 		/*
30447543Skarels 		 * Now in process 2.
30547543Skarels 		 */
30647543Skarels 		p = curproc;
30747543Skarels 		pageproc = p;
30847543Skarels 		p->p_flag |= SLOAD|SSYS;		/* XXX */
30947543Skarels 		bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
31045724Smckusick 		vm_pageout();
3119025Sroot 		/*NOTREACHED*/
31226Sbill 	}
31326Sbill 
31426Sbill 	/*
31526Sbill 	 * enter scheduling loop
31626Sbill 	 */
31726Sbill 	sched();
31826Sbill }
319