init_main.c revision 1.156 1 /* $NetBSD: init_main.c,v 1.156 1999/09/17 20:11:56 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
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.16 (Berkeley) 5/14/95
42 */
43
44 #include "fs_nfs.h"
45 #include "opt_nfsserver.h"
46 #include "opt_sysv.h"
47
48 #include "rnd.h"
49
50 #include <sys/param.h>
51 #include <sys/filedesc.h>
52 #include <sys/file.h>
53 #include <sys/errno.h>
54 #include <sys/exec.h>
55 #include <sys/kernel.h>
56 #include <sys/mount.h>
57 #include <sys/map.h>
58 #include <sys/proc.h>
59 #include <sys/kthread.h>
60 #include <sys/resourcevar.h>
61 #include <sys/signalvar.h>
62 #include <sys/systm.h>
63 #include <sys/vnode.h>
64 #include <sys/tty.h>
65 #include <sys/conf.h>
66 #include <sys/disklabel.h>
67 #include <sys/buf.h>
68 #include <sys/device.h>
69 #include <sys/socketvar.h>
70 #include <sys/protosw.h>
71 #include <sys/reboot.h>
72 #include <sys/user.h>
73 #ifdef SYSVSHM
74 #include <sys/shm.h>
75 #endif
76 #ifdef SYSVSEM
77 #include <sys/sem.h>
78 #endif
79 #ifdef SYSVMSG
80 #include <sys/msg.h>
81 #endif
82 #include <sys/domain.h>
83 #include <sys/mbuf.h>
84 #include <sys/namei.h>
85 #if NRND > 0
86 #include <sys/rnd.h>
87 #endif
88
89 #include <sys/syscall.h>
90 #include <sys/syscallargs.h>
91
92 #include <ufs/ufs/quota.h>
93
94 #include <machine/cpu.h>
95
96 #include <vm/vm.h>
97 #include <vm/vm_pageout.h>
98
99 #include <uvm/uvm.h>
100
101 #include <net/if.h>
102 #include <net/raw_cb.h>
103
104 char copyright[] = "\
105 Copyright (c) 1996, 1997, 1998, 1999
106 The NetBSD Foundation, Inc. All rights reserved.
107 Copyright (c) 1982, 1986, 1989, 1991, 1993
108 The Regents of the University of California. All rights reserved.
109
110 ";
111
112 /* Components of the first process -- never freed. */
113 struct session session0;
114 struct pgrp pgrp0;
115 struct proc proc0;
116 struct pcred cred0;
117 struct filedesc0 filedesc0;
118 struct cwdinfo cwdi0;
119 struct plimit limit0;
120 struct vmspace vmspace0;
121 struct sigacts sigacts0;
122 #ifndef curproc
123 struct proc *curproc = &proc0;
124 #endif
125 struct proc *initproc;
126
127 int cmask = CMASK;
128 extern struct user *proc0paddr;
129
130 struct vnode *rootvp, *swapdev_vp;
131 int boothowto;
132 int cold = 1; /* still working on startup */
133 struct timeval boottime;
134 struct timeval runtime;
135
136 static void check_console __P((struct proc *p));
137 static void start_init __P((void *));
138 static void start_pagedaemon __P((void *));
139 static void start_reaper __P((void *));
140 void main __P((void));
141
142 extern char sigcode[], esigcode[];
143 #ifdef SYSCALL_DEBUG
144 extern char *syscallnames[];
145 #endif
146
147 struct emul emul_netbsd = {
148 "netbsd",
149 NULL,
150 sendsig,
151 SYS_syscall,
152 SYS_MAXSYSCALL,
153 sysent,
154 #ifdef SYSCALL_DEBUG
155 syscallnames,
156 #else
157 NULL,
158 #endif
159 0,
160 copyargs,
161 setregs,
162 sigcode,
163 esigcode,
164 };
165
166 /*
167 * System startup; initialize the world, create process 0, mount root
168 * filesystem, and fork to create init and pagedaemon. Most of the
169 * hard work is done in the lower-level initialization routines including
170 * startup(), which does memory initialization and autoconfiguration.
171 */
172 void
173 main()
174 {
175 struct proc *p;
176 struct pdevinit *pdev;
177 int i, s, error;
178 extern struct pdevinit pdevinit[];
179 extern void roundrobin __P((void *));
180 extern void schedcpu __P((void *));
181 extern void disk_init __P((void));
182 #if defined(NFSSERVER) || defined(NFS)
183 extern void nfs_init __P((void));
184 #endif
185
186 /*
187 * Initialize the current process pointer (curproc) before
188 * any possible traps/probes to simplify trap processing.
189 */
190 p = &proc0;
191 curproc = p;
192 /*
193 * Attempt to find console and initialize
194 * in case of early panic or other messages.
195 */
196 consinit();
197 printf("%s", copyright);
198
199 uvm_init();
200
201 /* Do machine-dependent initialization. */
202 cpu_startup();
203
204 /*
205 * Initialize mbuf's. Do this now because we might attempt to
206 * allocate mbufs or mbuf clusters during autoconfiguration.
207 */
208 mbinit();
209
210 /* Initialize sockets. */
211 soinit();
212
213 /*
214 * The following 3 things must be done before autoconfiguration.
215 */
216 disk_init(); /* initialize disk list */
217 tty_init(); /* initialize tty list */
218 #if NRND > 0
219 rnd_init(); /* initialize RNG */
220 #endif
221
222 /*
223 * Initialize process and pgrp structures.
224 */
225 procinit();
226
227 /*
228 * Create process 0 (the swapper).
229 */
230 s = proclist_lock_write();
231 LIST_INSERT_HEAD(&allproc, p, p_list);
232 proclist_unlock_write(s);
233
234 p->p_pgrp = &pgrp0;
235 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
236 LIST_INIT(&pgrp0.pg_members);
237 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
238
239 pgrp0.pg_session = &session0;
240 session0.s_count = 1;
241 session0.s_sid = p->p_pid;
242 session0.s_leader = p;
243
244 /*
245 * Set P_NOCLDWAIT so that kernel threads are reparented to
246 * init(8) when they exit. init(8) can easily wait them out
247 * for us.
248 */
249 p->p_flag = P_INMEM | P_SYSTEM | P_NOCLDWAIT;
250 p->p_stat = SRUN;
251 p->p_nice = NZERO;
252 p->p_emul = &emul_netbsd;
253 strncpy(p->p_comm, "swapper", MAXCOMLEN);
254
255 /* Create credentials. */
256 cred0.p_refcnt = 1;
257 p->p_cred = &cred0;
258 p->p_ucred = crget();
259 p->p_ucred->cr_ngroups = 1; /* group 0 */
260
261 /* Create the file descriptor table. */
262 finit();
263 p->p_fd = &filedesc0.fd_fd;
264 fdinit1(&filedesc0);
265
266 /* Create the CWD info. */
267 p->p_cwdi = &cwdi0;
268 cwdi0.cwdi_cmask = cmask;
269 cwdi0.cwdi_refcnt = 1;
270
271 /* Create the limits structures. */
272 p->p_limit = &limit0;
273 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
274 limit0.pl_rlimit[i].rlim_cur =
275 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
276
277 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
278 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur =
279 maxfiles < NOFILE ? maxfiles : NOFILE;
280
281 limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
282 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur =
283 maxproc < MAXUPRC ? maxproc : MAXUPRC;
284
285 i = ptoa(uvmexp.free);
286 limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
287 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
288 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
289 limit0.p_refcnt = 1;
290
291 /*
292 * Initialize proc0's vmspace, which uses the kernel pmap.
293 * All kernel processes (which never have user space mappings)
294 * share proc0's vmspace, and thus, the kernel pmap.
295 */
296 uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
297 trunc_page(VM_MAX_ADDRESS), TRUE);
298 p->p_vmspace = &vmspace0;
299
300 p->p_addr = proc0paddr; /* XXX */
301
302 /*
303 * We continue to place resource usage info in the
304 * user struct so they're pageable.
305 */
306 p->p_stats = &p->p_addr->u_stats;
307
308 /*
309 * Charge root for one process.
310 */
311 (void)chgproccnt(0, 1);
312
313 rqinit();
314
315 /* Configure virtual memory system, set vm rlimits. */
316 uvm_init_limits(p);
317
318 /* Initialize the file systems. */
319 #if defined(NFSSERVER) || defined(NFS)
320 nfs_init(); /* initialize server/shared data */
321 #endif
322 vfsinit();
323
324 /* Configure the system hardware. This will enable interrupts. */
325 configure();
326
327 #ifdef SYSVSHM
328 /* Initialize System V style shared memory. */
329 shminit();
330 #endif
331
332 #ifdef SYSVSEM
333 /* Initialize System V style semaphores. */
334 seminit();
335 #endif
336
337 #ifdef SYSVMSG
338 /* Initialize System V style message queues. */
339 msginit();
340 #endif
341
342 /* Attach pseudo-devices. */
343 for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
344 (*pdev->pdev_attach)(pdev->pdev_count);
345
346 /*
347 * Initialize protocols. Block reception of incoming packets
348 * until everything is ready.
349 */
350 s = splimp();
351 ifinit();
352 domaininit();
353 splx(s);
354
355 #ifdef GPROF
356 /* Initialize kernel profiling. */
357 kmstartup();
358 #endif
359
360 /* Kick off timeout driven events by calling first time. */
361 roundrobin(NULL);
362 schedcpu(NULL);
363
364 /* Determine the root and dump devices. */
365 cpu_rootconf();
366 cpu_dumpconf();
367
368 /* Mount the root file system. */
369 do {
370 domountroothook();
371 if ((error = vfs_mountroot())) {
372 printf("cannot mount root, error = %d\n", error);
373 boothowto |= RB_ASKNAME;
374 setroot(root_device,
375 (rootdev != NODEV) ? DISKPART(rootdev) : 0);
376 }
377 } while (error != 0);
378 mountroothook_destroy();
379
380 mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
381 mountlist.cqh_first->mnt_op->vfs_refcount++;
382
383 /*
384 * Get the vnode for '/'. Set filedesc0.fd_fd.fd_cdir to
385 * reference it.
386 */
387 if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
388 panic("cannot find root vnode");
389 cwdi0.cwdi_cdir = rootvnode;
390 VREF(cwdi0.cwdi_cdir);
391 VOP_UNLOCK(rootvnode, 0);
392 cwdi0.cwdi_rdir = NULL;
393 uvm_swap_init();
394
395 /*
396 * Now can look at time, having had a chance to verify the time
397 * from the file system. Reset p->p_rtime as it may have been
398 * munched in mi_switch() after the time got set.
399 */
400 p->p_stats->p_start = runtime = mono_time = boottime = time;
401 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
402
403 /*
404 * Initialize signal-related data structures, and signal state
405 * for proc0.
406 */
407 signal_init();
408 p->p_sigacts = &sigacts0;
409 siginit(p);
410
411 /* Create process 1 (init(8)). */
412 if (fork1(p, 0, SIGCHLD, NULL, 0, NULL, &initproc))
413 panic("fork init");
414 cpu_set_kpc(initproc, start_init, initproc);
415
416 /* Create process 2, the pageout daemon kernel thread. */
417 if (kthread_create1(start_pagedaemon, NULL, NULL, "pagedaemon"))
418 panic("fork pagedaemon");
419
420 /* Create process 3, the process reaper kernel thread. */
421 if (kthread_create1(start_reaper, NULL, NULL, "reaper"))
422 panic("fork reaper");
423
424 /* Create any other deferred kernel threads. */
425 kthread_run_deferred_queue();
426
427 /* The scheduler is an infinite loop. */
428 uvm_scheduler();
429 /* NOTREACHED */
430 }
431
432 static void
433 check_console(p)
434 struct proc *p;
435 {
436 struct nameidata nd;
437 int error;
438
439 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
440 error = namei(&nd);
441 if (error == 0)
442 vrele(nd.ni_vp);
443 else if (error == ENOENT)
444 printf("warning: no /dev/console\n");
445 else
446 printf("warning: lookup /dev/console: error %d\n", error);
447 }
448
449 /*
450 * List of paths to try when searching for "init".
451 */
452 static char *initpaths[] = {
453 "/sbin/init",
454 "/sbin/oinit",
455 "/sbin/init.bak",
456 NULL,
457 };
458
459 /*
460 * Start the initial user process; try exec'ing each pathname in "initpaths".
461 * The program is invoked with one argument containing the boot flags.
462 */
463 static void
464 start_init(arg)
465 void *arg;
466 {
467 struct proc *p = arg;
468 vaddr_t addr;
469 struct sys_execve_args /* {
470 syscallarg(const char *) path;
471 syscallarg(char * const *) argp;
472 syscallarg(char * const *) envp;
473 } */ args;
474 int options, i, error;
475 register_t retval[2];
476 char flags[4], *flagsp;
477 char **pathp, *path, *slash, *ucp, **uap, *arg0, *arg1 = NULL;
478
479 /*
480 * Now in process 1.
481 */
482 strncpy(p->p_comm, "init", MAXCOMLEN);
483
484 /*
485 * This is not the right way to do this. We really should
486 * hand-craft a descriptor onto /dev/console to hand to init,
487 * but that's a _lot_ more work, and the benefit from this easy
488 * hack makes up for the "good is the enemy of the best" effect.
489 */
490 check_console(p);
491
492 /*
493 * Need just enough stack to hold the faked-up "execve()" arguments.
494 */
495 addr = USRSTACK - PAGE_SIZE;
496 if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
497 NULL, UVM_UNKNOWN_OFFSET,
498 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
499 UVM_ADV_NORMAL,
500 UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
501 != KERN_SUCCESS)
502 panic("init: couldn't allocate argument space");
503 p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
504
505 for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
506 ucp = (char *)(addr + PAGE_SIZE);
507
508 /*
509 * Construct the boot flag argument.
510 */
511 flagsp = flags;
512 *flagsp++ = '-';
513 options = 0;
514
515 if (boothowto & RB_SINGLE) {
516 *flagsp++ = 's';
517 options = 1;
518 }
519 #ifdef notyet
520 if (boothowto & RB_FASTBOOT) {
521 *flagsp++ = 'f';
522 options = 1;
523 }
524 #endif
525
526 /*
527 * Move out the flags (arg 1), if necessary.
528 */
529 if (options != 0) {
530 *flagsp++ = '\0';
531 i = flagsp - flags;
532 #ifdef DEBUG
533 printf("init: copying out flags `%s' %d\n", flags, i);
534 #endif
535 (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
536 arg1 = ucp;
537 }
538
539 /*
540 * Move out the file name (also arg 0).
541 */
542 i = strlen(path) + 1;
543 #ifdef DEBUG
544 printf("init: copying out path `%s' %d\n", path, i);
545 #endif
546 (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
547 arg0 = ucp;
548
549 /*
550 * Move out the arg pointers.
551 */
552 uap = (char **)((long)ucp & ~ALIGNBYTES);
553 (void)suword((caddr_t)--uap, 0); /* terminator */
554 if (options != 0)
555 (void)suword((caddr_t)--uap, (long)arg1);
556 slash = strrchr(path, '/');
557 if (slash)
558 (void)suword((caddr_t)--uap,
559 (long)arg0 + (slash + 1 - path));
560 else
561 (void)suword((caddr_t)--uap, (long)arg0);
562
563 /*
564 * Point at the arguments.
565 */
566 SCARG(&args, path) = arg0;
567 SCARG(&args, argp) = uap;
568 SCARG(&args, envp) = NULL;
569
570 /*
571 * Now try to exec the program. If can't for any reason
572 * other than it doesn't exist, complain.
573 */
574 error = sys_execve(p, &args, retval);
575 if (error == 0 || error == EJUSTRETURN)
576 return;
577 if (error != ENOENT)
578 printf("exec %s: error %d\n", path, error);
579 }
580 printf("init: not found\n");
581 panic("no init");
582 }
583
584 /* ARGSUSED */
585 static void
586 start_pagedaemon(arg)
587 void *arg;
588 {
589
590 uvm_pageout();
591 /* NOTREACHED */
592 }
593
594 /* ARGSUSED */
595 static void
596 start_reaper(arg)
597 void *arg;
598 {
599
600 reaper();
601 /* NOTREACHED */
602 }
603