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