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