init_main.c revision 1541
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
39 */
40
41#include <sys/param.h>
42#include <sys/filedesc.h>
43#include <sys/errno.h>
44#include <sys/exec.h>
45#include <sys/kernel.h>
46#include <sys/mount.h>
47#include <sys/map.h>
48#include <sys/proc.h>
49#include <sys/resourcevar.h>
50#include <sys/signalvar.h>
51#include <sys/systm.h>
52#include <sys/vnode.h>
53#include <sys/conf.h>
54#include <sys/buf.h>
55#include <sys/clist.h>
56#include <sys/device.h>
57#include <sys/protosw.h>
58#include <sys/reboot.h>
59#include <sys/user.h>
60
61#include <ufs/ufs/quota.h>
62
63#include <machine/cpu.h>
64
65#include <vm/vm.h>
66
67#ifdef HPFPLIB
68char	copyright[] =
69"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";
70#else
71char	copyright[] =
72"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.  All rights reserved.\n\n";
73#endif
74
75/* Components of the first process -- never freed. */
76struct	session session0;
77struct	pgrp pgrp0;
78struct	proc proc0;
79struct	pcred cred0;
80struct	filedesc0 filedesc0;
81struct	plimit limit0;
82struct	vmspace vmspace0;
83struct	proc *curproc = &proc0;
84struct	proc *initproc, *pageproc;
85
86int	cmask = CMASK;
87extern	struct user *proc0paddr;
88
89struct	vnode *rootvp, *swapdev_vp;
90int	boothowto;
91struct	timeval boottime;
92struct	timeval runtime;
93
94static void start_init __P((struct proc *p, void *framep));
95
96/*
97 * System startup; initialize the world, create process 0, mount root
98 * filesystem, and fork to create init and pagedaemon.  Most of the
99 * hard work is done in the lower-level initialization routines including
100 * startup(), which does memory initialization and autoconfiguration.
101 */
102main(framep)
103	void *framep;
104{
105	register struct proc *p;
106	register struct filedesc0 *fdp;
107	register struct pdevinit *pdev;
108	register int i;
109	int s, rval[2];
110	extern int (*mountroot) __P((void));
111	extern struct pdevinit pdevinit[];
112	extern void roundrobin __P((void *));
113	extern void schedcpu __P((void *));
114
115	/*
116	 * Initialize the current process pointer (curproc) before
117	 * any possible traps/probes to simplify trap processing.
118	 */
119	p = &proc0;
120	curproc = p;
121	/*
122	 * Attempt to find console and initialize
123	 * in case of early panic or other messages.
124	 */
125	consinit();
126	printf(copyright);
127
128	vm_mem_init();
129	kmeminit();
130	cpu_startup();
131
132	/*
133	 * Create process 0 (the swapper).
134	 */
135	allproc = (volatile struct proc *)p;
136	p->p_prev = (struct proc **)&allproc;
137	p->p_pgrp = &pgrp0;
138	pgrphash[0] = &pgrp0;
139	pgrp0.pg_mem = p;
140	pgrp0.pg_session = &session0;
141	session0.s_count = 1;
142	session0.s_leader = p;
143
144	p->p_flag = P_INMEM | P_SYSTEM;
145	p->p_stat = SRUN;
146	p->p_nice = NZERO;
147	bcopy("swapper", p->p_comm, sizeof ("swapper"));
148
149	/* Create credentials. */
150	cred0.p_refcnt = 1;
151	p->p_cred = &cred0;
152	p->p_ucred = crget();
153	p->p_ucred->cr_ngroups = 1;	/* group 0 */
154
155	/* Create the file descriptor table. */
156	fdp = &filedesc0;
157	p->p_fd = &fdp->fd_fd;
158	fdp->fd_fd.fd_refcnt = 1;
159	fdp->fd_fd.fd_cmask = cmask;
160	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
161	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
162	fdp->fd_fd.fd_nfiles = NDFILE;
163
164	/* Create the limits structures. */
165	p->p_limit = &limit0;
166	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
167		limit0.pl_rlimit[i].rlim_cur =
168		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
169	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
170	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
171	i = ptoa(cnt.v_free_count);
172	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
173	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
174	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
175	limit0.p_refcnt = 1;
176
177	/* Allocate a prototype map so we have something to fork. */
178	p->p_vmspace = &vmspace0;
179	vmspace0.vm_refcnt = 1;
180	pmap_pinit(&vmspace0.vm_pmap);
181	vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS),
182	    trunc_page(VM_MAX_ADDRESS), TRUE);
183	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
184	p->p_addr = proc0paddr;				/* XXX */
185
186	/*
187	 * We continue to place resource usage info and signal
188	 * actions in the user struct so they're pageable.
189	 */
190	p->p_stats = &p->p_addr->u_stats;
191	p->p_sigacts = &p->p_addr->u_sigacts;
192
193	/*
194	 * Initialize per uid information structure and charge
195	 * root for one process.
196	 */
197	usrinfoinit();
198	(void)chgproccnt(0, 1);
199
200	rqinit();
201
202	/* Configure virtual memory system, set vm rlimits. */
203	vm_init_limits(p);
204
205	/* Initialize the file systems. */
206	vfsinit();
207
208	/* Start real time and statistics clocks. */
209	initclocks();
210
211	/* Initialize mbuf's. */
212	mbinit();
213
214	/* Initialize clists. */
215	clist_init();
216
217#ifdef SYSVSHM
218	/* Initialize System V style shared memory. */
219	shminit();
220#endif
221
222	/* Attach pseudo-devices. */
223	for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
224		(*pdev->pdev_attach)(pdev->pdev_count);
225
226	/*
227	 * Initialize protocols.  Block reception of incoming packets
228	 * until everything is ready.
229	 */
230	s = splimp();
231	ifinit();
232	domaininit();
233	splx(s);
234
235#ifdef GPROF
236	/* Initialize kernel profiling. */
237	kmstartup();
238#endif
239
240	/* Kick off timeout driven events by calling first time. */
241	roundrobin(NULL);
242	schedcpu(NULL);
243
244	/* Mount the root file system. */
245	if ((*mountroot)())
246		panic("cannot mount root");
247
248	/* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
249	if (VFS_ROOT(mountlist.tqh_first, &rootvnode))
250		panic("cannot find root vnode");
251	fdp->fd_fd.fd_cdir = rootvnode;
252	VREF(fdp->fd_fd.fd_cdir);
253	VOP_UNLOCK(rootvnode);
254	fdp->fd_fd.fd_rdir = NULL;
255	swapinit();
256
257	/*
258	 * Now can look at time, having had a chance to verify the time
259	 * from the file system.  Reset p->p_rtime as it may have been
260	 * munched in mi_switch() after the time got set.
261	 */
262	p->p_stats->p_start = runtime = mono_time = boottime = time;
263	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
264
265	/* Initialize signal state for process 0. */
266	siginit(p);
267
268	/* Create process 1 (init(8)). */
269	if (fork(p, NULL, rval))
270		panic("fork init");
271	if (rval[1]) {
272		start_init(curproc, framep);
273		return;
274	}
275
276	/* Create process 2 (the pageout daemon). */
277	if (fork(p, NULL, rval))
278		panic("fork pager");
279	if (rval[1]) {
280		/*
281		 * Now in process 2.
282		 */
283		p = curproc;
284		pageproc = p;
285		p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
286		bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
287		vm_pageout();
288		/* NOTREACHED */
289	}
290
291	/* The scheduler is an infinite loop. */
292	scheduler();
293	/* NOTREACHED */
294}
295
296/*
297 * List of paths to try when searching for "init".
298 */
299static char *initpaths[] = {
300	"/sbin/init",
301	"/sbin/oinit",
302	"/sbin/init.bak",
303	NULL,
304};
305
306/*
307 * Start the initial user process; try exec'ing each pathname in "initpaths".
308 * The program is invoked with one argument containing the boot flags.
309 */
310static void
311start_init(p, framep)
312	struct proc *p;
313	void *framep;
314{
315	vm_offset_t addr;
316	struct execve_args args;
317	int options, i, retval[2], error;
318	char **pathp, *path, *ucp, **uap, *arg0, *arg1;
319
320	initproc = p;
321
322	/*
323	 * We need to set the system call frame as if we were entered through
324	 * a syscall() so that when we call execve() below, it will be able
325	 * to set the entry point (see setregs) when it tries to exec.  The
326	 * startup code in "locore.s" has allocated space for the frame and
327	 * passed a pointer to that space as main's argument.
328	 */
329	cpu_set_init_frame(p, framep);
330
331	/*
332	 * Need just enough stack to hold the faked-up "execve()" arguments.
333	 */
334	addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE);
335	if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0)
336		panic("init: couldn't allocate argument space");
337	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
338
339	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
340		/*
341		 * Move out the boot flag argument.
342		 */
343		options = 0;
344		ucp = (char *)USRSTACK;
345		(void)subyte(--ucp, 0);		/* trailing zero */
346		if (boothowto & RB_SINGLE) {
347			(void)subyte(--ucp, 's');
348			options = 1;
349		}
350#ifdef notyet
351                if (boothowto & RB_FASTBOOT) {
352			(void)subyte(--ucp, 'f');
353			options = 1;
354		}
355#endif
356		if (options == 0)
357			(void)subyte(--ucp, '-');
358		(void)subyte(--ucp, '-');		/* leading hyphen */
359		arg1 = ucp;
360
361		/*
362		 * Move out the file name (also arg 0).
363		 */
364		for (i = strlen(path) + 1; i >= 0; i--)
365			(void)subyte(--ucp, path[i]);
366		arg0 = ucp;
367
368		/*
369		 * Move out the arg pointers.
370		 */
371		uap = (char **)((int)ucp & ~(NBPW-1));
372		(void)suword((caddr_t)--uap, 0);	/* terminator */
373		(void)suword((caddr_t)--uap, (int)arg1);
374		(void)suword((caddr_t)--uap, (int)arg0);
375
376		/*
377		 * Point at the arguments.
378		 */
379		args.fname = arg0;
380		args.argp = uap;
381		args.envp = NULL;
382
383		/*
384		 * Now try to exec the program.  If can't for any reason
385		 * other than it doesn't exist, complain.
386		 */
387		if ((error = execve(p, &args, &retval)) == 0)
388			return;
389		if (error != ENOENT)
390			printf("exec %s: error %d\n", path, error);
391	}
392	printf("init: not found\n");
393	panic("no init");
394}
395