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