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