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