xref: /freebsd/sys/kern/init_main.c (revision 8e6b01171e30297084bb0b4457c4183c2746aacc)
1 /*
2  * Copyright (c) 1995 Terrence R. Lambert
3  * All rights reserved.
4  *
5  * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  * (c) UNIX System Laboratories, Inc.
8  * All or some portions of this file are derived from material licensed
9  * to the University of California by American Telephone and Telegraph
10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11  * the permission of UNIX System Laboratories, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *	This product includes software developed by the University of
24  *	California, Berkeley and its contributors.
25  * 4. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
42  * $Id: init_main.c,v 1.30 1995/09/09 18:09:59 davidg Exp $
43  */
44 
45 #include <sys/param.h>
46 #include <sys/filedesc.h>
47 #include <sys/errno.h>
48 #include <sys/exec.h>
49 #include <sys/kernel.h>
50 #ifdef GPROF
51 #include <sys/gmon.h>
52 #endif
53 #include <sys/mount.h>
54 #include <sys/proc.h>
55 #include <sys/resourcevar.h>
56 #include <sys/signalvar.h>
57 #include <sys/systm.h>
58 #include <sys/vnode.h>
59 #include <sys/sysent.h>
60 #include <sys/conf.h>
61 #include <sys/buf.h>
62 #include <sys/clist.h>
63 #include <sys/device.h>
64 #include <sys/msg.h>
65 #include <sys/protosw.h>
66 #include <sys/reboot.h>
67 #include <sys/sem.h>
68 #include <sys/shm.h>
69 #include <sys/user.h>
70 #include <sys/sysproto.h>
71 
72 #include <ufs/ufs/quota.h>
73 
74 #include <machine/cpu.h>
75 
76 #include <vm/vm.h>
77 #include <vm/vm_pageout.h>
78 
79 extern struct linker_set	sysinit_set;	/* XXX */
80 
81 extern void __main __P((void));
82 extern void main __P((void *framep));
83 
84 /* Components of the first process -- never freed. */
85 struct	session session0;
86 struct	pgrp pgrp0;
87 struct	proc proc0;
88 struct	pcred cred0;
89 struct	filedesc0 filedesc0;
90 struct	plimit limit0;
91 struct	vmspace vmspace0;
92 struct	proc *curproc = &proc0;
93 struct	proc *initproc;
94 
95 int	cmask = CMASK;
96 extern	struct user *proc0paddr;
97 
98 struct	vnode *rootvp;
99 int	boothowto;
100 struct	timeval boottime;
101 struct	timeval runtime;
102 
103 /*
104  * Promiscuous argument pass for start_init()
105  *
106  * This is a kludge because we use a return from main() rather than a call
107  * to a new reoutine in locore.s to kick the kernel alive from locore.s.
108  */
109 static void	*init_framep;
110 
111 
112 #if __GNUC__ >= 2
113 void __main() {}
114 #endif
115 
116 
117 /*
118  * This ensures that there is at least one entry so that the sysinit_set
119  * symbol is not undefined.  A sybsystem ID of SI_SUB_DUMMY is never
120  * executed.
121  */
122 SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL)
123 
124 
125 /*
126  * System startup; initialize the world, create process 0, mount root
127  * filesystem, and fork to create init and pagedaemon.  Most of the
128  * hard work is done in the lower-level initialization routines including
129  * startup(), which does memory initialization and autoconfiguration.
130  *
131  * This allows simple addition of new kernel subsystems that require
132  * boot time initialization.  It also allows substitution of subsystem
133  * (for instance, a scheduler, kernel profiler, or VM system) by object
134  * module.  Finally, it allows for optional "kernel threads", like an LFS
135  * cleaner.
136  */
137 void
138 main(framep)
139 	void *framep;
140 {
141 
142 	register struct sysinit **sipp;		/* system initialization*/
143 	register struct sysinit **xipp;		/* interior loop of sort*/
144 	register struct sysinit *save;		/* bubble*/
145 	int			rval[2];	/* SI_TYPE_KTHREAD support*/
146 
147 	/*
148 	 * Save the locore.s frame pointer for start_init().
149 	 */
150 	init_framep = framep;
151 
152 	/*
153 	 * Perform a bubble sort of the system initialization objects by
154 	 * their subsystem (primary key) and order (secondary key).
155 	 *
156 	 * Since some things care about execution order, this is the
157 	 * operation which ensures continued function.
158 	 */
159 	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
160 		for( xipp = sipp + 1; *xipp; xipp++) {
161 			if( (*sipp)->subsystem < (*xipp)->subsystem ||
162 			    ( (*sipp)->subsystem == (*xipp)->subsystem &&
163 			      (*sipp)->order < (*xipp)->order))
164 				continue;	/* skip*/
165 			save = *sipp;
166 			*sipp = *xipp;
167 			*xipp = save;
168 		}
169 	}
170 
171 	/*
172 	 * Traverse the (now) ordered list of system initialization tasks.
173 	 * Perform each task, and continue on to the next task.
174 	 *
175 	 * The last item on the list is expected to be the scheduler,
176 	 * which will not return.
177 	 */
178 	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
179 		if( (*sipp)->subsystem == SI_SUB_DUMMY)
180 			continue;	/* skip dummy task(s)*/
181 
182 		switch( (*sipp)->type) {
183 		case SI_TYPE_DEFAULT:
184 			/* no special processing*/
185 			(*((*sipp)->func))( (*sipp)->udata);
186 			break;
187 
188 		case SI_TYPE_KTHREAD:
189 			/* kernel thread*/
190 			if (fork(&proc0, NULL, rval))
191 				panic("fork kernel process");
192 			if (rval[1]) {
193 				(*((*sipp)->func))( (*sipp)->udata);
194 				/*
195 				 * The call to start "init" returns
196 				 * here after the scheduler has been
197 				 * started, and returns to the caller
198 				 * in i386/i386/locore.s.  This is a
199 				 * necessary part of initialization
200 				 * and is rather non-obvious.
201 				 *
202 				 * No other "kernel threads" should
203 				 * return here.  Call panic() instead.
204 				 */
205 				return;
206 			}
207 			break;
208 
209 		default:
210 			panic( "init_main: unrecognized init type");
211 		}
212 	}
213 
214 	/* NOTREACHED*/
215 }
216 
217 
218 /*
219  * Start a kernel process.  This is called after a fork() call in
220  * main() in the file kern/init_main.c.
221  *
222  * This function is used to start "internal" daemons.
223  */
224 /* ARGSUSED*/
225 void
226 kproc_start(udata)
227 	void *udata;	/* pointer to a 'kproc_desc' ? */
228 {
229 	struct kproc_desc	*kp = (struct kproc_desc *)udata;
230 	struct proc		*p = curproc;
231 
232 	/* save a global descriptor, if desired*/
233 	if( kp->global_procpp != NULL)
234 		*kp->global_procpp	= p;
235 
236 	/* this is a non-swapped system process*/
237 	p->p_flag |= P_INMEM | P_SYSTEM;
238 
239 	/* set up arg0 for 'ps', et al*/
240 	strcpy( p->p_comm, kp->arg0);
241 
242 	/* call the processes' main()...*/
243 	(*kp->func)();
244 
245 	/* NOTREACHED */
246 	panic( "kproc_start: %s", kp->arg0);
247 }
248 
249 
250 /*
251  ***************************************************************************
252  ****
253  **** The following SYSINIT's belong elsewhere, but have not yet
254  **** been moved.
255  ****
256  ***************************************************************************
257  */
258 #ifdef OMIT
259 /*
260  * Handled by vfs_mountroot (bad idea) at this time... should be
261  * done the same as 4.4Lite2.
262  */
263 SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL)
264 #endif	/* OMIT*/
265 
266 /*
267  * Should get its own file...
268  */
269 #ifdef HPFPLIB
270 char	copyright[] =
271 "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";
272 #else
273 char	copyright[] =
274 "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.  All rights reserved.\n\n";
275 #endif
276 static void print_caddr_t __P((void *data));
277 static void
278 print_caddr_t(data)
279 	void *data;
280 {
281 	printf("%s", (char *)data);
282 }
283 SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t,
284 	copyright)
285 
286 
287 /*
288  ***************************************************************************
289  ****
290  **** The two following SYSINT's are proc0 specific glue code.  I am not
291  **** convinced that they can not be safely combined, but their order of
292  **** operation has been maintained as the same as the original init_main.c
293  **** for right now.
294  ****
295  **** These probably belong in init_proc.c or kern_proc.c, since they
296  **** deal with proc0 (the fork template process).
297  ****
298  ***************************************************************************
299  */
300 /* ARGSUSED*/
301 void proc0_init __P((void *udata));
302 void
303 proc0_init(udata)
304 	void *udata;		/* not used*/
305 {
306 	register struct proc		*p;
307 	register struct filedesc0	*fdp;
308 	register int i;
309 
310 	/*
311 	 * Initialize the current process pointer (curproc) before
312 	 * any possible traps/probes to simplify trap processing.
313 	 */
314 	p = &proc0;
315 	curproc = p;			/* XXX redundant*/
316 
317 	/*
318 	 * Create process 0 (the swapper).
319 	 */
320 	allproc = (volatile struct proc *)p;
321 	p->p_prev = (struct proc **)&allproc;
322 	p->p_pgrp = &pgrp0;
323 	pgrphash[0] = &pgrp0;
324 	pgrp0.pg_mem = p;
325 	pgrp0.pg_session = &session0;
326 	session0.s_count = 1;
327 	session0.s_leader = p;
328 
329 	p->p_sysent = &aout_sysvec;
330 
331 	p->p_flag = P_INMEM | P_SYSTEM;
332 	p->p_stat = SRUN;
333 	p->p_nice = NZERO;
334 	p->p_rtprio.type = RTP_PRIO_NORMAL;
335 	p->p_rtprio.prio = 0;
336 
337 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
338 
339 	/* Create credentials. */
340 	cred0.p_refcnt = 1;
341 	p->p_cred = &cred0;
342 	p->p_ucred = crget();
343 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
344 
345 	/* Create the file descriptor table. */
346 	fdp = &filedesc0;
347 	p->p_fd = &fdp->fd_fd;
348 	fdp->fd_fd.fd_refcnt = 1;
349 	fdp->fd_fd.fd_cmask = cmask;
350 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
351 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
352 	fdp->fd_fd.fd_nfiles = NDFILE;
353 
354 	/* Create the limits structures. */
355 	p->p_limit = &limit0;
356 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
357 		limit0.pl_rlimit[i].rlim_cur =
358 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
359 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
360 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
361 	i = ptoa(cnt.v_free_count);
362 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
363 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
364 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
365 	limit0.p_refcnt = 1;
366 
367 	/* Allocate a prototype map so we have something to fork. */
368 	p->p_vmspace = &vmspace0;
369 	vmspace0.vm_refcnt = 1;
370 	pmap_pinit(&vmspace0.vm_pmap);
371 	vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS),
372 	    trunc_page(VM_MAX_ADDRESS), TRUE);
373 	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
374 	p->p_addr = proc0paddr;				/* XXX */
375 
376 #define INCOMPAT_LITES2
377 #ifdef INCOMPAT_LITES2
378 	/*
379 	 * proc0 needs to have a coherent frame base, too.
380 	 * This probably makes the identical call for the init proc
381 	 * that happens later unnecessary since it should inherit
382 	 * it during the fork.
383 	 */
384 	cpu_set_init_frame(p, init_framep);			/* XXX! */
385 #endif	/* INCOMPAT_LITES2*/
386 
387 	/*
388 	 * We continue to place resource usage info and signal
389 	 * actions in the user struct so they're pageable.
390 	 */
391 	p->p_stats = &p->p_addr->u_stats;
392 	p->p_sigacts = &p->p_addr->u_sigacts;
393 
394 	/*
395 	 * Initialize per uid information structure and charge
396 	 * root for one process.
397 	 */
398 	usrinfoinit();
399 	(void)chgproccnt(0, 1);
400 }
401 SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
402 
403 /* ARGSUSED*/
404 void proc0_post __P((void *udata));
405 void
406 proc0_post(udata)
407 	void *udata;		/* not used*/
408 {
409 	/*
410 	 * Now can look at time, having had a chance to verify the time
411 	 * from the file system.  Reset p->p_rtime as it may have been
412 	 * munched in mi_switch() after the time got set.
413 	 */
414 	proc0.p_stats->p_start = runtime = mono_time = boottime = time;
415 	proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0;
416 
417 	/* Initialize signal state for process 0. */
418 	siginit(&proc0);
419 }
420 SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
421 
422 
423 
424 
425 /*
426  ***************************************************************************
427  ****
428  **** The following SYSINIT's and glue code should be moved to the
429  **** respective files on a per subsystem basis.
430  ****
431  ***************************************************************************
432  */
433 /* ARGSUSED*/
434 void sched_setup __P((void *udata));
435 void
436 sched_setup(udata)
437 	void *udata;		/* not used*/
438 {
439 	/* Kick off timeout driven events by calling first time. */
440 	roundrobin(NULL);
441 	schedcpu(NULL);
442 }
443 SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL)
444 
445 /* ARGSUSED*/
446 void xxx_vfs_mountroot __P((void *udata));
447 void
448 xxx_vfs_mountroot(udata)
449 	void *udata;		/* not used*/
450 {
451 	/* Mount the root file system. */
452 	if ((*mountroot)(mountrootvfsops))
453 		panic("cannot mount root");
454 }
455 SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, NULL)
456 
457 /* ARGSUSED*/
458 void xxx_vfs_root_fdtab __P((void *udata));
459 void
460 xxx_vfs_root_fdtab(udata)
461 	void *udata;		/* not used*/
462 {
463 	register struct filedesc0	*fdp = &filedesc0;
464 
465 	/* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
466 	if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
467 		panic("cannot find root vnode");
468 	fdp->fd_fd.fd_cdir = rootvnode;
469 	VREF(fdp->fd_fd.fd_cdir);
470 	VOP_UNLOCK(rootvnode);
471 	fdp->fd_fd.fd_rdir = NULL;
472 }
473 SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL)
474 
475 
476 /*
477  ***************************************************************************
478  ****
479  **** The following code probably belongs in another file, like
480  **** kern/init_init.c.  It is here for two reasons only:
481  ****
482  ****	1)	This code returns to startup the system; this is
483  ****		abnormal for a kernel thread.
484  ****	2)	This code promiscuously uses init_frame
485  ****
486  ***************************************************************************
487  */
488 
489 static void kthread_init __P((void *udata));
490 SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL)
491 
492 
493 static void start_init __P((struct proc *p, void *framep));
494 
495 /* ARGSUSED*/
496 static void
497 kthread_init(udata)
498 	void *udata;		/* not used*/
499 {
500 
501 	/* Create process 1 (init(8)). */
502 	start_init(curproc, init_framep);
503 
504 	/*
505 	 * This is the only kernel thread allowed to return yo the
506 	 * caller!!!
507 	 */
508 	return;
509 }
510 
511 
512 /*
513  * List of paths to try when searching for "init".
514  */
515 static char *initpaths[] = {
516 	"/sbin/init",
517 	"/sbin/oinit",
518 	"/sbin/init.bak",
519 	"/stand/sysinstall",
520 	NULL,
521 };
522 
523 /*
524  * Start the initial user process; try exec'ing each pathname in "initpaths".
525  * The program is invoked with one argument containing the boot flags.
526  */
527 static void
528 start_init(p, framep)
529 	struct proc *p;
530 	void *framep;
531 {
532 	vm_offset_t addr;
533 	struct execve_args args;
534 	int options, i, retval[2], error;
535 	char **pathp, *path, *ucp, **uap, *arg0, *arg1;
536 
537 	initproc = p;
538 
539 	/*
540 	 * We need to set the system call frame as if we were entered through
541 	 * a syscall() so that when we call execve() below, it will be able
542 	 * to set the entry point (see setregs) when it tries to exec.  The
543 	 * startup code in "locore.s" has allocated space for the frame and
544 	 * passed a pointer to that space as main's argument.
545 	 */
546 	cpu_set_init_frame(p, framep);
547 
548 	/*
549 	 * Need just enough stack to hold the faked-up "execve()" arguments.
550 	 */
551 	addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE);
552 	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE) != 0)
553 		panic("init: couldn't allocate argument space");
554 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
555 	p->p_vmspace->vm_ssize = 1;
556 
557 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
558 		/*
559 		 * Move out the boot flag argument.
560 		 */
561 		options = 0;
562 		ucp = (char *)USRSTACK;
563 		(void)subyte(--ucp, 0);		/* trailing zero */
564 		if (boothowto & RB_SINGLE) {
565 			(void)subyte(--ucp, 's');
566 			options = 1;
567 		}
568 #ifdef notyet
569                 if (boothowto & RB_FASTBOOT) {
570 			(void)subyte(--ucp, 'f');
571 			options = 1;
572 		}
573 #endif
574 
575 #ifdef BOOTCDROM
576 		(void)subyte(--ucp, 'C');
577 		options = 1;
578 #endif
579 		if (options == 0)
580 			(void)subyte(--ucp, '-');
581 		(void)subyte(--ucp, '-');		/* leading hyphen */
582 		arg1 = ucp;
583 
584 		/*
585 		 * Move out the file name (also arg 0).
586 		 */
587 		for (i = strlen(path) + 1; i >= 0; i--)
588 			(void)subyte(--ucp, path[i]);
589 		arg0 = ucp;
590 
591 		/*
592 		 * Move out the arg pointers.
593 		 */
594 		uap = (char **)((int)ucp & ~(NBPW-1));
595 		(void)suword((caddr_t)--uap, 0);	/* terminator */
596 		(void)suword((caddr_t)--uap, (int)arg1);
597 		(void)suword((caddr_t)--uap, (int)arg0);
598 
599 		/*
600 		 * Point at the arguments.
601 		 */
602 		args.fname = arg0;
603 		args.argv = uap;
604 		args.envv = NULL;
605 
606 		/*
607 		 * Now try to exec the program.  If can't for any reason
608 		 * other than it doesn't exist, complain.
609 		 *
610 		 * Otherwise return to main() which returns to btext
611 		 * which completes the system startup.
612 		 */
613 		if ((error = execve(p, &args, &retval[0])) == 0)
614 			return;
615 		if (error != ENOENT)
616 			printf("exec %s: error %d\n", path, error);
617 	}
618 	printf("init: not found\n");
619 	panic("no init");
620 }
621