1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)init_main.c 7.36 (Berkeley) 03/31/91 7 */ 8 9 #include "param.h" 10 #include "filedesc.h" 11 #include "kernel.h" 12 #include "mount.h" 13 #include "map.h" 14 #include "proc.h" 15 #include "resourcevar.h" 16 #include "signalvar.h" 17 #include "systm.h" 18 #include "vnode.h" 19 #include "seg.h" 20 #include "conf.h" 21 #include "buf.h" 22 #include "clist.h" 23 #include "malloc.h" 24 #include "protosw.h" 25 #include "reboot.h" 26 #include "user.h" 27 28 #include "ufs/quota.h" 29 30 #include "machine/cpu.h" 31 32 #include "vm/vm.h" 33 34 /* 35 * Components of process 0; 36 * never freed. 37 */ 38 struct session session0; 39 struct pgrp pgrp0; 40 struct proc proc0; 41 struct pcred cred0; 42 struct filedesc0 filedesc0; 43 struct plimit limit0; 44 struct vmspace vmspace0; 45 struct proc *curproc = &proc0; 46 struct proc *initproc, *pageproc; 47 48 int cmask = CMASK; 49 extern caddr_t proc0paddr; 50 extern int (*mountroot)(); 51 52 /* 53 * System startup; initialize the world, create process 0, 54 * mount root filesystem, and fork to create init and pagedaemon. 55 * Most of the hard work is done in the lower-level initialization 56 * routines including startup(), which does memory initialization 57 * and autoconfiguration. 58 */ 59 main(firstaddr) 60 int firstaddr; 61 { 62 register int i; 63 register struct proc *p; 64 register struct filedesc0 *fdp; 65 int s, rval[2]; 66 67 /* 68 * Initialize curproc before any possible traps/probes 69 * to simplify trap processing. 70 */ 71 p = &proc0; 72 curproc = p; 73 /* 74 * Attempt to find console and initialize 75 * in case of early panic or other messages. 76 */ 77 consinit(); 78 79 vm_mem_init(); 80 kmeminit(); 81 startup(firstaddr); 82 83 /* 84 * set up system process 0 (swapper) 85 */ 86 p = &proc0; 87 curproc = p; 88 89 allproc = p; 90 p->p_prev = &allproc; 91 p->p_pgrp = &pgrp0; 92 pgrphash[0] = &pgrp0; 93 pgrp0.pg_mem = p; 94 pgrp0.pg_session = &session0; 95 session0.s_count = 1; 96 session0.s_leader = p; 97 98 p->p_flag = SLOAD|SSYS; 99 p->p_stat = SRUN; 100 p->p_nice = NZERO; 101 bcopy("swapper", p->p_comm, sizeof ("swapper")); 102 103 /* 104 * Setup credentials 105 */ 106 p->p_cred = &cred0; 107 p->p_ucred = crget(); 108 p->p_ucred->cr_ngroups = 1; /* group 0 */ 109 110 /* 111 * Create the file descriptor table for process 0. 112 */ 113 fdp = &filedesc0; 114 p->p_fd = &fdp->fd_fd; 115 fdp->fd_fd.fd_refcnt = 1; 116 fdp->fd_fd.fd_cmask = cmask; 117 fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 118 fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 119 fdp->fd_fd.fd_nfiles = NDFILE; 120 121 /* 122 * Set initial limits 123 */ 124 p->p_limit = &limit0; 125 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 126 limit0.pl_rlimit[i].rlim_cur = 127 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 128 limit0.pl_rlimit[RLIMIT_OFILE].rlim_cur = NOFILE; 129 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 130 limit0.p_refcnt = 1; 131 132 /* 133 * Allocate a prototype map so we have something to fork 134 */ 135 p->p_vmspace = &vmspace0; 136 vmspace0.vm_refcnt = 1; 137 pmap_pinit(&vmspace0.vm_pmap); 138 vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 139 trunc_page(VM_MAX_ADDRESS), TRUE); 140 vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 141 p->p_addr = proc0paddr; /* XXX */ 142 143 /* 144 * We continue to place resource usage info 145 * and signal actions in the user struct so they're pageable. 146 */ 147 p->p_stats = &((struct user *)p->p_addr)->u_stats; 148 p->p_sigacts = &((struct user *)p->p_addr)->u_sigacts; 149 150 rqinit(); 151 152 /* 153 * configure virtual memory system, 154 * set vm rlimits 155 */ 156 vm_init_limits(p); 157 158 /* 159 * Initialize the file systems. 160 * 161 * Get vnodes for swapdev, argdev, and rootdev. 162 */ 163 vfsinit(); 164 if (bdevvp(swapdev, &swapdev_vp) || 165 bdevvp(argdev, &argdev_vp) || 166 bdevvp(rootdev, &rootvp)) 167 panic("can't setup bdevvp's"); 168 169 startrtclock(); 170 #if defined(vax) 171 #include "kg.h" 172 #if NKG > 0 173 startkgclock(); 174 #endif 175 #endif 176 177 /* 178 * Initialize tables, protocols, and set up well-known inodes. 179 */ 180 mbinit(); 181 cinit(); 182 #ifdef SYSVSHM 183 shminit(); 184 #endif 185 #include "sl.h" 186 #if NSL > 0 187 slattach(); /* XXX */ 188 #endif 189 #include "loop.h" 190 #if NLOOP > 0 191 loattach(); /* XXX */ 192 #endif 193 /* 194 * Block reception of incoming packets 195 * until protocols have been initialized. 196 */ 197 s = splimp(); 198 ifinit(); 199 domaininit(); 200 splx(s); 201 202 #ifdef GPROF 203 kmstartup(); 204 #endif 205 206 /* kick off timeout driven events by calling first time */ 207 roundrobin(); 208 schedcpu(); 209 enablertclock(); /* enable realtime clock interrupts */ 210 211 /* 212 * Set up the root file system and vnode. 213 */ 214 if ((*mountroot)()) 215 panic("cannot mount root"); 216 /* 217 * Get vnode for '/'. 218 * Setup rootdir and fdp->fd_fd.fd_cdir to point to it. 219 */ 220 if (VFS_ROOT(rootfs, &rootdir)) 221 panic("cannot find root vnode"); 222 fdp->fd_fd.fd_cdir = rootdir; 223 VREF(fdp->fd_fd.fd_cdir); 224 VOP_UNLOCK(rootdir); 225 fdp->fd_fd.fd_rdir = NULL; 226 swapinit(); 227 228 /* 229 * Now can look at time, having had a chance 230 * to verify the time from the file system. 231 */ 232 boottime = p->p_stats->p_start = time; 233 234 /* 235 * make init process 236 */ 237 siginit(p); 238 if (fork(p, (void *) NULL, rval)) 239 panic("fork init"); 240 if (rval[1]) { 241 static char initflags[] = "-sf"; 242 char *ip = initflags + 1; 243 vm_offset_t addr = 0; 244 245 /* 246 * Now in process 1. Set init flags into icode, 247 * get a minimal address space, copy out "icode", 248 * and return to it to do an exec of init. 249 */ 250 p = curproc; 251 initproc = p; 252 if (boothowto&RB_SINGLE) 253 *ip++ = 's'; 254 #ifdef notyet 255 if (boothowto&RB_FASTBOOT) 256 *ip++ = 'f'; 257 #endif 258 *ip++ = '\0'; 259 260 if (vm_allocate(&p->p_vmspace->vm_map, &addr, 261 round_page(szicode + sizeof(initflags)), FALSE) != 0 || 262 addr != 0) 263 panic("init: couldn't allocate at zero"); 264 265 /* need just enough stack to exec from */ 266 addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 267 if (vm_allocate(&p->p_vmspace->vm_map, &addr, 268 PAGE_SIZE, FALSE) != KERN_SUCCESS) 269 panic("vm_allocate init stack"); 270 p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 271 (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode); 272 (void) copyout(initflags, (caddr_t)szicode, sizeof(initflags)); 273 return; /* returns to icode */ 274 } 275 276 /* 277 * Start up pageout daemon (process 2). 278 */ 279 if (fork(p, (void *) NULL, rval)) 280 panic("fork pager"); 281 if (rval[1]) { 282 /* 283 * Now in process 2. 284 */ 285 p = curproc; 286 pageproc = p; 287 p->p_flag |= SLOAD|SSYS; /* XXX */ 288 bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 289 vm_pageout(); 290 /*NOTREACHED*/ 291 } 292 293 /* 294 * enter scheduling loop 295 */ 296 sched(); 297 } 298 299 /* MOVE TO vfs_bio.c (bufinit) XXX */ 300 /* 301 * Initialize buffers and hash links for buffers. 302 */ 303 bufinit() 304 { 305 register int i; 306 register struct buf *bp, *dp; 307 register struct bufhd *hp; 308 int base, residual; 309 310 for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++) 311 hp->b_forw = hp->b_back = (struct buf *)hp; 312 313 for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) { 314 dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp; 315 dp->b_flags = B_HEAD; 316 } 317 base = bufpages / nbuf; 318 residual = bufpages % nbuf; 319 for (i = 0; i < nbuf; i++) { 320 bp = &buf[i]; 321 bp->b_dev = NODEV; 322 bp->b_bcount = 0; 323 bp->b_rcred = NOCRED; 324 bp->b_wcred = NOCRED; 325 bp->b_dirtyoff = 0; 326 bp->b_dirtyend = 0; 327 bp->b_un.b_addr = buffers + i * MAXBSIZE; 328 if (i < residual) 329 bp->b_bufsize = (base + 1) * CLBYTES; 330 else 331 bp->b_bufsize = base * CLBYTES; 332 binshash(bp, &bfreelist[BQ_AGE]); 333 bp->b_flags = B_BUSY|B_INVAL; 334 brelse(bp); 335 } 336 } 337