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