init_main.c revision 1.135 1 /* $NetBSD: init_main.c,v 1.135 1998/11/11 06:34:43 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 #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((void *));
140 static void start_pagedaemon __P((void *));
141 static void start_reaper __P((void *));
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, p2);
419
420 /* Create process 2, the pageout daemon kernel thread. */
421 if (fork_kthread(start_pagedaemon, NULL, NULL, "pagedaemon"))
422 panic("fork pagedaemon");
423
424 /* Create process 3, the process reaper kernel thread. */
425 if (fork_kthread(start_reaper, NULL, NULL, "reaper"))
426 panic("fork reaper");
427
428 /* The scheduler is an infinite loop. */
429 #if defined(UVM)
430 uvm_scheduler();
431 #else
432 scheduler();
433 #endif
434 /* NOTREACHED */
435 }
436
437 static void
438 check_console(p)
439 struct proc *p;
440 {
441 struct nameidata nd;
442 int error;
443
444 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
445 error = namei(&nd);
446 if (error == 0)
447 vrele(nd.ni_vp);
448 else if (error == ENOENT)
449 printf("warning: no /dev/console\n");
450 else
451 printf("warning: lookup /dev/console: error %d\n", error);
452 }
453
454 /*
455 * List of paths to try when searching for "init".
456 */
457 static char *initpaths[] = {
458 "/sbin/init",
459 "/sbin/oinit",
460 "/sbin/init.bak",
461 NULL,
462 };
463
464 /*
465 * Start the initial user process; try exec'ing each pathname in "initpaths".
466 * The program is invoked with one argument containing the boot flags.
467 */
468 static void
469 start_init(arg)
470 void *arg;
471 {
472 struct proc *p = arg;
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 /* ARGSUSED */
591 static void
592 start_pagedaemon(arg)
593 void *arg;
594 {
595
596 #if defined(UVM)
597 uvm_pageout();
598 #else
599 vm_pageout();
600 #endif
601 /* NOTREACHED */
602 }
603
604 /* ARGSUSED */
605 static void
606 start_reaper(arg)
607 void *arg;
608 {
609
610 reaper();
611 /* NOTREACHED */
612 }
613