fix olstat to give the correct symlink info
[unix-history] / usr / src / sys / kern / init_main.c
CommitLineData
da7c5cc6 1/*
1acdbcea
KB
2 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
adb35f79
KB
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
da7c5cc6 9 *
2d9d8fa8
MK
10 * %sccs.include.redist.c%
11 *
3ef0a118 12 * @(#)init_main.c 8.10 (Berkeley) %G%
da7c5cc6 13 */
961945a8 14
d89c95b4
KM
15#include <sys/param.h>
16#include <sys/filedesc.h>
1ccd5ccc
KM
17#include <sys/errno.h>
18#include <sys/exec.h>
d89c95b4
KM
19#include <sys/kernel.h>
20#include <sys/mount.h>
21#include <sys/map.h>
22#include <sys/proc.h>
23#include <sys/resourcevar.h>
24#include <sys/signalvar.h>
25#include <sys/systm.h>
26#include <sys/vnode.h>
27#include <sys/conf.h>
28#include <sys/buf.h>
29#include <sys/clist.h>
0d6eb1b7 30#include <sys/device.h>
d89c95b4
KM
31#include <sys/protosw.h>
32#include <sys/reboot.h>
33#include <sys/user.h>
c040c6b1 34
d301d150 35
d89c95b4 36#include <machine/cpu.h>
961945a8 37
d89c95b4 38#include <vm/vm.h>
d7db4999 39
875b0815
KM
40#ifdef HPFPLIB
41char copyright[] =
d8c34843 42"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 43#else
94d045fa 44char copyright[] =
d8c34843 45"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
875b0815 46#endif
94d045fa 47
802236f4 48/* Components of the first process -- never freed. */
d7db4999
MK
49struct session session0;
50struct pgrp pgrp0;
51struct proc proc0;
52struct pcred cred0;
c040c6b1 53struct filedesc0 filedesc0;
d7db4999
MK
54struct plimit limit0;
55struct vmspace vmspace0;
c040c6b1 56struct proc *curproc = &proc0;
d7db4999 57struct proc *initproc, *pageproc;
9d4095a1 58
28c7a4c5 59int cmask = CMASK;
f657c741 60extern struct user *proc0paddr;
362786f8 61
94d045fa
MK
62struct vnode *rootvp, *swapdev_vp;
63int boothowto;
31390dba 64struct timeval boottime;
571f7085 65struct timeval runtime;
94d045fa 66
bd65f614 67static void start_init __P((struct proc *p, void *framep));
1ccd5ccc 68
c4708522 69/*
802236f4
KB
70 * System startup; initialize the world, create process 0, mount root
71 * filesystem, and fork to create init and pagedaemon. Most of the
72 * hard work is done in the lower-level initialization routines including
73 * startup(), which does memory initialization and autoconfiguration.
c4708522 74 */
bd65f614
KM
75main(framep)
76 void *framep;
c4708522 77{
dd4b582c 78 register struct proc *p;
c040c6b1 79 register struct filedesc0 *fdp;
0d6eb1b7 80 register struct pdevinit *pdev;
802236f4 81 register int i;
d7db4999 82 int s, rval[2];
802236f4 83 extern int (*mountroot) __P((void));
0d6eb1b7 84 extern struct pdevinit pdevinit[];
571f7085
CT
85 extern void roundrobin __P((void *));
86 extern void schedcpu __P((void *));
083baeb6 87
362786f8 88 /*
802236f4
KB
89 * Initialize the current process pointer (curproc) before
90 * any possible traps/probes to simplify trap processing.
362786f8 91 */
d7db4999
MK
92 p = &proc0;
93 curproc = p;
9d4095a1 94 /*
d7db4999
MK
95 * Attempt to find console and initialize
96 * in case of early panic or other messages.
9d4095a1 97 */
d7db4999 98 consinit();
94d045fa 99 printf(copyright);
d7db4999 100
9d4095a1
KM
101 vm_mem_init();
102 kmeminit();
27bff27d 103 cpu_startup();
c4708522 104
3ef0a118
KM
105 /*
106 * Initialize process and pgrp structures.
107 */
108 procinit();
109
61b0bd0a
KM
110 /*
111 * Create process 0 (the swapper).
112 */
3ef0a118 113 LIST_INSERT_HEAD(&allproc, p, p_list);
d7db4999 114 p->p_pgrp = &pgrp0;
3ef0a118
KM
115 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
116 LIST_INIT(&pgrp0.pg_members);
117 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
118
d7db4999
MK
119 pgrp0.pg_session = &session0;
120 session0.s_count = 1;
121 session0.s_leader = p;
122
cf5ef508 123 p->p_flag = P_INMEM | P_SYSTEM;
dd4b582c 124 p->p_stat = SRUN;
dd4b582c 125 p->p_nice = NZERO;
d7db4999
MK
126 bcopy("swapper", p->p_comm, sizeof ("swapper"));
127
802236f4 128 /* Create credentials. */
2dd3075b 129 cred0.p_refcnt = 1;
d7db4999
MK
130 p->p_cred = &cred0;
131 p->p_ucred = crget();
132 p->p_ucred->cr_ngroups = 1; /* group 0 */
fb1db32c 133
802236f4 134 /* Create the file descriptor table. */
d7db4999 135 fdp = &filedesc0;
c040c6b1
MK
136 p->p_fd = &fdp->fd_fd;
137 fdp->fd_fd.fd_refcnt = 1;
138 fdp->fd_fd.fd_cmask = cmask;
139 fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
140 fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
141 fdp->fd_fd.fd_nfiles = NDFILE;
d7db4999 142
802236f4 143 /* Create the limits structures. */
d7db4999
MK
144 p->p_limit = &limit0;
145 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
146 limit0.pl_rlimit[i].rlim_cur =
147 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
50b95cfe 148 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
d7db4999 149 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
6db5115e
KM
150 i = ptoa(cnt.v_free_count);
151 limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
152 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
153 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
d7db4999
MK
154 limit0.p_refcnt = 1;
155
802236f4 156 /* Allocate a prototype map so we have something to fork. */
d7db4999
MK
157 p->p_vmspace = &vmspace0;
158 vmspace0.vm_refcnt = 1;
159 pmap_pinit(&vmspace0.vm_pmap);
160 vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS),
161 trunc_page(VM_MAX_ADDRESS), TRUE);
162 vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
163 p->p_addr = proc0paddr; /* XXX */
164
165 /*
802236f4
KB
166 * We continue to place resource usage info and signal
167 * actions in the user struct so they're pageable.
d7db4999 168 */
f657c741
MK
169 p->p_stats = &p->p_addr->u_stats;
170 p->p_sigacts = &p->p_addr->u_sigacts;
d7db4999 171
06a043ee 172 /*
3ef0a118 173 * Charge root for one process.
06a043ee 174 */
06a043ee
KM
175 (void)chgproccnt(0, 1);
176
d7db4999
MK
177 rqinit();
178
0d6eb1b7 179 /* Configure virtual memory system, set vm rlimits. */
d7db4999 180 vm_init_limits(p);
8ede3c1b 181
0d6eb1b7 182 /* Initialize the file systems. */
85570e35 183 vfsinit();
475798b6 184
0d6eb1b7 185 /* Start real time and statistics clocks. */
571f7085 186 initclocks();
c4708522 187
802236f4 188 /* Initialize mbuf's. */
d872f034 189 mbinit();
802236f4
KB
190
191 /* Initialize clists. */
192 clist_init();
193
933220e9 194#ifdef SYSVSHM
802236f4 195 /* Initialize System V style shared memory. */
933220e9
KM
196 shminit();
197#endif
0d6eb1b7
CT
198
199 /* Attach pseudo-devices. */
200 for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
201 (*pdev->pdev_attach)(pdev->pdev_count);
202
4f083fd7 203 /*
0d6eb1b7
CT
204 * Initialize protocols. Block reception of incoming packets
205 * until everything is ready.
4f083fd7
SL
206 */
207 s = splimp();
fbf9a431 208 ifinit();
b7892118 209 domaininit();
4f083fd7 210 splx(s);
d7db4999 211
e6254ffb 212#ifdef GPROF
802236f4 213 /* Initialize kernel profiling. */
e6254ffb
BJ
214 kmstartup();
215#endif
9d6d37ce 216
802236f4 217 /* Kick off timeout driven events by calling first time. */
571f7085
CT
218 roundrobin(NULL);
219 schedcpu(NULL);
27b91f59 220
802236f4 221 /* Mount the root file system. */
475798b6
KM
222 if ((*mountroot)())
223 panic("cannot mount root");
802236f4
KB
224
225 /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
af50abe6 226 if (VFS_ROOT(mountlist.tqh_first, &rootvnode))
475798b6 227 panic("cannot find root vnode");
802236f4 228 fdp->fd_fd.fd_cdir = rootvnode;
c040c6b1 229 VREF(fdp->fd_fd.fd_cdir);
802236f4 230 VOP_UNLOCK(rootvnode);
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
cf5ef508 237 * munched in mi_switch() 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
802236f4 242 /* Initialize signal state for process 0. */
d7db4999 243 siginit(p);
802236f4
KB
244
245 /* Create process 1 (init(8)). */
fb06b384 246 if (fork(p, NULL, rval))
d7db4999
MK
247 panic("fork init");
248 if (rval[1]) {
bd65f614 249 start_init(curproc, framep);
1ccd5ccc 250 return;
28c7a4c5 251 }
d7db4999 252
802236f4 253 /* Create process 2 (the pageout daemon). */
fb06b384 254 if (fork(p, NULL, rval))
d7db4999
MK
255 panic("fork pager");
256 if (rval[1]) {
257 /*
258 * Now in process 2.
259 */
260 p = curproc;
261 pageproc = p;
cf5ef508 262 p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */
d7db4999 263 bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
9d4095a1 264 vm_pageout();
802236f4 265 /* NOTREACHED */
c4708522
BJ
266 }
267
802236f4
KB
268 /* The scheduler is an infinite loop. */
269 scheduler();
270 /* NOTREACHED */
c4708522 271}
1ccd5ccc
KM
272
273/*
274 * List of paths to try when searching for "init".
275 */
276static char *initpaths[] = {
277 "/sbin/init",
278 "/sbin/oinit",
279 "/sbin/init.bak",
280 NULL,
281};
282
283/*
284 * Start the initial user process; try exec'ing each pathname in "initpaths".
285 * The program is invoked with one argument containing the boot flags.
286 */
287static void
bd65f614 288start_init(p, framep)
1ccd5ccc 289 struct proc *p;
bd65f614 290 void *framep;
1ccd5ccc
KM
291{
292 vm_offset_t addr;
293 struct execve_args args;
294 int options, i, retval[2], error;
295 char **pathp, *path, *ucp, **uap, *arg0, *arg1;
b4607756
MH
296
297 initproc = p;
1ccd5ccc
KM
298
299 /*
bd65f614
KM
300 * We need to set the system call frame as if we were entered through
301 * a syscall() so that when we call execve() below, it will be able
302 * to set the entry point (see setregs) when it tries to exec. The
303 * startup code in "locore.s" has allocated space for the frame and
304 * passed a pointer to that space as main's argument.
1ccd5ccc 305 */
bd65f614 306 cpu_set_init_frame(p, framep);
1ccd5ccc
KM
307
308 /*
309 * Need just enough stack to hold the faked-up "execve()" arguments.
310 */
311 addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE);
312 if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0)
313 panic("init: couldn't allocate argument space");
314 p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
315
316 for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
317 /*
318 * Move out the boot flag argument.
319 */
320 options = 0;
321 ucp = (char *)USRSTACK;
cf5ef508 322 (void)subyte(--ucp, 0); /* trailing zero */
1ccd5ccc 323 if (boothowto & RB_SINGLE) {
cf5ef508 324 (void)subyte(--ucp, 's');
1ccd5ccc
KM
325 options = 1;
326 }
327#ifdef notyet
328 if (boothowto & RB_FASTBOOT) {
cf5ef508 329 (void)subyte(--ucp, 'f');
1ccd5ccc
KM
330 options = 1;
331 }
332#endif
333 if (options == 0)
cf5ef508
KB
334 (void)subyte(--ucp, '-');
335 (void)subyte(--ucp, '-'); /* leading hyphen */
1ccd5ccc
KM
336 arg1 = ucp;
337
338 /*
339 * Move out the file name (also arg 0).
340 */
341 for (i = strlen(path) + 1; i >= 0; i--)
cf5ef508 342 (void)subyte(--ucp, path[i]);
1ccd5ccc
KM
343 arg0 = ucp;
344
345 /*
346 * Move out the arg pointers.
347 */
348 uap = (char **)((int)ucp & ~(NBPW-1));
cf5ef508
KB
349 (void)suword((caddr_t)--uap, 0); /* terminator */
350 (void)suword((caddr_t)--uap, (int)arg1);
351 (void)suword((caddr_t)--uap, (int)arg0);
1ccd5ccc
KM
352
353 /*
354 * Point at the arguments.
355 */
356 args.fname = arg0;
357 args.argp = uap;
358 args.envp = NULL;
359
360 /*
cf5ef508
KB
361 * Now try to exec the program. If can't for any reason
362 * other than it doesn't exist, complain.
1ccd5ccc
KM
363 */
364 if ((error = execve(p, &args, &retval)) == 0)
365 return;
cf5ef508
KB
366 if (error != ENOENT)
367 printf("exec %s: error %d\n", path, error);
1ccd5ccc
KM
368 }
369 printf("init: not found\n");
370 panic("no init");
371}