init_main.c revision 147730
1/*-
2 * Copyright (c) 1995 Terrence R. Lambert
3 * All rights reserved.
4 *
5 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 *    must display the following acknowledgement:
23 *	This product includes software developed by the University of
24 *	California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 *    may be used to endorse or promote products derived from this software
27 *    without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/kern/init_main.c 147730 2005-07-01 16:28:32Z ssouhlal $");
46
47#include "opt_init_path.h"
48#include "opt_mac.h"
49
50#include <sys/param.h>
51#include <sys/kernel.h>
52#include <sys/exec.h>
53#include <sys/file.h>
54#include <sys/filedesc.h>
55#include <sys/ktr.h>
56#include <sys/lock.h>
57#include <sys/mac.h>
58#include <sys/mount.h>
59#include <sys/mutex.h>
60#include <sys/syscallsubr.h>
61#include <sys/sysctl.h>
62#include <sys/proc.h>
63#include <sys/resourcevar.h>
64#include <sys/systm.h>
65#include <sys/signalvar.h>
66#include <sys/vnode.h>
67#include <sys/sysent.h>
68#include <sys/reboot.h>
69#include <sys/sched.h>
70#include <sys/sx.h>
71#include <sys/sysproto.h>
72#include <sys/vmmeter.h>
73#include <sys/unistd.h>
74#include <sys/malloc.h>
75#include <sys/conf.h>
76
77#include <machine/cpu.h>
78
79#include <vm/vm.h>
80#include <vm/vm_param.h>
81#include <vm/pmap.h>
82#include <vm/vm_map.h>
83#include <sys/copyright.h>
84
85void mi_startup(void);				/* Should be elsewhere */
86
87/* Components of the first process -- never freed. */
88static struct session session0;
89static struct pgrp pgrp0;
90struct	proc proc0;
91struct	thread thread0;
92struct	ksegrp ksegrp0;
93struct	vmspace vmspace0;
94struct	proc *initproc;
95
96int	boothowto = 0;		/* initialized so that it can be patched */
97SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "");
98int	bootverbose;
99SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, "");
100
101/*
102 * This ensures that there is at least one entry so that the sysinit_set
103 * symbol is not undefined.  A sybsystem ID of SI_SUB_DUMMY is never
104 * executed.
105 */
106SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
107
108/*
109 * The sysinit table itself.  Items are checked off as the are run.
110 * If we want to register new sysinit types, add them to newsysinit.
111 */
112SET_DECLARE(sysinit_set, struct sysinit);
113struct sysinit **sysinit, **sysinit_end;
114struct sysinit **newsysinit, **newsysinit_end;
115
116/*
117 * Merge a new sysinit set into the current set, reallocating it if
118 * necessary.  This can only be called after malloc is running.
119 */
120void
121sysinit_add(struct sysinit **set, struct sysinit **set_end)
122{
123	struct sysinit **newset;
124	struct sysinit **sipp;
125	struct sysinit **xipp;
126	int count;
127
128	count = set_end - set;
129	if (newsysinit)
130		count += newsysinit_end - newsysinit;
131	else
132		count += sysinit_end - sysinit;
133	newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
134	if (newset == NULL)
135		panic("cannot malloc for sysinit");
136	xipp = newset;
137	if (newsysinit)
138		for (sipp = newsysinit; sipp < newsysinit_end; sipp++)
139			*xipp++ = *sipp;
140	else
141		for (sipp = sysinit; sipp < sysinit_end; sipp++)
142			*xipp++ = *sipp;
143	for (sipp = set; sipp < set_end; sipp++)
144		*xipp++ = *sipp;
145	if (newsysinit)
146		free(newsysinit, M_TEMP);
147	newsysinit = newset;
148	newsysinit_end = newset + count;
149}
150
151/*
152 * System startup; initialize the world, create process 0, mount root
153 * filesystem, and fork to create init and pagedaemon.  Most of the
154 * hard work is done in the lower-level initialization routines including
155 * startup(), which does memory initialization and autoconfiguration.
156 *
157 * This allows simple addition of new kernel subsystems that require
158 * boot time initialization.  It also allows substitution of subsystem
159 * (for instance, a scheduler, kernel profiler, or VM system) by object
160 * module.  Finally, it allows for optional "kernel threads".
161 */
162void
163mi_startup(void)
164{
165
166	register struct sysinit **sipp;		/* system initialization*/
167	register struct sysinit **xipp;		/* interior loop of sort*/
168	register struct sysinit *save;		/* bubble*/
169
170	if (sysinit == NULL) {
171		sysinit = SET_BEGIN(sysinit_set);
172		sysinit_end = SET_LIMIT(sysinit_set);
173	}
174
175restart:
176	/*
177	 * Perform a bubble sort of the system initialization objects by
178	 * their subsystem (primary key) and order (secondary key).
179	 */
180	for (sipp = sysinit; sipp < sysinit_end; sipp++) {
181		for (xipp = sipp + 1; xipp < sysinit_end; xipp++) {
182			if ((*sipp)->subsystem < (*xipp)->subsystem ||
183			     ((*sipp)->subsystem == (*xipp)->subsystem &&
184			      (*sipp)->order <= (*xipp)->order))
185				continue;	/* skip*/
186			save = *sipp;
187			*sipp = *xipp;
188			*xipp = save;
189		}
190	}
191
192	/*
193	 * Traverse the (now) ordered list of system initialization tasks.
194	 * Perform each task, and continue on to the next task.
195	 *
196	 * The last item on the list is expected to be the scheduler,
197	 * which will not return.
198	 */
199	for (sipp = sysinit; sipp < sysinit_end; sipp++) {
200
201		if ((*sipp)->subsystem == SI_SUB_DUMMY)
202			continue;	/* skip dummy task(s)*/
203
204		if ((*sipp)->subsystem == SI_SUB_DONE)
205			continue;
206
207		/* Call function */
208		(*((*sipp)->func))((*sipp)->udata);
209
210		/* Check off the one we're just done */
211		(*sipp)->subsystem = SI_SUB_DONE;
212
213		/* Check if we've installed more sysinit items via KLD */
214		if (newsysinit != NULL) {
215			if (sysinit != SET_BEGIN(sysinit_set))
216				free(sysinit, M_TEMP);
217			sysinit = newsysinit;
218			sysinit_end = newsysinit_end;
219			newsysinit = NULL;
220			newsysinit_end = NULL;
221			goto restart;
222		}
223	}
224
225	panic("Shouldn't get here!");
226	/* NOTREACHED*/
227}
228
229
230/*
231 ***************************************************************************
232 ****
233 **** The following SYSINIT's belong elsewhere, but have not yet
234 **** been moved.
235 ****
236 ***************************************************************************
237 */
238static void
239print_caddr_t(void *data __unused)
240{
241	printf("%s", (char *)data);
242}
243SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
244SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version)
245
246#ifdef WITNESS
247static char wit_warn[] =
248     "WARNING: WITNESS option enabled, expect reduced performance.\n";
249SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 1,
250   print_caddr_t, wit_warn)
251#endif
252
253#ifdef DIAGNOSTIC
254static char diag_warn[] =
255     "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n";
256SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 2,
257    print_caddr_t, diag_warn)
258#endif
259
260static void
261set_boot_verbose(void *data __unused)
262{
263
264	if (boothowto & RB_VERBOSE)
265		bootverbose++;
266}
267SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL)
268
269struct sysentvec null_sysvec = {
270	0,
271	NULL,
272	0,
273	0,
274	NULL,
275	0,
276	NULL,
277	NULL,
278	NULL,
279	NULL,
280	NULL,
281	NULL,
282	NULL,
283	"null",
284	NULL,
285	NULL,
286	0,
287	PAGE_SIZE,
288	VM_MIN_ADDRESS,
289	VM_MAXUSER_ADDRESS,
290	USRSTACK,
291	PS_STRINGS,
292	VM_PROT_ALL,
293	NULL,
294	NULL,
295	NULL
296};
297
298/*
299 ***************************************************************************
300 ****
301 **** The two following SYSINIT's are proc0 specific glue code.  I am not
302 **** convinced that they can not be safely combined, but their order of
303 **** operation has been maintained as the same as the original init_main.c
304 **** for right now.
305 ****
306 **** These probably belong in init_proc.c or kern_proc.c, since they
307 **** deal with proc0 (the fork template process).
308 ****
309 ***************************************************************************
310 */
311/* ARGSUSED*/
312static void
313proc0_init(void *dummy __unused)
314{
315	struct proc *p;
316	unsigned i;
317	struct thread *td;
318	struct ksegrp *kg;
319
320	GIANT_REQUIRED;
321	p = &proc0;
322	td = &thread0;
323	kg = &ksegrp0;
324
325	/*
326	 * Initialize magic number.
327	 */
328	p->p_magic = P_MAGIC;
329
330	/*
331	 * Initialize thread, process and ksegrp structures.
332	 */
333	procinit();	/* set up proc zone */
334	threadinit();	/* set up thead, upcall and KSEGRP zones */
335
336	/*
337	 * Initialise scheduler resources.
338	 * Add scheduler specific parts to proc, ksegrp, thread as needed.
339	 */
340	schedinit();	/* scheduler gets its house in order */
341	/*
342	 * Initialize sleep queue hash table
343	 */
344	sleepinit();
345
346	/*
347	 * additional VM structures
348	 */
349	vm_init2();
350
351	/*
352	 * Create process 0 (the swapper).
353	 */
354	LIST_INSERT_HEAD(&allproc, p, p_list);
355	LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
356	mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
357	p->p_pgrp = &pgrp0;
358	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
359	LIST_INIT(&pgrp0.pg_members);
360	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
361
362	pgrp0.pg_session = &session0;
363	mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF);
364	session0.s_count = 1;
365	session0.s_leader = p;
366
367	p->p_sysent = &null_sysvec;
368	p->p_flag = P_SYSTEM;
369	p->p_sflag = PS_INMEM;
370	p->p_state = PRS_NORMAL;
371	knlist_init(&p->p_klist, &p->p_mtx, NULL, NULL, NULL);
372	p->p_nice = NZERO;
373	td->td_state = TDS_RUNNING;
374	kg->kg_pri_class = PRI_TIMESHARE;
375	kg->kg_user_pri = PUSER;
376	td->td_priority = PVM;
377	td->td_base_pri = PUSER;
378	td->td_oncpu = 0;
379	p->p_peers = 0;
380	p->p_leader = p;
381
382
383	bcopy("swapper", p->p_comm, sizeof ("swapper"));
384
385	callout_init(&p->p_itcallout, CALLOUT_MPSAFE);
386	callout_init(&td->td_slpcallout, CALLOUT_MPSAFE);
387
388	/* Create credentials. */
389	p->p_ucred = crget();
390	p->p_ucred->cr_ngroups = 1;	/* group 0 */
391	p->p_ucred->cr_uidinfo = uifind(0);
392	p->p_ucred->cr_ruidinfo = uifind(0);
393	p->p_ucred->cr_prison = NULL;	/* Don't jail it. */
394#ifdef MAC
395	mac_create_proc0(p->p_ucred);
396#endif
397	td->td_ucred = crhold(p->p_ucred);
398
399	/* Create sigacts. */
400	p->p_sigacts = sigacts_alloc();
401
402	/* Initialize signal state for process 0. */
403	siginit(&proc0);
404
405	/* Create the file descriptor table. */
406	p->p_fd = fdinit(NULL);
407	p->p_fdtol = NULL;
408
409	/* Create the limits structures. */
410	p->p_limit = lim_alloc();
411	for (i = 0; i < RLIM_NLIMITS; i++)
412		p->p_limit->pl_rlimit[i].rlim_cur =
413		    p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY;
414	p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur =
415	    p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
416	p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur =
417	    p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
418	i = ptoa(cnt.v_free_count);
419	p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = i;
420	p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
421	p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
422	p->p_cpulimit = RLIM_INFINITY;
423
424	p->p_stats = pstats_alloc();
425
426	/* Allocate a prototype map so we have something to fork. */
427	pmap_pinit0(vmspace_pmap(&vmspace0));
428	p->p_vmspace = &vmspace0;
429	vmspace0.vm_refcnt = 1;
430	vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser,
431	    p->p_sysent->sv_maxuser);
432	vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0);
433
434	/*
435	 * Charge root for one process.
436	 */
437	(void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0);
438}
439SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
440
441/* ARGSUSED*/
442static void
443proc0_post(void *dummy __unused)
444{
445	struct timespec ts;
446	struct proc *p;
447
448	/*
449	 * Now we can look at the time, having had a chance to verify the
450	 * time from the filesystem.  Pretend that proc0 started now.
451	 */
452	sx_slock(&allproc_lock);
453	LIST_FOREACH(p, &allproc, p_list) {
454		microuptime(&p->p_stats->p_start);
455		p->p_rux.rux_runtime.sec = 0;
456		p->p_rux.rux_runtime.frac = 0;
457	}
458	sx_sunlock(&allproc_lock);
459	binuptime(PCPU_PTR(switchtime));
460	PCPU_SET(switchticks, ticks);
461
462	/*
463	 * Give the ``random'' number generator a thump.
464	 */
465	nanotime(&ts);
466	srandom(ts.tv_sec ^ ts.tv_nsec);
467}
468SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
469
470/*
471 ***************************************************************************
472 ****
473 **** The following SYSINIT's and glue code should be moved to the
474 **** respective files on a per subsystem basis.
475 ****
476 ***************************************************************************
477 */
478
479
480/*
481 ***************************************************************************
482 ****
483 **** The following code probably belongs in another file, like
484 **** kern/init_init.c.
485 ****
486 ***************************************************************************
487 */
488
489/*
490 * List of paths to try when searching for "init".
491 */
492static char init_path[MAXPATHLEN] =
493#ifdef	INIT_PATH
494    __XSTRING(INIT_PATH);
495#else
496    "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init:/stand/sysinstall";
497#endif
498SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0,
499	"Path used to search the init process");
500
501/*
502 * Start the initial user process; try exec'ing each pathname in init_path.
503 * The program is invoked with one argument containing the boot flags.
504 */
505static void
506start_init(void *dummy)
507{
508	vm_offset_t addr;
509	struct execve_args args;
510	int options, error;
511	char *var, *path, *next, *s;
512	char *ucp, **uap, *arg0, *arg1;
513	struct thread *td;
514	struct proc *p;
515
516	mtx_lock(&Giant);
517
518	GIANT_REQUIRED;
519
520	td = curthread;
521	p = td->td_proc;
522
523	vfs_mountroot();
524
525#ifdef MAC
526	mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist));
527#endif
528
529	/*
530	 * Need just enough stack to hold the faked-up "execve()" arguments.
531	 */
532	addr = p->p_sysent->sv_usrstack - PAGE_SIZE;
533	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE,
534			FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
535		panic("init: couldn't allocate argument space");
536	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
537	p->p_vmspace->vm_ssize = 1;
538
539	if ((var = getenv("init_path")) != NULL) {
540		strlcpy(init_path, var, sizeof(init_path));
541		freeenv(var);
542	}
543
544	for (path = init_path; *path != '\0'; path = next) {
545		while (*path == ':')
546			path++;
547		if (*path == '\0')
548			break;
549		for (next = path; *next != '\0' && *next != ':'; next++)
550			/* nothing */ ;
551		if (bootverbose)
552			printf("start_init: trying %.*s\n", (int)(next - path),
553			    path);
554
555		/*
556		 * Move out the boot flag argument.
557		 */
558		options = 0;
559		ucp = (char *)p->p_sysent->sv_usrstack;
560		(void)subyte(--ucp, 0);		/* trailing zero */
561		if (boothowto & RB_SINGLE) {
562			(void)subyte(--ucp, 's');
563			options = 1;
564		}
565#ifdef notyet
566                if (boothowto & RB_FASTBOOT) {
567			(void)subyte(--ucp, 'f');
568			options = 1;
569		}
570#endif
571
572#ifdef BOOTCDROM
573		(void)subyte(--ucp, 'C');
574		options = 1;
575#endif
576
577		if (options == 0)
578			(void)subyte(--ucp, '-');
579		(void)subyte(--ucp, '-');		/* leading hyphen */
580		arg1 = ucp;
581
582		/*
583		 * Move out the file name (also arg 0).
584		 */
585		(void)subyte(--ucp, 0);
586		for (s = next - 1; s >= path; s--)
587			(void)subyte(--ucp, *s);
588		arg0 = ucp;
589
590		/*
591		 * Move out the arg pointers.
592		 */
593		uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1));
594		(void)suword((caddr_t)--uap, (long)0);	/* terminator */
595		(void)suword((caddr_t)--uap, (long)(intptr_t)arg1);
596		(void)suword((caddr_t)--uap, (long)(intptr_t)arg0);
597
598		/*
599		 * Point at the arguments.
600		 */
601		args.fname = arg0;
602		args.argv = uap;
603		args.envv = NULL;
604
605		/*
606		 * Now try to exec the program.  If can't for any reason
607		 * other than it doesn't exist, complain.
608		 *
609		 * Otherwise, return via fork_trampoline() all the way
610		 * to user mode as init!
611		 */
612		if ((error = execve(td, &args)) == 0) {
613			mtx_unlock(&Giant);
614			return;
615		}
616		if (error != ENOENT)
617			printf("exec %.*s: error %d\n", (int)(next - path),
618			    path, error);
619	}
620	printf("init: not found in path %s\n", init_path);
621	panic("no init");
622}
623
624/*
625 * Like kthread_create(), but runs in it's own address space.
626 * We do this early to reserve pid 1.
627 *
628 * Note special case - do not make it runnable yet.  Other work
629 * in progress will change this more.
630 */
631static void
632create_init(const void *udata __unused)
633{
634	struct ucred *newcred, *oldcred;
635	int error;
636
637	error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc);
638	if (error)
639		panic("cannot fork init: %d\n", error);
640	KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
641	/* divorce init's credentials from the kernel's */
642	newcred = crget();
643	PROC_LOCK(initproc);
644	initproc->p_flag |= P_SYSTEM;
645	oldcred = initproc->p_ucred;
646	crcopy(newcred, oldcred);
647#ifdef MAC
648	mac_create_proc1(newcred);
649#endif
650	initproc->p_ucred = newcred;
651	PROC_UNLOCK(initproc);
652	crfree(oldcred);
653	cred_update_thread(FIRST_THREAD_IN_PROC(initproc));
654	mtx_lock_spin(&sched_lock);
655	initproc->p_sflag |= PS_INMEM;
656	mtx_unlock_spin(&sched_lock);
657	cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);
658}
659SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)
660
661/*
662 * Make it runnable now.
663 */
664static void
665kick_init(const void *udata __unused)
666{
667	struct thread *td;
668
669	td = FIRST_THREAD_IN_PROC(initproc);
670	mtx_lock_spin(&sched_lock);
671	TD_SET_CAN_RUN(td);
672	setrunqueue(td, SRQ_BORING);	/* XXXKSE */
673	mtx_unlock_spin(&sched_lock);
674}
675SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL)
676