init_main.c revision 1.120 1 /* $NetBSD: init_main.c,v 1.120 1998/03/27 01:52:01 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 /*
265 * Initialize proc0's vmspace, which uses the kernel pmap.
266 * All kernel processes (which never have user space mappings)
267 * share proc0's vmspace, and thus, the kernel pmap.
268 */
269 #if defined(UVM)
270 uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
271 trunc_page(VM_MAX_ADDRESS), TRUE);
272 #else
273 vmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
274 trunc_page(VM_MAX_ADDRESS), TRUE);
275 #endif
276 p->p_vmspace = &vmspace0;
277
278 p->p_addr = proc0paddr; /* XXX */
279
280 /*
281 * We continue to place resource usage info and signal
282 * actions in the user struct so they're pageable.
283 */
284 p->p_stats = &p->p_addr->u_stats;
285 p->p_sigacts = &p->p_addr->u_sigacts;
286
287 /*
288 * Charge root for one process.
289 */
290 (void)chgproccnt(0, 1);
291
292 rqinit();
293
294 /* Configure virtual memory system, set vm rlimits. */
295 #if defined(UVM)
296 uvm_init_limits(p);
297 #else
298 vm_init_limits(p);
299 #endif
300
301 /* Initialize the file systems. */
302 #if defined(NFSSERVER) || defined(NFS)
303 nfs_init(); /* initialize server/shared data */
304 #endif
305 vfsinit();
306
307 /* Start real time and statistics clocks. */
308 initclocks();
309
310 /* Initialize mbuf's. */
311 mbinit();
312
313 #ifdef REAL_CLISTS
314 /* Initialize clists. */
315 clist_init();
316 #endif
317
318 #ifdef SYSVSHM
319 /* Initialize System V style shared memory. */
320 shminit();
321 #endif
322
323 #ifdef SYSVSEM
324 /* Initialize System V style semaphores. */
325 seminit();
326 #endif
327
328 #ifdef SYSVMSG
329 /* Initialize System V style message queues. */
330 msginit();
331 #endif
332
333 /* Attach pseudo-devices. */
334 for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
335 (*pdev->pdev_attach)(pdev->pdev_count);
336
337 /*
338 * Initialize protocols. Block reception of incoming packets
339 * until everything is ready.
340 */
341 s = splimp();
342 ifinit();
343 domaininit();
344 splx(s);
345
346 #ifdef GPROF
347 /* Initialize kernel profiling. */
348 kmstartup();
349 #endif
350
351 /* Kick off timeout driven events by calling first time. */
352 roundrobin(NULL);
353 schedcpu(NULL);
354
355 /* Determine the root and dump devices. */
356 cpu_rootconf();
357 cpu_dumpconf();
358
359 /* Mount the root file system. */
360 do {
361 domountroothook();
362 if ((error = vfs_mountroot())) {
363 printf("cannot mount root, error = %d\n", error);
364 boothowto |= RB_ASKNAME;
365 setroot(root_device,
366 (rootdev != NODEV) ? DISKPART(rootdev) : 0, NULL);
367 }
368 } while (error != 0);
369 mountroothook_destroy();
370
371 mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
372 mountlist.cqh_first->mnt_op->vfs_refcount++;
373
374 /*
375 * Get the vnode for '/'. Set filedesc0.fd_fd.fd_cdir to
376 * reference it.
377 */
378 if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
379 panic("cannot find root vnode");
380 filedesc0.fd_fd.fd_cdir = rootvnode;
381 VREF(filedesc0.fd_fd.fd_cdir);
382 VOP_UNLOCK(rootvnode, 0);
383 filedesc0.fd_fd.fd_rdir = NULL;
384 #if defined(UVM)
385 uvm_swap_init();
386 #else
387 swapinit();
388 #endif
389
390 /*
391 * Now can look at time, having had a chance to verify the time
392 * from the file system. Reset p->p_rtime as it may have been
393 * munched in mi_switch() after the time got set.
394 */
395 p->p_stats->p_start = runtime = mono_time = boottime = time;
396 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
397
398 /* Initialize signal state for process 0. */
399 siginit(p);
400
401 /* Create process 1 (init(8)). */
402 if (fork1(p, 0, NULL, &p2))
403 panic("fork init");
404 cpu_set_kpc(p2, start_init);
405
406 /* Create process 2 (the pageout daemon). */
407 if (fork1(p, FORK_SHAREVM, NULL, &p2))
408 panic("fork pager");
409 cpu_set_kpc(p2, start_pagedaemon);
410
411 /* The scheduler is an infinite loop. */
412 #if defined(UVM)
413 uvm_scheduler();
414 #else
415 scheduler();
416 #endif
417 /* NOTREACHED */
418 }
419
420 static void
421 check_console(p)
422 struct proc *p;
423 {
424 struct nameidata nd;
425 int error;
426
427 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
428 error = namei(&nd);
429 if (error == 0)
430 vrele(nd.ni_vp);
431 else if (error == ENOENT)
432 printf("warning: no /dev/console\n");
433 else
434 printf("warning: lookup /dev/console: error %d\n", error);
435 }
436
437 /*
438 * List of paths to try when searching for "init".
439 */
440 static char *initpaths[] = {
441 "/sbin/init",
442 "/sbin/oinit",
443 "/sbin/init.bak",
444 NULL,
445 };
446
447 /*
448 * Start the initial user process; try exec'ing each pathname in "initpaths".
449 * The program is invoked with one argument containing the boot flags.
450 */
451 static void
452 start_init(p)
453 struct proc *p;
454 {
455 vm_offset_t addr;
456 struct sys_execve_args /* {
457 syscallarg(const char *) path;
458 syscallarg(char * const *) argp;
459 syscallarg(char * const *) envp;
460 } */ args;
461 int options, i, error;
462 register_t retval[2];
463 char flags[4], *flagsp;
464 char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
465
466 /*
467 * Now in process 1.
468 */
469 initproc = p;
470
471 /*
472 * This is not the right way to do this. We really should
473 * hand-craft a descriptor onto /dev/console to hand to init,
474 * but that's a _lot_ more work, and the benefit from this easy
475 * hack makes up for the "good is the enemy of the best" effect.
476 */
477 check_console(p);
478
479 /*
480 * Need just enough stack to hold the faked-up "execve()" arguments.
481 */
482 addr = USRSTACK - PAGE_SIZE;
483 #if defined(UVM)
484 if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
485 NULL, UVM_UNKNOWN_OFFSET,
486 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
487 UVM_ADV_NORMAL,
488 UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
489 != KERN_SUCCESS)
490 panic("init: couldn't allocate argument space");
491 #else
492 if (vm_allocate(&p->p_vmspace->vm_map, &addr, (vm_size_t)PAGE_SIZE,
493 FALSE) != 0)
494 panic("init: couldn't allocate argument space");
495 #endif
496 p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
497
498 for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
499 ucp = (char *)(addr + PAGE_SIZE);
500
501 /*
502 * Construct the boot flag argument.
503 */
504 flagsp = flags;
505 *flagsp++ = '-';
506 options = 0;
507
508 if (boothowto & RB_SINGLE) {
509 *flagsp++ = 's';
510 options = 1;
511 }
512 #ifdef notyet
513 if (boothowto & RB_FASTBOOT) {
514 *flagsp++ = 'f';
515 options = 1;
516 }
517 #endif
518
519 /*
520 * Move out the flags (arg 1), if necessary.
521 */
522 if (options != 0) {
523 *flagsp++ = '\0';
524 i = flagsp - flags;
525 #ifdef DEBUG
526 printf("init: copying out flags `%s' %d\n", flags, i);
527 #endif
528 (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
529 arg1 = ucp;
530 }
531
532 /*
533 * Move out the file name (also arg 0).
534 */
535 i = strlen(path) + 1;
536 #ifdef DEBUG
537 printf("init: copying out path `%s' %d\n", path, i);
538 #endif
539 (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
540 arg0 = ucp;
541
542 /*
543 * Move out the arg pointers.
544 */
545 uap = (char **)((long)ucp & ~ALIGNBYTES);
546 (void)suword((caddr_t)--uap, 0); /* terminator */
547 if (options != 0)
548 (void)suword((caddr_t)--uap, (long)arg1);
549 (void)suword((caddr_t)--uap, (long)arg0);
550
551 /*
552 * Point at the arguments.
553 */
554 SCARG(&args, path) = arg0;
555 SCARG(&args, argp) = uap;
556 SCARG(&args, envp) = NULL;
557
558 /*
559 * Now try to exec the program. If can't for any reason
560 * other than it doesn't exist, complain.
561 */
562 error = sys_execve(p, &args, retval);
563 if (error == 0 || error == EJUSTRETURN)
564 return;
565 if (error != ENOENT)
566 printf("exec %s: error %d\n", path, error);
567 }
568 printf("init: not found\n");
569 panic("no init");
570 }
571
572 static void
573 start_pagedaemon(p)
574 struct proc *p;
575 {
576
577 /*
578 * Now in process 2.
579 */
580 p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */
581 bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
582 #if defined(UVM)
583 uvm_pageout();
584 #else
585 vm_pageout();
586 #endif
587 /* NOTREACHED */
588 }
589