xref: /csrg-svn/sys/kern/init_main.c (revision 47689)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)init_main.c	7.36 (Berkeley) 03/31/91
7  */
8 
9 #include "param.h"
10 #include "filedesc.h"
11 #include "kernel.h"
12 #include "mount.h"
13 #include "map.h"
14 #include "proc.h"
15 #include "resourcevar.h"
16 #include "signalvar.h"
17 #include "systm.h"
18 #include "vnode.h"
19 #include "seg.h"
20 #include "conf.h"
21 #include "buf.h"
22 #include "clist.h"
23 #include "malloc.h"
24 #include "protosw.h"
25 #include "reboot.h"
26 #include "user.h"
27 
28 #include "ufs/quota.h"
29 
30 #include "machine/cpu.h"
31 
32 #include "vm/vm.h"
33 
34 /*
35  * Components of process 0;
36  * never freed.
37  */
38 struct	session session0;
39 struct	pgrp pgrp0;
40 struct	proc proc0;
41 struct	pcred cred0;
42 struct	filedesc0 filedesc0;
43 struct	plimit limit0;
44 struct	vmspace vmspace0;
45 struct	proc *curproc = &proc0;
46 struct	proc *initproc, *pageproc;
47 
48 int	cmask = CMASK;
49 extern	caddr_t proc0paddr;
50 extern	int (*mountroot)();
51 
52 /*
53  * System startup; initialize the world, create process 0,
54  * mount root filesystem, and fork to create init and pagedaemon.
55  * Most of the hard work is done in the lower-level initialization
56  * routines including startup(), which does memory initialization
57  * and autoconfiguration.
58  */
59 main(firstaddr)
60 	int firstaddr;
61 {
62 	register int i;
63 	register struct proc *p;
64 	register struct filedesc0 *fdp;
65 	int s, rval[2];
66 
67 	/*
68 	 * Initialize curproc before any possible traps/probes
69 	 * to simplify trap processing.
70 	 */
71 	p = &proc0;
72 	curproc = p;
73 	/*
74 	 * Attempt to find console and initialize
75 	 * in case of early panic or other messages.
76 	 */
77 	consinit();
78 
79 	vm_mem_init();
80 	kmeminit();
81 	startup(firstaddr);
82 
83 	/*
84 	 * set up system process 0 (swapper)
85 	 */
86 	p = &proc0;
87 	curproc = p;
88 
89 	allproc = p;
90 	p->p_prev = &allproc;
91 	p->p_pgrp = &pgrp0;
92 	pgrphash[0] = &pgrp0;
93 	pgrp0.pg_mem = p;
94 	pgrp0.pg_session = &session0;
95 	session0.s_count = 1;
96 	session0.s_leader = p;
97 
98 	p->p_flag = SLOAD|SSYS;
99 	p->p_stat = SRUN;
100 	p->p_nice = NZERO;
101 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
102 
103 	/*
104 	 * Setup credentials
105 	 */
106 	p->p_cred = &cred0;
107 	p->p_ucred = crget();
108 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
109 
110 	/*
111 	 * Create the file descriptor table for process 0.
112 	 */
113 	fdp = &filedesc0;
114 	p->p_fd = &fdp->fd_fd;
115 	fdp->fd_fd.fd_refcnt = 1;
116 	fdp->fd_fd.fd_cmask = cmask;
117 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
118 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
119 	fdp->fd_fd.fd_nfiles = NDFILE;
120 
121 	/*
122 	 * Set initial limits
123 	 */
124 	p->p_limit = &limit0;
125 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
126 		limit0.pl_rlimit[i].rlim_cur =
127 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
128 	limit0.pl_rlimit[RLIMIT_OFILE].rlim_cur = NOFILE;
129 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
130 	limit0.p_refcnt = 1;
131 
132 	/*
133 	 * Allocate a prototype map so we have something to fork
134 	 */
135 	p->p_vmspace = &vmspace0;
136 	vmspace0.vm_refcnt = 1;
137 	pmap_pinit(&vmspace0.vm_pmap);
138 	vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS),
139 	    trunc_page(VM_MAX_ADDRESS), TRUE);
140 	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
141 	p->p_addr = proc0paddr;				/* XXX */
142 
143 	/*
144 	 * We continue to place resource usage info
145 	 * and signal actions in the user struct so they're pageable.
146 	 */
147 	p->p_stats = &((struct user *)p->p_addr)->u_stats;
148 	p->p_sigacts = &((struct user *)p->p_addr)->u_sigacts;
149 
150 	rqinit();
151 
152 	/*
153 	 * configure virtual memory system,
154 	 * set vm rlimits
155 	 */
156 	vm_init_limits(p);
157 
158 	/*
159 	 * Initialize the file systems.
160 	 *
161 	 * Get vnodes for swapdev, argdev, and rootdev.
162 	 */
163 	vfsinit();
164 	if (bdevvp(swapdev, &swapdev_vp) ||
165 	    bdevvp(argdev, &argdev_vp) ||
166 	    bdevvp(rootdev, &rootvp))
167 		panic("can't setup bdevvp's");
168 
169 	startrtclock();
170 #if defined(vax)
171 #include "kg.h"
172 #if NKG > 0
173 	startkgclock();
174 #endif
175 #endif
176 
177 	/*
178 	 * Initialize tables, protocols, and set up well-known inodes.
179 	 */
180 	mbinit();
181 	cinit();
182 #ifdef SYSVSHM
183 	shminit();
184 #endif
185 #include "sl.h"
186 #if NSL > 0
187 	slattach();			/* XXX */
188 #endif
189 #include "loop.h"
190 #if NLOOP > 0
191 	loattach();			/* XXX */
192 #endif
193 	/*
194 	 * Block reception of incoming packets
195 	 * until protocols have been initialized.
196 	 */
197 	s = splimp();
198 	ifinit();
199 	domaininit();
200 	splx(s);
201 
202 #ifdef GPROF
203 	kmstartup();
204 #endif
205 
206 	/* kick off timeout driven events by calling first time */
207 	roundrobin();
208 	schedcpu();
209 	enablertclock();		/* enable realtime clock interrupts */
210 
211 	/*
212 	 * Set up the root file system and vnode.
213 	 */
214 	if ((*mountroot)())
215 		panic("cannot mount root");
216 	/*
217 	 * Get vnode for '/'.
218 	 * Setup rootdir and fdp->fd_fd.fd_cdir to point to it.
219 	 */
220 	if (VFS_ROOT(rootfs, &rootdir))
221 		panic("cannot find root vnode");
222 	fdp->fd_fd.fd_cdir = rootdir;
223 	VREF(fdp->fd_fd.fd_cdir);
224 	VOP_UNLOCK(rootdir);
225 	fdp->fd_fd.fd_rdir = NULL;
226 	swapinit();
227 
228 	/*
229 	 * Now can look at time, having had a chance
230 	 * to verify the time from the file system.
231 	 */
232 	boottime = p->p_stats->p_start = time;
233 
234 	/*
235 	 * make init process
236 	 */
237 	siginit(p);
238 	if (fork(p, (void *) NULL, rval))
239 		panic("fork init");
240 	if (rval[1]) {
241 		static char initflags[] = "-sf";
242 		char *ip = initflags + 1;
243 		vm_offset_t addr = 0;
244 
245 		/*
246 		 * Now in process 1.  Set init flags into icode,
247 		 * get a minimal address space, copy out "icode",
248 		 * and return to it to do an exec of init.
249 		 */
250 		p = curproc;
251 		initproc = p;
252 		if (boothowto&RB_SINGLE)
253 			*ip++ = 's';
254 #ifdef notyet
255 		if (boothowto&RB_FASTBOOT)
256 			*ip++ = 'f';
257 #endif
258 		*ip++ = '\0';
259 
260 		if (vm_allocate(&p->p_vmspace->vm_map, &addr,
261 		    round_page(szicode + sizeof(initflags)), FALSE) != 0 ||
262 		    addr != 0)
263 			panic("init: couldn't allocate at zero");
264 
265 		/* need just enough stack to exec from */
266 		addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE);
267 		if (vm_allocate(&p->p_vmspace->vm_map, &addr,
268 		    PAGE_SIZE, FALSE) != KERN_SUCCESS)
269 			panic("vm_allocate init stack");
270 		p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
271 		(void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode);
272 		(void) copyout(initflags, (caddr_t)szicode, sizeof(initflags));
273 		return;			/* returns to icode */
274 	}
275 
276 	/*
277 	 * Start up pageout daemon (process 2).
278 	 */
279 	if (fork(p, (void *) NULL, rval))
280 		panic("fork pager");
281 	if (rval[1]) {
282 		/*
283 		 * Now in process 2.
284 		 */
285 		p = curproc;
286 		pageproc = p;
287 		p->p_flag |= SLOAD|SSYS;		/* XXX */
288 		bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
289 		vm_pageout();
290 		/*NOTREACHED*/
291 	}
292 
293 	/*
294 	 * enter scheduling loop
295 	 */
296 	sched();
297 }
298 
299 /* MOVE TO vfs_bio.c (bufinit) XXX */
300 /*
301  * Initialize buffers and hash links for buffers.
302  */
303 bufinit()
304 {
305 	register int i;
306 	register struct buf *bp, *dp;
307 	register struct bufhd *hp;
308 	int base, residual;
309 
310 	for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++)
311 		hp->b_forw = hp->b_back = (struct buf *)hp;
312 
313 	for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) {
314 		dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp;
315 		dp->b_flags = B_HEAD;
316 	}
317 	base = bufpages / nbuf;
318 	residual = bufpages % nbuf;
319 	for (i = 0; i < nbuf; i++) {
320 		bp = &buf[i];
321 		bp->b_dev = NODEV;
322 		bp->b_bcount = 0;
323 		bp->b_rcred = NOCRED;
324 		bp->b_wcred = NOCRED;
325 		bp->b_dirtyoff = 0;
326 		bp->b_dirtyend = 0;
327 		bp->b_un.b_addr = buffers + i * MAXBSIZE;
328 		if (i < residual)
329 			bp->b_bufsize = (base + 1) * CLBYTES;
330 		else
331 			bp->b_bufsize = base * CLBYTES;
332 		binshash(bp, &bfreelist[BQ_AGE]);
333 		bp->b_flags = B_BUSY|B_INVAL;
334 		brelse(bp);
335 	}
336 }
337