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