1 /* $NetBSD: init_main.c,v 1.157 1999/09/28 14:47:03 bouyer 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_sysv.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/kthread.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 #include <sys/device.h> 69 #include <sys/socketvar.h> 70 #include <sys/protosw.h> 71 #include <sys/reboot.h> 72 #include <sys/user.h> 73 #ifdef SYSVSHM 74 #include <sys/shm.h> 75 #endif 76 #ifdef SYSVSEM 77 #include <sys/sem.h> 78 #endif 79 #ifdef SYSVMSG 80 #include <sys/msg.h> 81 #endif 82 #include <sys/domain.h> 83 #include <sys/mbuf.h> 84 #include <sys/namei.h> 85 #if NRND > 0 86 #include <sys/rnd.h> 87 #endif 88 89 #include <sys/syscall.h> 90 #include <sys/syscallargs.h> 91 92 #include <ufs/ufs/quota.h> 93 94 #include <machine/cpu.h> 95 96 #include <vm/vm.h> 97 #include <vm/vm_pageout.h> 98 99 #include <uvm/uvm.h> 100 101 #include <net/if.h> 102 #include <net/raw_cb.h> 103 104 char copyright[] = "\ 105 Copyright (c) 1996, 1997, 1998, 1999 106 The NetBSD Foundation, Inc. All rights reserved. 107 Copyright (c) 1982, 1986, 1989, 1991, 1993 108 The Regents of the University of California. All rights reserved. 109 110 "; 111 112 /* Components of the first process -- never freed. */ 113 struct session session0; 114 struct pgrp pgrp0; 115 struct proc proc0; 116 struct pcred cred0; 117 struct filedesc0 filedesc0; 118 struct cwdinfo cwdi0; 119 struct plimit limit0; 120 struct vmspace vmspace0; 121 struct sigacts sigacts0; 122 #ifndef curproc 123 struct proc *curproc = &proc0; 124 #endif 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 int cold = 1; /* still working on startup */ 133 struct timeval boottime; 134 struct timeval runtime; 135 136 static void check_console __P((struct proc *p)); 137 static void start_init __P((void *)); 138 static void start_pagedaemon __P((void *)); 139 static void start_reaper __P((void *)); 140 void main __P((void)); 141 142 extern char sigcode[], esigcode[]; 143 #ifdef SYSCALL_DEBUG 144 extern char *syscallnames[]; 145 #endif 146 147 struct emul emul_netbsd = { 148 "netbsd", 149 NULL, 150 sendsig, 151 SYS_syscall, 152 SYS_MAXSYSCALL, 153 sysent, 154 #ifdef SYSCALL_DEBUG 155 syscallnames, 156 #else 157 NULL, 158 #endif 159 0, 160 copyargs, 161 setregs, 162 sigcode, 163 esigcode, 164 }; 165 166 /* 167 * System startup; initialize the world, create process 0, mount root 168 * filesystem, and fork to create init and pagedaemon. Most of the 169 * hard work is done in the lower-level initialization routines including 170 * startup(), which does memory initialization and autoconfiguration. 171 */ 172 void 173 main() 174 { 175 struct proc *p; 176 struct pdevinit *pdev; 177 int i, s, error; 178 extern struct pdevinit pdevinit[]; 179 extern void roundrobin __P((void *)); 180 extern void schedcpu __P((void *)); 181 extern void disk_init __P((void)); 182 #if defined(NFSSERVER) || defined(NFS) 183 extern void nfs_init __P((void)); 184 #endif 185 186 /* 187 * Initialize the current process pointer (curproc) before 188 * any possible traps/probes to simplify trap processing. 189 */ 190 p = &proc0; 191 curproc = p; 192 /* 193 * Attempt to find console and initialize 194 * in case of early panic or other messages. 195 */ 196 consinit(); 197 printf("%s", copyright); 198 199 uvm_init(); 200 201 /* Do machine-dependent initialization. */ 202 cpu_startup(); 203 204 /* 205 * Initialize mbuf's. Do this now because we might attempt to 206 * allocate mbufs or mbuf clusters during autoconfiguration. 207 */ 208 mbinit(); 209 210 /* Initialize sockets. */ 211 soinit(); 212 213 /* 214 * The following 3 things must be done before autoconfiguration. 215 */ 216 disk_init(); /* initialize disk list */ 217 tty_init(); /* initialize tty list */ 218 #if NRND > 0 219 rnd_init(); /* initialize RNG */ 220 #endif 221 222 /* 223 * Initialize process and pgrp structures. 224 */ 225 procinit(); 226 227 /* 228 * Create process 0 (the swapper). 229 */ 230 s = proclist_lock_write(); 231 LIST_INSERT_HEAD(&allproc, p, p_list); 232 proclist_unlock_write(s); 233 234 p->p_pgrp = &pgrp0; 235 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 236 LIST_INIT(&pgrp0.pg_members); 237 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 238 239 pgrp0.pg_session = &session0; 240 session0.s_count = 1; 241 session0.s_sid = p->p_pid; 242 session0.s_leader = p; 243 244 /* 245 * Set P_NOCLDWAIT so that kernel threads are reparented to 246 * init(8) when they exit. init(8) can easily wait them out 247 * for us. 248 */ 249 p->p_flag = P_INMEM | P_SYSTEM | P_NOCLDWAIT; 250 p->p_stat = SRUN; 251 p->p_nice = NZERO; 252 p->p_emul = &emul_netbsd; 253 strncpy(p->p_comm, "swapper", MAXCOMLEN); 254 255 /* Create credentials. */ 256 cred0.p_refcnt = 1; 257 p->p_cred = &cred0; 258 p->p_ucred = crget(); 259 p->p_ucred->cr_ngroups = 1; /* group 0 */ 260 261 /* Create the file descriptor table. */ 262 finit(); 263 p->p_fd = &filedesc0.fd_fd; 264 fdinit1(&filedesc0); 265 266 /* Create the CWD info. */ 267 p->p_cwdi = &cwdi0; 268 cwdi0.cwdi_cmask = cmask; 269 cwdi0.cwdi_refcnt = 1; 270 271 /* Create the limits structures. */ 272 p->p_limit = &limit0; 273 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 274 limit0.pl_rlimit[i].rlim_cur = 275 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 276 277 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; 278 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = 279 maxfiles < NOFILE ? maxfiles : NOFILE; 280 281 limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 282 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = 283 maxproc < MAXUPRC ? maxproc : MAXUPRC; 284 285 i = ptoa(uvmexp.free); 286 limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 287 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 288 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 289 limit0.pl_corename = defcorename; 290 limit0.p_refcnt = 1; 291 292 /* 293 * Initialize proc0's vmspace, which uses the kernel pmap. 294 * All kernel processes (which never have user space mappings) 295 * share proc0's vmspace, and thus, the kernel pmap. 296 */ 297 uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS), 298 trunc_page(VM_MAX_ADDRESS), TRUE); 299 p->p_vmspace = &vmspace0; 300 301 p->p_addr = proc0paddr; /* XXX */ 302 303 /* 304 * We continue to place resource usage info in the 305 * user struct so they're pageable. 306 */ 307 p->p_stats = &p->p_addr->u_stats; 308 309 /* 310 * Charge root for one process. 311 */ 312 (void)chgproccnt(0, 1); 313 314 rqinit(); 315 316 /* Configure virtual memory system, set vm rlimits. */ 317 uvm_init_limits(p); 318 319 /* Initialize the file systems. */ 320 #if defined(NFSSERVER) || defined(NFS) 321 nfs_init(); /* initialize server/shared data */ 322 #endif 323 vfsinit(); 324 325 /* Configure the system hardware. This will enable interrupts. */ 326 configure(); 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); 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 cwdi0.cwdi_cdir = rootvnode; 391 VREF(cwdi0.cwdi_cdir); 392 VOP_UNLOCK(rootvnode, 0); 393 cwdi0.cwdi_rdir = NULL; 394 uvm_swap_init(); 395 396 /* 397 * Now can look at time, having had a chance to verify the time 398 * from the file system. Reset p->p_rtime as it may have been 399 * munched in mi_switch() after the time got set. 400 */ 401 p->p_stats->p_start = runtime = mono_time = boottime = time; 402 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 403 404 /* 405 * Initialize signal-related data structures, and signal state 406 * for proc0. 407 */ 408 signal_init(); 409 p->p_sigacts = &sigacts0; 410 siginit(p); 411 412 /* Create process 1 (init(8)). */ 413 if (fork1(p, 0, SIGCHLD, NULL, 0, NULL, &initproc)) 414 panic("fork init"); 415 cpu_set_kpc(initproc, start_init, initproc); 416 417 /* Create process 2, the pageout daemon kernel thread. */ 418 if (kthread_create1(start_pagedaemon, NULL, NULL, "pagedaemon")) 419 panic("fork pagedaemon"); 420 421 /* Create process 3, the process reaper kernel thread. */ 422 if (kthread_create1(start_reaper, NULL, NULL, "reaper")) 423 panic("fork reaper"); 424 425 /* Create any other deferred kernel threads. */ 426 kthread_run_deferred_queue(); 427 428 /* The scheduler is an infinite loop. */ 429 uvm_scheduler(); 430 /* NOTREACHED */ 431 } 432 433 static void 434 check_console(p) 435 struct proc *p; 436 { 437 struct nameidata nd; 438 int error; 439 440 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p); 441 error = namei(&nd); 442 if (error == 0) 443 vrele(nd.ni_vp); 444 else if (error == ENOENT) 445 printf("warning: no /dev/console\n"); 446 else 447 printf("warning: lookup /dev/console: error %d\n", error); 448 } 449 450 /* 451 * List of paths to try when searching for "init". 452 */ 453 static char *initpaths[] = { 454 "/sbin/init", 455 "/sbin/oinit", 456 "/sbin/init.bak", 457 NULL, 458 }; 459 460 /* 461 * Start the initial user process; try exec'ing each pathname in "initpaths". 462 * The program is invoked with one argument containing the boot flags. 463 */ 464 static void 465 start_init(arg) 466 void *arg; 467 { 468 struct proc *p = arg; 469 vaddr_t addr; 470 struct sys_execve_args /* { 471 syscallarg(const char *) path; 472 syscallarg(char * const *) argp; 473 syscallarg(char * const *) envp; 474 } */ args; 475 int options, i, error; 476 register_t retval[2]; 477 char flags[4], *flagsp; 478 char **pathp, *path, *slash, *ucp, **uap, *arg0, *arg1 = NULL; 479 480 /* 481 * Now in process 1. 482 */ 483 strncpy(p->p_comm, "init", MAXCOMLEN); 484 485 /* 486 * This is not the right way to do this. We really should 487 * hand-craft a descriptor onto /dev/console to hand to init, 488 * but that's a _lot_ more work, and the benefit from this easy 489 * hack makes up for the "good is the enemy of the best" effect. 490 */ 491 check_console(p); 492 493 /* 494 * Need just enough stack to hold the faked-up "execve()" arguments. 495 */ 496 addr = USRSTACK - PAGE_SIZE; 497 if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, 498 NULL, UVM_UNKNOWN_OFFSET, 499 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY, 500 UVM_ADV_NORMAL, 501 UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) 502 != KERN_SUCCESS) 503 panic("init: couldn't allocate argument space"); 504 p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 505 506 for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 507 ucp = (char *)(addr + PAGE_SIZE); 508 509 /* 510 * Construct the boot flag argument. 511 */ 512 flagsp = flags; 513 *flagsp++ = '-'; 514 options = 0; 515 516 if (boothowto & RB_SINGLE) { 517 *flagsp++ = 's'; 518 options = 1; 519 } 520 #ifdef notyet 521 if (boothowto & RB_FASTBOOT) { 522 *flagsp++ = 'f'; 523 options = 1; 524 } 525 #endif 526 527 /* 528 * Move out the flags (arg 1), if necessary. 529 */ 530 if (options != 0) { 531 *flagsp++ = '\0'; 532 i = flagsp - flags; 533 #ifdef DEBUG 534 printf("init: copying out flags `%s' %d\n", flags, i); 535 #endif 536 (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i); 537 arg1 = ucp; 538 } 539 540 /* 541 * Move out the file name (also arg 0). 542 */ 543 i = strlen(path) + 1; 544 #ifdef DEBUG 545 printf("init: copying out path `%s' %d\n", path, i); 546 #endif 547 (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i); 548 arg0 = ucp; 549 550 /* 551 * Move out the arg pointers. 552 */ 553 uap = (char **)((long)ucp & ~ALIGNBYTES); 554 (void)suword((caddr_t)--uap, 0); /* terminator */ 555 if (options != 0) 556 (void)suword((caddr_t)--uap, (long)arg1); 557 slash = strrchr(path, '/'); 558 if (slash) 559 (void)suword((caddr_t)--uap, 560 (long)arg0 + (slash + 1 - path)); 561 else 562 (void)suword((caddr_t)--uap, (long)arg0); 563 564 /* 565 * Point at the arguments. 566 */ 567 SCARG(&args, path) = arg0; 568 SCARG(&args, argp) = uap; 569 SCARG(&args, envp) = NULL; 570 571 /* 572 * Now try to exec the program. If can't for any reason 573 * other than it doesn't exist, complain. 574 */ 575 error = sys_execve(p, &args, retval); 576 if (error == 0 || error == EJUSTRETURN) 577 return; 578 if (error != ENOENT) 579 printf("exec %s: error %d\n", path, error); 580 } 581 printf("init: not found\n"); 582 panic("no init"); 583 } 584 585 /* ARGSUSED */ 586 static void 587 start_pagedaemon(arg) 588 void *arg; 589 { 590 591 uvm_pageout(); 592 /* NOTREACHED */ 593 } 594 595 /* ARGSUSED */ 596 static void 597 start_reaper(arg) 598 void *arg; 599 { 600 601 reaper(); 602 /* NOTREACHED */ 603 } 604