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