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