Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
1acdbcea KB |
2 | * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
da7c5cc6 | 4 | * |
2d9d8fa8 MK |
5 | * %sccs.include.redist.c% |
6 | * | |
1acdbcea | 7 | * @(#)init_main.c 8.1 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
961945a8 | 9 | |
d89c95b4 KM |
10 | #include <sys/param.h> |
11 | #include <sys/filedesc.h> | |
12 | #include <sys/kernel.h> | |
13 | #include <sys/mount.h> | |
14 | #include <sys/map.h> | |
15 | #include <sys/proc.h> | |
16 | #include <sys/resourcevar.h> | |
17 | #include <sys/signalvar.h> | |
18 | #include <sys/systm.h> | |
19 | #include <sys/vnode.h> | |
20 | #include <sys/conf.h> | |
21 | #include <sys/buf.h> | |
22 | #include <sys/clist.h> | |
0d6eb1b7 | 23 | #include <sys/device.h> |
d89c95b4 KM |
24 | #include <sys/protosw.h> |
25 | #include <sys/reboot.h> | |
26 | #include <sys/user.h> | |
c040c6b1 | 27 | |
d301d150 | 28 | |
d89c95b4 | 29 | #include <machine/cpu.h> |
961945a8 | 30 | |
d89c95b4 | 31 | #include <vm/vm.h> |
d7db4999 | 32 | |
875b0815 KM |
33 | #ifdef HPFPLIB |
34 | char copyright[] = | |
d8c34843 | 35 | "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n"; |
875b0815 | 36 | #else |
94d045fa | 37 | char copyright[] = |
d8c34843 | 38 | "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; |
875b0815 | 39 | #endif |
94d045fa | 40 | |
d7db4999 MK |
41 | /* |
42 | * Components of process 0; | |
43 | * never freed. | |
44 | */ | |
45 | struct session session0; | |
46 | struct pgrp pgrp0; | |
47 | struct proc proc0; | |
48 | struct pcred cred0; | |
c040c6b1 | 49 | struct filedesc0 filedesc0; |
d7db4999 MK |
50 | struct plimit limit0; |
51 | struct vmspace vmspace0; | |
c040c6b1 | 52 | struct proc *curproc = &proc0; |
d7db4999 | 53 | struct proc *initproc, *pageproc; |
9d4095a1 | 54 | |
28c7a4c5 | 55 | int cmask = CMASK; |
f657c741 | 56 | extern struct user *proc0paddr; |
475798b6 | 57 | extern int (*mountroot)(); |
362786f8 | 58 | |
94d045fa MK |
59 | struct vnode *rootvp, *swapdev_vp; |
60 | int boothowto; | |
31390dba | 61 | struct timeval boottime; |
571f7085 | 62 | struct timeval runtime; |
94d045fa | 63 | |
c4708522 | 64 | /* |
d7db4999 MK |
65 | * System startup; initialize the world, create process 0, |
66 | * mount root filesystem, and fork to create init and pagedaemon. | |
67 | * Most of the hard work is done in the lower-level initialization | |
68 | * routines including startup(), which does memory initialization | |
69 | * and autoconfiguration. | |
c4708522 | 70 | */ |
27bff27d | 71 | main() |
c4708522 | 72 | { |
73248996 | 73 | register int i; |
dd4b582c | 74 | register struct proc *p; |
c040c6b1 | 75 | register struct filedesc0 *fdp; |
0d6eb1b7 | 76 | register struct pdevinit *pdev; |
d7db4999 | 77 | int s, rval[2]; |
0d6eb1b7 | 78 | extern struct pdevinit pdevinit[]; |
571f7085 CT |
79 | extern void roundrobin __P((void *)); |
80 | extern void schedcpu __P((void *)); | |
083baeb6 | 81 | |
362786f8 | 82 | /* |
d7db4999 MK |
83 | * Initialize curproc before any possible traps/probes |
84 | * to simplify trap processing. | |
362786f8 | 85 | */ |
d7db4999 MK |
86 | p = &proc0; |
87 | curproc = p; | |
9d4095a1 | 88 | /* |
d7db4999 MK |
89 | * Attempt to find console and initialize |
90 | * in case of early panic or other messages. | |
9d4095a1 | 91 | */ |
d7db4999 | 92 | consinit(); |
94d045fa | 93 | printf(copyright); |
d7db4999 | 94 | |
9d4095a1 KM |
95 | vm_mem_init(); |
96 | kmeminit(); | |
27bff27d | 97 | cpu_startup(); |
c4708522 BJ |
98 | |
99 | /* | |
100 | * set up system process 0 (swapper) | |
101 | */ | |
d7db4999 MK |
102 | p = &proc0; |
103 | curproc = p; | |
104 | ||
571f7085 CT |
105 | allproc = (volatile struct proc *)p; |
106 | p->p_prev = (struct proc **)&allproc; | |
d7db4999 MK |
107 | p->p_pgrp = &pgrp0; |
108 | pgrphash[0] = &pgrp0; | |
109 | pgrp0.pg_mem = p; | |
110 | pgrp0.pg_session = &session0; | |
111 | session0.s_count = 1; | |
112 | session0.s_leader = p; | |
113 | ||
114 | p->p_flag = SLOAD|SSYS; | |
dd4b582c | 115 | p->p_stat = SRUN; |
dd4b582c | 116 | p->p_nice = NZERO; |
d7db4999 MK |
117 | bcopy("swapper", p->p_comm, sizeof ("swapper")); |
118 | ||
9d4095a1 | 119 | /* |
d7db4999 | 120 | * Setup credentials |
14fda239 | 121 | */ |
2dd3075b | 122 | cred0.p_refcnt = 1; |
d7db4999 MK |
123 | p->p_cred = &cred0; |
124 | p->p_ucred = crget(); | |
125 | p->p_ucred->cr_ngroups = 1; /* group 0 */ | |
fb1db32c | 126 | |
5e00df3b KM |
127 | /* |
128 | * Create the file descriptor table for process 0. | |
129 | */ | |
d7db4999 | 130 | fdp = &filedesc0; |
c040c6b1 MK |
131 | p->p_fd = &fdp->fd_fd; |
132 | fdp->fd_fd.fd_refcnt = 1; | |
133 | fdp->fd_fd.fd_cmask = cmask; | |
134 | fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; | |
135 | fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; | |
136 | fdp->fd_fd.fd_nfiles = NDFILE; | |
d7db4999 MK |
137 | |
138 | /* | |
139 | * Set initial limits | |
140 | */ | |
141 | p->p_limit = &limit0; | |
142 | for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) | |
143 | limit0.pl_rlimit[i].rlim_cur = | |
144 | limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; | |
50b95cfe | 145 | limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; |
d7db4999 | 146 | limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; |
6db5115e KM |
147 | i = ptoa(cnt.v_free_count); |
148 | limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; | |
149 | limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; | |
150 | limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; | |
d7db4999 MK |
151 | limit0.p_refcnt = 1; |
152 | ||
153 | /* | |
154 | * Allocate a prototype map so we have something to fork | |
155 | */ | |
156 | p->p_vmspace = &vmspace0; | |
157 | vmspace0.vm_refcnt = 1; | |
158 | pmap_pinit(&vmspace0.vm_pmap); | |
159 | vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), | |
160 | trunc_page(VM_MAX_ADDRESS), TRUE); | |
161 | vmspace0.vm_map.pmap = &vmspace0.vm_pmap; | |
162 | p->p_addr = proc0paddr; /* XXX */ | |
163 | ||
164 | /* | |
165 | * We continue to place resource usage info | |
166 | * and signal actions in the user struct so they're pageable. | |
167 | */ | |
f657c741 MK |
168 | p->p_stats = &p->p_addr->u_stats; |
169 | p->p_sigacts = &p->p_addr->u_sigacts; | |
d7db4999 | 170 | |
06a043ee KM |
171 | /* |
172 | * Initialize per uid information structure and charge | |
173 | * root for one process. | |
174 | */ | |
175 | usrinfoinit(); | |
176 | (void)chgproccnt(0, 1); | |
177 | ||
d7db4999 MK |
178 | rqinit(); |
179 | ||
0d6eb1b7 | 180 | /* Configure virtual memory system, set vm rlimits. */ |
d7db4999 | 181 | vm_init_limits(p); |
8ede3c1b | 182 | |
0d6eb1b7 | 183 | /* Initialize the file systems. */ |
85570e35 | 184 | vfsinit(); |
475798b6 | 185 | |
0d6eb1b7 | 186 | /* Start real time and statistics clocks. */ |
571f7085 | 187 | initclocks(); |
c4708522 | 188 | |
0d6eb1b7 | 189 | /* Initialize tables. */ |
d872f034 | 190 | mbinit(); |
a5829200 | 191 | cinit(); |
933220e9 KM |
192 | #ifdef SYSVSHM |
193 | shminit(); | |
194 | #endif | |
0d6eb1b7 CT |
195 | |
196 | /* Attach pseudo-devices. */ | |
197 | for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) | |
198 | (*pdev->pdev_attach)(pdev->pdev_count); | |
199 | ||
4f083fd7 | 200 | /* |
0d6eb1b7 CT |
201 | * Initialize protocols. Block reception of incoming packets |
202 | * until everything is ready. | |
4f083fd7 SL |
203 | */ |
204 | s = splimp(); | |
fbf9a431 | 205 | ifinit(); |
b7892118 | 206 | domaininit(); |
4f083fd7 | 207 | splx(s); |
d7db4999 | 208 | |
e6254ffb BJ |
209 | #ifdef GPROF |
210 | kmstartup(); | |
211 | #endif | |
9d6d37ce | 212 | |
d7db4999 | 213 | /* kick off timeout driven events by calling first time */ |
571f7085 CT |
214 | roundrobin(NULL); |
215 | schedcpu(NULL); | |
27b91f59 | 216 | |
d7db4999 MK |
217 | /* |
218 | * Set up the root file system and vnode. | |
219 | */ | |
475798b6 KM |
220 | if ((*mountroot)()) |
221 | panic("cannot mount root"); | |
222 | /* | |
223 | * Get vnode for '/'. | |
c040c6b1 | 224 | * Setup rootdir and fdp->fd_fd.fd_cdir to point to it. |
475798b6 KM |
225 | */ |
226 | if (VFS_ROOT(rootfs, &rootdir)) | |
227 | panic("cannot find root vnode"); | |
c040c6b1 MK |
228 | fdp->fd_fd.fd_cdir = rootdir; |
229 | VREF(fdp->fd_fd.fd_cdir); | |
3ca85ace | 230 | VOP_UNLOCK(rootdir); |
c040c6b1 | 231 | fdp->fd_fd.fd_rdir = NULL; |
d7db4999 | 232 | swapinit(); |
c4708522 | 233 | |
28c7a4c5 | 234 | /* |
38fab586 KM |
235 | * Now can look at time, having had a chance to verify the time |
236 | * from the file system. Reset p->p_rtime as it may have been | |
237 | * munched in swtch() after the time got set. | |
28c7a4c5 | 238 | */ |
d4f004e2 | 239 | p->p_stats->p_start = runtime = mono_time = boottime = time; |
38fab586 | 240 | p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; |
28c7a4c5 | 241 | |
d7db4999 MK |
242 | /* |
243 | * make init process | |
244 | */ | |
245 | siginit(p); | |
fb06b384 | 246 | if (fork(p, NULL, rval)) |
d7db4999 MK |
247 | panic("fork init"); |
248 | if (rval[1]) { | |
94d045fa MK |
249 | extern int icode[]; /* user init code */ |
250 | extern int szicode; /* size of icode */ | |
fb06b384 KB |
251 | static char initflags[] = "-sf"; |
252 | vm_offset_t addr; | |
253 | char *ip; | |
9d4095a1 | 254 | |
d7db4999 | 255 | /* |
fb06b384 KB |
256 | * Now in process 1. Set init flags into icode, get a minimal |
257 | * address space, copy out "icode", and return to it to do an | |
258 | * exec of init. | |
d7db4999 | 259 | */ |
fb06b384 | 260 | ip = initflags + 1; |
d7db4999 MK |
261 | if (boothowto&RB_SINGLE) |
262 | *ip++ = 's'; | |
263 | #ifdef notyet | |
264 | if (boothowto&RB_FASTBOOT) | |
265 | *ip++ = 'f'; | |
d7db4999 | 266 | #endif |
fb06b384 KB |
267 | if (ip == initflags + 1) |
268 | *ip++ = '-'; | |
83cf086b | 269 | *ip++ = '\0'; |
d7db4999 | 270 | |
f5c2666f | 271 | addr = VM_MIN_ADDRESS; |
fb06b384 | 272 | initproc = p = curproc; |
d7db4999 | 273 | if (vm_allocate(&p->p_vmspace->vm_map, &addr, |
83cf086b | 274 | round_page(szicode + sizeof(initflags)), FALSE) != 0 || |
f5c2666f | 275 | addr != VM_MIN_ADDRESS) |
9d4095a1 KM |
276 | panic("init: couldn't allocate at zero"); |
277 | ||
278 | /* need just enough stack to exec from */ | |
f657c741 | 279 | addr = trunc_page(USRSTACK - PAGE_SIZE); |
d7db4999 MK |
280 | if (vm_allocate(&p->p_vmspace->vm_map, &addr, |
281 | PAGE_SIZE, FALSE) != KERN_SUCCESS) | |
282 | panic("vm_allocate init stack"); | |
283 | p->p_vmspace->vm_maxsaddr = (caddr_t)addr; | |
f5c2666f CT |
284 | (void)copyout((caddr_t)icode, (caddr_t)VM_MIN_ADDRESS, |
285 | (u_int)szicode); | |
286 | (void)copyout(initflags, (caddr_t)(VM_MIN_ADDRESS + szicode), | |
287 | sizeof(initflags)); | |
d7db4999 | 288 | return; /* returns to icode */ |
28c7a4c5 | 289 | } |
d7db4999 | 290 | |
c4708522 | 291 | /* |
9d4095a1 | 292 | * Start up pageout daemon (process 2). |
c4708522 | 293 | */ |
fb06b384 | 294 | if (fork(p, NULL, rval)) |
d7db4999 MK |
295 | panic("fork pager"); |
296 | if (rval[1]) { | |
297 | /* | |
298 | * Now in process 2. | |
299 | */ | |
300 | p = curproc; | |
301 | pageproc = p; | |
302 | p->p_flag |= SLOAD|SSYS; /* XXX */ | |
303 | bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); | |
9d4095a1 | 304 | vm_pageout(); |
b7892118 | 305 | /*NOTREACHED*/ |
c4708522 BJ |
306 | } |
307 | ||
308 | /* | |
c4708522 BJ |
309 | * enter scheduling loop |
310 | */ | |
c4708522 BJ |
311 | sched(); |
312 | } |