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