init_main.c revision 1.157 1 /* $NetBSD: init_main.c,v 1.157 1999/09/28 14:47:03 bouyer 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.pl_corename = defcorename;
290 limit0.p_refcnt = 1;
291
292 /*
293 * Initialize proc0's vmspace, which uses the kernel pmap.
294 * All kernel processes (which never have user space mappings)
295 * share proc0's vmspace, and thus, the kernel pmap.
296 */
297 uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
298 trunc_page(VM_MAX_ADDRESS), TRUE);
299 p->p_vmspace = &vmspace0;
300
301 p->p_addr = proc0paddr; /* XXX */
302
303 /*
304 * We continue to place resource usage info in the
305 * user struct so they're pageable.
306 */
307 p->p_stats = &p->p_addr->u_stats;
308
309 /*
310 * Charge root for one process.
311 */
312 (void)chgproccnt(0, 1);
313
314 rqinit();
315
316 /* Configure virtual memory system, set vm rlimits. */
317 uvm_init_limits(p);
318
319 /* Initialize the file systems. */
320 #if defined(NFSSERVER) || defined(NFS)
321 nfs_init(); /* initialize server/shared data */
322 #endif
323 vfsinit();
324
325 /* Configure the system hardware. This will enable interrupts. */
326 configure();
327
328 #ifdef SYSVSHM
329 /* Initialize System V style shared memory. */
330 shminit();
331 #endif
332
333 #ifdef SYSVSEM
334 /* Initialize System V style semaphores. */
335 seminit();
336 #endif
337
338 #ifdef SYSVMSG
339 /* Initialize System V style message queues. */
340 msginit();
341 #endif
342
343 /* Attach pseudo-devices. */
344 for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
345 (*pdev->pdev_attach)(pdev->pdev_count);
346
347 /*
348 * Initialize protocols. Block reception of incoming packets
349 * until everything is ready.
350 */
351 s = splimp();
352 ifinit();
353 domaininit();
354 splx(s);
355
356 #ifdef GPROF
357 /* Initialize kernel profiling. */
358 kmstartup();
359 #endif
360
361 /* Kick off timeout driven events by calling first time. */
362 roundrobin(NULL);
363 schedcpu(NULL);
364
365 /* Determine the root and dump devices. */
366 cpu_rootconf();
367 cpu_dumpconf();
368
369 /* Mount the root file system. */
370 do {
371 domountroothook();
372 if ((error = vfs_mountroot())) {
373 printf("cannot mount root, error = %d\n", error);
374 boothowto |= RB_ASKNAME;
375 setroot(root_device,
376 (rootdev != NODEV) ? DISKPART(rootdev) : 0);
377 }
378 } while (error != 0);
379 mountroothook_destroy();
380
381 mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
382 mountlist.cqh_first->mnt_op->vfs_refcount++;
383
384 /*
385 * Get the vnode for '/'. Set filedesc0.fd_fd.fd_cdir to
386 * reference it.
387 */
388 if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
389 panic("cannot find root vnode");
390 cwdi0.cwdi_cdir = rootvnode;
391 VREF(cwdi0.cwdi_cdir);
392 VOP_UNLOCK(rootvnode, 0);
393 cwdi0.cwdi_rdir = NULL;
394 uvm_swap_init();
395
396 /*
397 * Now can look at time, having had a chance to verify the time
398 * from the file system. Reset p->p_rtime as it may have been
399 * munched in mi_switch() after the time got set.
400 */
401 p->p_stats->p_start = runtime = mono_time = boottime = time;
402 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
403
404 /*
405 * Initialize signal-related data structures, and signal state
406 * for proc0.
407 */
408 signal_init();
409 p->p_sigacts = &sigacts0;
410 siginit(p);
411
412 /* Create process 1 (init(8)). */
413 if (fork1(p, 0, SIGCHLD, NULL, 0, NULL, &initproc))
414 panic("fork init");
415 cpu_set_kpc(initproc, start_init, initproc);
416
417 /* Create process 2, the pageout daemon kernel thread. */
418 if (kthread_create1(start_pagedaemon, NULL, NULL, "pagedaemon"))
419 panic("fork pagedaemon");
420
421 /* Create process 3, the process reaper kernel thread. */
422 if (kthread_create1(start_reaper, NULL, NULL, "reaper"))
423 panic("fork reaper");
424
425 /* Create any other deferred kernel threads. */
426 kthread_run_deferred_queue();
427
428 /* The scheduler is an infinite loop. */
429 uvm_scheduler();
430 /* NOTREACHED */
431 }
432
433 static void
434 check_console(p)
435 struct proc *p;
436 {
437 struct nameidata nd;
438 int error;
439
440 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
441 error = namei(&nd);
442 if (error == 0)
443 vrele(nd.ni_vp);
444 else if (error == ENOENT)
445 printf("warning: no /dev/console\n");
446 else
447 printf("warning: lookup /dev/console: error %d\n", error);
448 }
449
450 /*
451 * List of paths to try when searching for "init".
452 */
453 static char *initpaths[] = {
454 "/sbin/init",
455 "/sbin/oinit",
456 "/sbin/init.bak",
457 NULL,
458 };
459
460 /*
461 * Start the initial user process; try exec'ing each pathname in "initpaths".
462 * The program is invoked with one argument containing the boot flags.
463 */
464 static void
465 start_init(arg)
466 void *arg;
467 {
468 struct proc *p = arg;
469 vaddr_t addr;
470 struct sys_execve_args /* {
471 syscallarg(const char *) path;
472 syscallarg(char * const *) argp;
473 syscallarg(char * const *) envp;
474 } */ args;
475 int options, i, error;
476 register_t retval[2];
477 char flags[4], *flagsp;
478 char **pathp, *path, *slash, *ucp, **uap, *arg0, *arg1 = NULL;
479
480 /*
481 * Now in process 1.
482 */
483 strncpy(p->p_comm, "init", MAXCOMLEN);
484
485 /*
486 * This is not the right way to do this. We really should
487 * hand-craft a descriptor onto /dev/console to hand to init,
488 * but that's a _lot_ more work, and the benefit from this easy
489 * hack makes up for the "good is the enemy of the best" effect.
490 */
491 check_console(p);
492
493 /*
494 * Need just enough stack to hold the faked-up "execve()" arguments.
495 */
496 addr = USRSTACK - PAGE_SIZE;
497 if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
498 NULL, UVM_UNKNOWN_OFFSET,
499 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
500 UVM_ADV_NORMAL,
501 UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
502 != KERN_SUCCESS)
503 panic("init: couldn't allocate argument space");
504 p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
505
506 for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
507 ucp = (char *)(addr + PAGE_SIZE);
508
509 /*
510 * Construct the boot flag argument.
511 */
512 flagsp = flags;
513 *flagsp++ = '-';
514 options = 0;
515
516 if (boothowto & RB_SINGLE) {
517 *flagsp++ = 's';
518 options = 1;
519 }
520 #ifdef notyet
521 if (boothowto & RB_FASTBOOT) {
522 *flagsp++ = 'f';
523 options = 1;
524 }
525 #endif
526
527 /*
528 * Move out the flags (arg 1), if necessary.
529 */
530 if (options != 0) {
531 *flagsp++ = '\0';
532 i = flagsp - flags;
533 #ifdef DEBUG
534 printf("init: copying out flags `%s' %d\n", flags, i);
535 #endif
536 (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
537 arg1 = ucp;
538 }
539
540 /*
541 * Move out the file name (also arg 0).
542 */
543 i = strlen(path) + 1;
544 #ifdef DEBUG
545 printf("init: copying out path `%s' %d\n", path, i);
546 #endif
547 (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
548 arg0 = ucp;
549
550 /*
551 * Move out the arg pointers.
552 */
553 uap = (char **)((long)ucp & ~ALIGNBYTES);
554 (void)suword((caddr_t)--uap, 0); /* terminator */
555 if (options != 0)
556 (void)suword((caddr_t)--uap, (long)arg1);
557 slash = strrchr(path, '/');
558 if (slash)
559 (void)suword((caddr_t)--uap,
560 (long)arg0 + (slash + 1 - path));
561 else
562 (void)suword((caddr_t)--uap, (long)arg0);
563
564 /*
565 * Point at the arguments.
566 */
567 SCARG(&args, path) = arg0;
568 SCARG(&args, argp) = uap;
569 SCARG(&args, envp) = NULL;
570
571 /*
572 * Now try to exec the program. If can't for any reason
573 * other than it doesn't exist, complain.
574 */
575 error = sys_execve(p, &args, retval);
576 if (error == 0 || error == EJUSTRETURN)
577 return;
578 if (error != ENOENT)
579 printf("exec %s: error %d\n", path, error);
580 }
581 printf("init: not found\n");
582 panic("no init");
583 }
584
585 /* ARGSUSED */
586 static void
587 start_pagedaemon(arg)
588 void *arg;
589 {
590
591 uvm_pageout();
592 /* NOTREACHED */
593 }
594
595 /* ARGSUSED */
596 static void
597 start_reaper(arg)
598 void *arg;
599 {
600
601 reaper();
602 /* NOTREACHED */
603 }
604