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