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