19454b2d8SWarner Losh /*- 22b14f991SJulian Elischer * Copyright (c) 1995 Terrence R. Lambert 32b14f991SJulian Elischer * All rights reserved. 42b14f991SJulian Elischer * 5df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 6df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 7df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 8df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 9df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 10df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 12df8bae1dSRodney W. Grimes * 13df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 14df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 15df8bae1dSRodney W. Grimes * are met: 16df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 18df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 19df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 20df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 21df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 22df8bae1dSRodney W. Grimes * must display the following acknowledgement: 23df8bae1dSRodney W. Grimes * This product includes software developed by the University of 24df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 25df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 26df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 27df8bae1dSRodney W. Grimes * without specific prior written permission. 28df8bae1dSRodney W. Grimes * 29df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39df8bae1dSRodney W. Grimes * SUCH DAMAGE. 40df8bae1dSRodney W. Grimes * 41df8bae1dSRodney W. Grimes * @(#)init_main.c 8.9 (Berkeley) 1/21/94 42df8bae1dSRodney W. Grimes */ 43df8bae1dSRodney W. Grimes 44677b542eSDavid E. O'Brien #include <sys/cdefs.h> 45677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 46677b542eSDavid E. O'Brien 4777fe4438SBenno Rice #include "opt_ddb.h" 4867481196SJohn Birrell #include "opt_init_path.h" 4940244964SRobert Watson #include "opt_mac.h" 504bd49128SPeter Wemm 51df8bae1dSRodney W. Grimes #include <sys/param.h> 529e209b12SAlfred Perlstein #include <sys/kernel.h> 53f36ba452SJake Burkholder #include <sys/exec.h> 54b3c5c18dSBruce Evans #include <sys/file.h> 55df8bae1dSRodney W. Grimes #include <sys/filedesc.h> 560384fff8SJason Evans #include <sys/ktr.h> 571005a129SJohn Baldwin #include <sys/lock.h> 5840244964SRobert Watson #include <sys/mac.h> 59ac0ad63fSBruce Evans #include <sys/mount.h> 6035e0e5b3SJohn Baldwin #include <sys/mutex.h> 618f19eb88SIan Dowse #include <sys/syscallsubr.h> 62946bb7a2SPoul-Henning Kamp #include <sys/sysctl.h> 63df8bae1dSRodney W. Grimes #include <sys/proc.h> 64df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 65df8bae1dSRodney W. Grimes #include <sys/systm.h> 6636240ea5SDoug Rabson #include <sys/signalvar.h> 67df8bae1dSRodney W. Grimes #include <sys/vnode.h> 68f3f0ca60SSøren Schmidt #include <sys/sysent.h> 69df8bae1dSRodney W. Grimes #include <sys/reboot.h> 70de028f5aSJeff Roberson #include <sys/sched.h> 711005a129SJohn Baldwin #include <sys/sx.h> 72ad7507e2SSteven Wallace #include <sys/sysproto.h> 73efeaf95aSDavid Greenman #include <sys/vmmeter.h> 7474b2192aSJohn Dyson #include <sys/unistd.h> 7594e9d7c1SPeter Wemm #include <sys/malloc.h> 76db901281SPoul-Henning Kamp #include <sys/conf.h> 77df8bae1dSRodney W. Grimes 78df8bae1dSRodney W. Grimes #include <machine/cpu.h> 79df8bae1dSRodney W. Grimes 803683665bSRobert Watson #include <security/audit/audit.h> 813683665bSRobert Watson 82df8bae1dSRodney W. Grimes #include <vm/vm.h> 83efeaf95aSDavid Greenman #include <vm/vm_param.h> 84efeaf95aSDavid Greenman #include <vm/pmap.h> 85efeaf95aSDavid Greenman #include <vm/vm_map.h> 866faaa756SWolfram Schneider #include <sys/copyright.h> 87df8bae1dSRodney W. Grimes 8826ab616fSBenno Rice #include <ddb/ddb.h> 8926ab616fSBenno Rice #include <ddb/db_sym.h> 9026ab616fSBenno Rice 9137b087a6SPeter Wemm void mi_startup(void); /* Should be elsewhere */ 92df8bae1dSRodney W. Grimes 93df8bae1dSRodney W. Grimes /* Components of the first process -- never freed. */ 94154c04e5SPoul-Henning Kamp static struct session session0; 95154c04e5SPoul-Henning Kamp static struct pgrp pgrp0; 96df8bae1dSRodney W. Grimes struct proc proc0; 972a3b1065SOlivier Houchard struct thread thread0 __aligned(8); 984f0db5e0SJulian Elischer struct ksegrp ksegrp0; 9923734995SJake Burkholder struct vmspace vmspace0; 1002b14f991SJulian Elischer struct proc *initproc; 101df8bae1dSRodney W. Grimes 102c463cf1cSBruce Evans int boothowto = 0; /* initialized so that it can be patched */ 1038d0bf3d6SJordan K. Hubbard SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); 1047a08bae6SJohn Baldwin int bootverbose; 1057a08bae6SJohn Baldwin SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, ""); 106946bb7a2SPoul-Henning Kamp 1072b14f991SJulian Elischer /* 1082b14f991SJulian Elischer * This ensures that there is at least one entry so that the sysinit_set 1092b14f991SJulian Elischer * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never 1102b14f991SJulian Elischer * executed. 11126f9a767SRodney W. Grimes */ 1122b14f991SJulian Elischer SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL) 1138a129caeSDavid Greenman 11494e9d7c1SPeter Wemm /* 11594e9d7c1SPeter Wemm * The sysinit table itself. Items are checked off as the are run. 11694e9d7c1SPeter Wemm * If we want to register new sysinit types, add them to newsysinit. 11794e9d7c1SPeter Wemm */ 118f41325dbSPeter Wemm SET_DECLARE(sysinit_set, struct sysinit); 119f41325dbSPeter Wemm struct sysinit **sysinit, **sysinit_end; 120f41325dbSPeter Wemm struct sysinit **newsysinit, **newsysinit_end; 12194e9d7c1SPeter Wemm 12294e9d7c1SPeter Wemm /* 12394e9d7c1SPeter Wemm * Merge a new sysinit set into the current set, reallocating it if 12494e9d7c1SPeter Wemm * necessary. This can only be called after malloc is running. 12594e9d7c1SPeter Wemm */ 12694e9d7c1SPeter Wemm void 127f41325dbSPeter Wemm sysinit_add(struct sysinit **set, struct sysinit **set_end) 12894e9d7c1SPeter Wemm { 12994e9d7c1SPeter Wemm struct sysinit **newset; 13094e9d7c1SPeter Wemm struct sysinit **sipp; 13194e9d7c1SPeter Wemm struct sysinit **xipp; 132f41325dbSPeter Wemm int count; 13394e9d7c1SPeter Wemm 134f41325dbSPeter Wemm count = set_end - set; 135ddd62546SPeter Wemm if (newsysinit) 136f41325dbSPeter Wemm count += newsysinit_end - newsysinit; 137ddd62546SPeter Wemm else 138f41325dbSPeter Wemm count += sysinit_end - sysinit; 13994e9d7c1SPeter Wemm newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); 14094e9d7c1SPeter Wemm if (newset == NULL) 14194e9d7c1SPeter Wemm panic("cannot malloc for sysinit"); 14294e9d7c1SPeter Wemm xipp = newset; 143ddd62546SPeter Wemm if (newsysinit) 144f41325dbSPeter Wemm for (sipp = newsysinit; sipp < newsysinit_end; sipp++) 145ddd62546SPeter Wemm *xipp++ = *sipp; 146ddd62546SPeter Wemm else 147f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) 14894e9d7c1SPeter Wemm *xipp++ = *sipp; 149f41325dbSPeter Wemm for (sipp = set; sipp < set_end; sipp++) 15094e9d7c1SPeter Wemm *xipp++ = *sipp; 151ddd62546SPeter Wemm if (newsysinit) 152ddd62546SPeter Wemm free(newsysinit, M_TEMP); 15394e9d7c1SPeter Wemm newsysinit = newset; 154f41325dbSPeter Wemm newsysinit_end = newset + count; 15594e9d7c1SPeter Wemm } 15626f9a767SRodney W. Grimes 157df8bae1dSRodney W. Grimes /* 158df8bae1dSRodney W. Grimes * System startup; initialize the world, create process 0, mount root 159df8bae1dSRodney W. Grimes * filesystem, and fork to create init and pagedaemon. Most of the 160df8bae1dSRodney W. Grimes * hard work is done in the lower-level initialization routines including 161df8bae1dSRodney W. Grimes * startup(), which does memory initialization and autoconfiguration. 1622b14f991SJulian Elischer * 1632b14f991SJulian Elischer * This allows simple addition of new kernel subsystems that require 1642b14f991SJulian Elischer * boot time initialization. It also allows substitution of subsystem 1652b14f991SJulian Elischer * (for instance, a scheduler, kernel profiler, or VM system) by object 166c5b193bfSPoul-Henning Kamp * module. Finally, it allows for optional "kernel threads". 167df8bae1dSRodney W. Grimes */ 16826f9a767SRodney W. Grimes void 16937b087a6SPeter Wemm mi_startup(void) 170df8bae1dSRodney W. Grimes { 1712b14f991SJulian Elischer 1722b14f991SJulian Elischer register struct sysinit **sipp; /* system initialization*/ 1732b14f991SJulian Elischer register struct sysinit **xipp; /* interior loop of sort*/ 1742b14f991SJulian Elischer register struct sysinit *save; /* bubble*/ 1752b14f991SJulian Elischer 17626ab616fSBenno Rice #if defined(VERBOSE_SYSINIT) 17726ab616fSBenno Rice int last; 17826ab616fSBenno Rice int verbose; 17926ab616fSBenno Rice #endif 18026ab616fSBenno Rice 181f41325dbSPeter Wemm if (sysinit == NULL) { 182f41325dbSPeter Wemm sysinit = SET_BEGIN(sysinit_set); 183f41325dbSPeter Wemm sysinit_end = SET_LIMIT(sysinit_set); 184f41325dbSPeter Wemm } 185f41325dbSPeter Wemm 18694e9d7c1SPeter Wemm restart: 1872b14f991SJulian Elischer /* 1882b14f991SJulian Elischer * Perform a bubble sort of the system initialization objects by 1892b14f991SJulian Elischer * their subsystem (primary key) and order (secondary key). 1902b14f991SJulian Elischer */ 191f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 192f41325dbSPeter Wemm for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { 1932b14f991SJulian Elischer if ((*sipp)->subsystem < (*xipp)->subsystem || 1942b14f991SJulian Elischer ((*sipp)->subsystem == (*xipp)->subsystem && 195af4b2d2dSPeter Wemm (*sipp)->order <= (*xipp)->order)) 1962b14f991SJulian Elischer continue; /* skip*/ 1972b14f991SJulian Elischer save = *sipp; 1982b14f991SJulian Elischer *sipp = *xipp; 1992b14f991SJulian Elischer *xipp = save; 2002b14f991SJulian Elischer } 2012b14f991SJulian Elischer } 2022b14f991SJulian Elischer 20326ab616fSBenno Rice #if defined(VERBOSE_SYSINIT) 20426ab616fSBenno Rice last = SI_SUB_COPYRIGHT; 20526ab616fSBenno Rice verbose = 0; 20626ab616fSBenno Rice #if !defined(DDB) 20726ab616fSBenno Rice printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n"); 20826ab616fSBenno Rice #endif 20926ab616fSBenno Rice #endif 21026ab616fSBenno Rice 2112b14f991SJulian Elischer /* 2122b14f991SJulian Elischer * Traverse the (now) ordered list of system initialization tasks. 2132b14f991SJulian Elischer * Perform each task, and continue on to the next task. 2142b14f991SJulian Elischer * 2152b14f991SJulian Elischer * The last item on the list is expected to be the scheduler, 2162b14f991SJulian Elischer * which will not return. 2172b14f991SJulian Elischer */ 218f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 21974b2192aSJohn Dyson 2202b14f991SJulian Elischer if ((*sipp)->subsystem == SI_SUB_DUMMY) 2212b14f991SJulian Elischer continue; /* skip dummy task(s)*/ 2222b14f991SJulian Elischer 22394e9d7c1SPeter Wemm if ((*sipp)->subsystem == SI_SUB_DONE) 22494e9d7c1SPeter Wemm continue; 22594e9d7c1SPeter Wemm 22626ab616fSBenno Rice #if defined(VERBOSE_SYSINIT) 22726ab616fSBenno Rice if ((*sipp)->subsystem > last) { 22826ab616fSBenno Rice verbose = 1; 22926ab616fSBenno Rice last = (*sipp)->subsystem; 23026ab616fSBenno Rice printf("subsystem %x\n", last); 23126ab616fSBenno Rice } 23226ab616fSBenno Rice if (verbose) { 23326ab616fSBenno Rice #if defined(DDB) 23426ab616fSBenno Rice const char *name; 23526ab616fSBenno Rice c_db_sym_t sym; 23626ab616fSBenno Rice db_expr_t offset; 23726ab616fSBenno Rice 23826ab616fSBenno Rice sym = db_search_symbol((vm_offset_t)(*sipp)->func, 23926ab616fSBenno Rice DB_STGY_PROC, &offset); 24026ab616fSBenno Rice db_symbol_values(sym, &name, NULL); 24126ab616fSBenno Rice if (name != NULL) 24226ab616fSBenno Rice printf(" %s(%p)... ", name, (*sipp)->udata); 24326ab616fSBenno Rice else 24426ab616fSBenno Rice #endif 24526ab616fSBenno Rice printf(" %p(%p)... ", (*sipp)->func, 24626ab616fSBenno Rice (*sipp)->udata); 24726ab616fSBenno Rice } 24826ab616fSBenno Rice #endif 24926ab616fSBenno Rice 2509c8b8baaSPeter Wemm /* Call function */ 2512b14f991SJulian Elischer (*((*sipp)->func))((*sipp)->udata); 25294e9d7c1SPeter Wemm 25326ab616fSBenno Rice #if defined(VERBOSE_SYSINIT) 25426ab616fSBenno Rice if (verbose) 25526ab616fSBenno Rice printf("done.\n"); 25626ab616fSBenno Rice #endif 25726ab616fSBenno Rice 25894e9d7c1SPeter Wemm /* Check off the one we're just done */ 25994e9d7c1SPeter Wemm (*sipp)->subsystem = SI_SUB_DONE; 26094e9d7c1SPeter Wemm 26194e9d7c1SPeter Wemm /* Check if we've installed more sysinit items via KLD */ 26294e9d7c1SPeter Wemm if (newsysinit != NULL) { 263f41325dbSPeter Wemm if (sysinit != SET_BEGIN(sysinit_set)) 26494e9d7c1SPeter Wemm free(sysinit, M_TEMP); 26594e9d7c1SPeter Wemm sysinit = newsysinit; 266f41325dbSPeter Wemm sysinit_end = newsysinit_end; 26794e9d7c1SPeter Wemm newsysinit = NULL; 268f41325dbSPeter Wemm newsysinit_end = NULL; 26994e9d7c1SPeter Wemm goto restart; 27094e9d7c1SPeter Wemm } 2712b14f991SJulian Elischer } 2722b14f991SJulian Elischer 273477a642cSPeter Wemm panic("Shouldn't get here!"); 2742b14f991SJulian Elischer /* NOTREACHED*/ 2752b14f991SJulian Elischer } 2762b14f991SJulian Elischer 2772b14f991SJulian Elischer 2782b14f991SJulian Elischer /* 2792b14f991SJulian Elischer *************************************************************************** 2802b14f991SJulian Elischer **** 2812b14f991SJulian Elischer **** The following SYSINIT's belong elsewhere, but have not yet 2822b14f991SJulian Elischer **** been moved. 2832b14f991SJulian Elischer **** 2842b14f991SJulian Elischer *************************************************************************** 2852b14f991SJulian Elischer */ 2869ef6c28aSBruce Evans static void 28737b087a6SPeter Wemm print_caddr_t(void *data __unused) 2889ef6c28aSBruce Evans { 2899ef6c28aSBruce Evans printf("%s", (char *)data); 2909ef6c28aSBruce Evans } 291d841aaa7SBruce Evans SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 2927a08bae6SJohn Baldwin SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version) 2937a08bae6SJohn Baldwin 2942cf6bdacSPoul-Henning Kamp #ifdef WITNESS 2952cf6bdacSPoul-Henning Kamp static char wit_warn[] = 2962cf6bdacSPoul-Henning Kamp "WARNING: WITNESS option enabled, expect reduced performance.\n"; 2972cf6bdacSPoul-Henning Kamp SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 1, 2982cf6bdacSPoul-Henning Kamp print_caddr_t, wit_warn) 2992cf6bdacSPoul-Henning Kamp #endif 3002cf6bdacSPoul-Henning Kamp 3012cf6bdacSPoul-Henning Kamp #ifdef DIAGNOSTIC 3022cf6bdacSPoul-Henning Kamp static char diag_warn[] = 3032cf6bdacSPoul-Henning Kamp "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n"; 3042cf6bdacSPoul-Henning Kamp SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 2, 3052cf6bdacSPoul-Henning Kamp print_caddr_t, diag_warn) 3062cf6bdacSPoul-Henning Kamp #endif 3072cf6bdacSPoul-Henning Kamp 3087a08bae6SJohn Baldwin static void 3097a08bae6SJohn Baldwin set_boot_verbose(void *data __unused) 3107a08bae6SJohn Baldwin { 3117a08bae6SJohn Baldwin 3127a08bae6SJohn Baldwin if (boothowto & RB_VERBOSE) 3137a08bae6SJohn Baldwin bootverbose++; 3147a08bae6SJohn Baldwin } 3157a08bae6SJohn Baldwin SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL) 3162b14f991SJulian Elischer 317f36ba452SJake Burkholder struct sysentvec null_sysvec = { 318f36ba452SJake Burkholder 0, 319f36ba452SJake Burkholder NULL, 320f36ba452SJake Burkholder 0, 321f36ba452SJake Burkholder 0, 322f36ba452SJake Burkholder NULL, 323f36ba452SJake Burkholder 0, 324f36ba452SJake Burkholder NULL, 325f36ba452SJake Burkholder NULL, 326f36ba452SJake Burkholder NULL, 327f36ba452SJake Burkholder NULL, 328f36ba452SJake Burkholder NULL, 329f36ba452SJake Burkholder NULL, 330f36ba452SJake Burkholder NULL, 331f36ba452SJake Burkholder "null", 332f36ba452SJake Burkholder NULL, 333f36ba452SJake Burkholder NULL, 334f36ba452SJake Burkholder 0, 335f36ba452SJake Burkholder PAGE_SIZE, 336f36ba452SJake Burkholder VM_MIN_ADDRESS, 337f36ba452SJake Burkholder VM_MAXUSER_ADDRESS, 338f36ba452SJake Burkholder USRSTACK, 339f36ba452SJake Burkholder PS_STRINGS, 340f36ba452SJake Burkholder VM_PROT_ALL, 341f36ba452SJake Burkholder NULL, 342c460ac3aSPeter Wemm NULL, 343f36ba452SJake Burkholder NULL 344f36ba452SJake Burkholder }; 3453ebc1248SPeter Wemm 3462b14f991SJulian Elischer /* 3472b14f991SJulian Elischer *************************************************************************** 3482b14f991SJulian Elischer **** 3490c920c0dSGiorgos Keramidas **** The two following SYSINIT's are proc0 specific glue code. I am not 3502b14f991SJulian Elischer **** convinced that they can not be safely combined, but their order of 3512b14f991SJulian Elischer **** operation has been maintained as the same as the original init_main.c 3522b14f991SJulian Elischer **** for right now. 3532b14f991SJulian Elischer **** 3542b14f991SJulian Elischer **** These probably belong in init_proc.c or kern_proc.c, since they 3552b14f991SJulian Elischer **** deal with proc0 (the fork template process). 3562b14f991SJulian Elischer **** 3572b14f991SJulian Elischer *************************************************************************** 3582b14f991SJulian Elischer */ 3592b14f991SJulian Elischer /* ARGSUSED*/ 360154c04e5SPoul-Henning Kamp static void 36137b087a6SPeter Wemm proc0_init(void *dummy __unused) 3622b14f991SJulian Elischer { 3638ec21e3aSPoul-Henning Kamp struct proc *p; 3648ec21e3aSPoul-Henning Kamp unsigned i; 365b40ce416SJulian Elischer struct thread *td; 366079b7badSJulian Elischer struct ksegrp *kg; 367df8bae1dSRodney W. Grimes 3680cddd8f0SMatthew Dillon GIANT_REQUIRED; 369df8bae1dSRodney W. Grimes p = &proc0; 370079b7badSJulian Elischer td = &thread0; 3714f0db5e0SJulian Elischer kg = &ksegrp0; 372df8bae1dSRodney W. Grimes 373df8bae1dSRodney W. Grimes /* 3740384fff8SJason Evans * Initialize magic number. 3750384fff8SJason Evans */ 3760384fff8SJason Evans p->p_magic = P_MAGIC; 3770384fff8SJason Evans 3780384fff8SJason Evans /* 379ed062c8dSJulian Elischer * Initialize thread, process and ksegrp structures. 380a3bfb996SJeffrey Hsu */ 381ed062c8dSJulian Elischer procinit(); /* set up proc zone */ 382ed062c8dSJulian Elischer threadinit(); /* set up thead, upcall and KSEGRP zones */ 383a3bfb996SJeffrey Hsu 384a3bfb996SJeffrey Hsu /* 385ed062c8dSJulian Elischer * Initialise scheduler resources. 386ed062c8dSJulian Elischer * Add scheduler specific parts to proc, ksegrp, thread as needed. 387ed062c8dSJulian Elischer */ 388ed062c8dSJulian Elischer schedinit(); /* scheduler gets its house in order */ 389ed062c8dSJulian Elischer /* 390b1508c72SDavid Greenman * Initialize sleep queue hash table 391b1508c72SDavid Greenman */ 392b1508c72SDavid Greenman sleepinit(); 393b1508c72SDavid Greenman 394b1508c72SDavid Greenman /* 3953075778bSJohn Dyson * additional VM structures 3963075778bSJohn Dyson */ 3973075778bSJohn Dyson vm_init2(); 3983075778bSJohn Dyson 3993075778bSJohn Dyson /* 400df8bae1dSRodney W. Grimes * Create process 0 (the swapper). 401df8bae1dSRodney W. Grimes */ 402a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&allproc, p, p_list); 4037b531e60SJohn Baldwin LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); 4046008862bSJohn Baldwin mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); 405df8bae1dSRodney W. Grimes p->p_pgrp = &pgrp0; 406a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 407a3bfb996SJeffrey Hsu LIST_INIT(&pgrp0.pg_members); 408a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 409a3bfb996SJeffrey Hsu 410df8bae1dSRodney W. Grimes pgrp0.pg_session = &session0; 4116008862bSJohn Baldwin mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); 412df8bae1dSRodney W. Grimes session0.s_count = 1; 413df8bae1dSRodney W. Grimes session0.s_leader = p; 414df8bae1dSRodney W. Grimes 4153ebc1248SPeter Wemm p->p_sysent = &null_sysvec; 416f202965eSJohn Baldwin p->p_flag = P_SYSTEM; 417f202965eSJohn Baldwin p->p_sflag = PS_INMEM; 418e602ba25SJulian Elischer p->p_state = PRS_NORMAL; 419571dcd15SSuleiman Souhlal knlist_init(&p->p_klist, &p->p_mtx, NULL, NULL, NULL); 4202c255e9dSRobert Watson STAILQ_INIT(&p->p_ktr); 421fa885116SJulian Elischer p->p_nice = NZERO; 422e602ba25SJulian Elischer td->td_state = TDS_RUNNING; 4232c100766SJulian Elischer kg->kg_pri_class = PRI_TIMESHARE; 4242c100766SJulian Elischer kg->kg_user_pri = PUSER; 4252c100766SJulian Elischer td->td_priority = PVM; 4262c100766SJulian Elischer td->td_base_pri = PUSER; 427060563ecSJulian Elischer td->td_oncpu = 0; 4282c1011f7SJohn Dyson p->p_peers = 0; 4292c1011f7SJohn Dyson p->p_leader = p; 430e602ba25SJulian Elischer 4312c1011f7SJohn Dyson 432df8bae1dSRodney W. Grimes bcopy("swapper", p->p_comm, sizeof ("swapper")); 433df8bae1dSRodney W. Grimes 434c06eb4e2SSam Leffler callout_init(&p->p_itcallout, CALLOUT_MPSAFE); 435c06eb4e2SSam Leffler callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); 4364f559836SJake Burkholder 437df8bae1dSRodney W. Grimes /* Create credentials. */ 438df8bae1dSRodney W. Grimes p->p_ucred = crget(); 439df8bae1dSRodney W. Grimes p->p_ucred->cr_ngroups = 1; /* group 0 */ 440f535380cSDon Lewis p->p_ucred->cr_uidinfo = uifind(0); 441b1fc0ec1SRobert Watson p->p_ucred->cr_ruidinfo = uifind(0); 44291421ba2SRobert Watson p->p_ucred->cr_prison = NULL; /* Don't jail it. */ 4433683665bSRobert Watson #ifdef AUDIT 4443683665bSRobert Watson audit_proc_alloc(p); 4453683665bSRobert Watson audit_proc_kproc0(p); 4463683665bSRobert Watson #endif 44740244964SRobert Watson #ifdef MAC 44840244964SRobert Watson mac_create_proc0(p->p_ucred); 44940244964SRobert Watson #endif 4508e2e767bSJohn Baldwin td->td_ucred = crhold(p->p_ucred); 45175c13541SPoul-Henning Kamp 45290af4afaSJohn Baldwin /* Create sigacts. */ 45390af4afaSJohn Baldwin p->p_sigacts = sigacts_alloc(); 4546626c604SJulian Elischer 45537b087a6SPeter Wemm /* Initialize signal state for process 0. */ 45637b087a6SPeter Wemm siginit(&proc0); 45737b087a6SPeter Wemm 458df8bae1dSRodney W. Grimes /* Create the file descriptor table. */ 4598ec21e3aSPoul-Henning Kamp p->p_fd = fdinit(NULL); 460ad05d580STor Egge p->p_fdtol = NULL; 461df8bae1dSRodney W. Grimes 462df8bae1dSRodney W. Grimes /* Create the limits structures. */ 46391d5354aSJohn Baldwin p->p_limit = lim_alloc(); 46491d5354aSJohn Baldwin for (i = 0; i < RLIM_NLIMITS; i++) 46591d5354aSJohn Baldwin p->p_limit->pl_rlimit[i].rlim_cur = 46691d5354aSJohn Baldwin p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY; 46791d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur = 46891d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; 46991d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur = 47091d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 471df8bae1dSRodney W. Grimes i = ptoa(cnt.v_free_count); 47291d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = i; 47391d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 47491d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 4755715307fSJohn Baldwin p->p_cpulimit = RLIM_INFINITY; 476df8bae1dSRodney W. Grimes 4778b059651SDavid Schultz p->p_stats = pstats_alloc(); 4788b059651SDavid Schultz 479df8bae1dSRodney W. Grimes /* Allocate a prototype map so we have something to fork. */ 480b1028ad1SLuoqi Chen pmap_pinit0(vmspace_pmap(&vmspace0)); 481df8bae1dSRodney W. Grimes p->p_vmspace = &vmspace0; 482df8bae1dSRodney W. Grimes vmspace0.vm_refcnt = 1; 48305ba50f5SJake Burkholder vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser, 48405ba50f5SJake Burkholder p->p_sysent->sv_maxuser); 485b1028ad1SLuoqi Chen vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 486df8bae1dSRodney W. Grimes 48739fb8e6bSJulian Elischer /* 488a3bfb996SJeffrey Hsu * Charge root for one process. 489df8bae1dSRodney W. Grimes */ 490b1fc0ec1SRobert Watson (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); 49126f9a767SRodney W. Grimes } 4922b14f991SJulian Elischer SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 4932b14f991SJulian Elischer 4942b14f991SJulian Elischer /* ARGSUSED*/ 495154c04e5SPoul-Henning Kamp static void 49637b087a6SPeter Wemm proc0_post(void *dummy __unused) 4972b14f991SJulian Elischer { 49800af9731SPoul-Henning Kamp struct timespec ts; 49937b087a6SPeter Wemm struct proc *p; 500a6fc8288SPeter Wemm 5012b14f991SJulian Elischer /* 5021b0b259eSBruce Evans * Now we can look at the time, having had a chance to verify the 5031b0b259eSBruce Evans * time from the filesystem. Pretend that proc0 started now. 5042b14f991SJulian Elischer */ 5051005a129SJohn Baldwin sx_slock(&allproc_lock); 50637b087a6SPeter Wemm LIST_FOREACH(p, &allproc, p_list) { 50787ccef7bSDag-Erling Smørgrav microuptime(&p->p_stats->p_start); 5085b1a8eb3SPoul-Henning Kamp p->p_rux.rux_runtime = 0; 50937b087a6SPeter Wemm } 5101005a129SJohn Baldwin sx_sunlock(&allproc_lock); 5115b1a8eb3SPoul-Henning Kamp PCPU_SET(switchtime, cpu_ticks()); 5120384fff8SJason Evans PCPU_SET(switchticks, ticks); 5132b14f991SJulian Elischer 514a6fc8288SPeter Wemm /* 515a6fc8288SPeter Wemm * Give the ``random'' number generator a thump. 516a6fc8288SPeter Wemm */ 51700af9731SPoul-Henning Kamp nanotime(&ts); 51800af9731SPoul-Henning Kamp srandom(ts.tv_sec ^ ts.tv_nsec); 5192b14f991SJulian Elischer } 5202b14f991SJulian Elischer SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 5212b14f991SJulian Elischer 522df8bae1dSRodney W. Grimes /* 5232b14f991SJulian Elischer *************************************************************************** 5242b14f991SJulian Elischer **** 5252b14f991SJulian Elischer **** The following SYSINIT's and glue code should be moved to the 5262b14f991SJulian Elischer **** respective files on a per subsystem basis. 5272b14f991SJulian Elischer **** 5282b14f991SJulian Elischer *************************************************************************** 529df8bae1dSRodney W. Grimes */ 530df8bae1dSRodney W. Grimes 531df8bae1dSRodney W. Grimes 532df8bae1dSRodney W. Grimes /* 5332b14f991SJulian Elischer *************************************************************************** 5342b14f991SJulian Elischer **** 5352b14f991SJulian Elischer **** The following code probably belongs in another file, like 53637b087a6SPeter Wemm **** kern/init_init.c. 5372b14f991SJulian Elischer **** 5382b14f991SJulian Elischer *************************************************************************** 539df8bae1dSRodney W. Grimes */ 540df8bae1dSRodney W. Grimes 541df8bae1dSRodney W. Grimes /* 542df8bae1dSRodney W. Grimes * List of paths to try when searching for "init". 543df8bae1dSRodney W. Grimes */ 5445f967b24SDag-Erling Smørgrav static char init_path[MAXPATHLEN] = 54567481196SJohn Birrell #ifdef INIT_PATH 54667481196SJohn Birrell __XSTRING(INIT_PATH); 54767481196SJohn Birrell #else 548f3f4baf0SDag-Erling Smørgrav "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init:/stand/sysinstall"; 54967481196SJohn Birrell #endif 550af1408e3SLuigi Rizzo SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, 551af1408e3SLuigi Rizzo "Path used to search the init process"); 552df8bae1dSRodney W. Grimes 553df8bae1dSRodney W. Grimes /* 554724447acSRalf S. Engelschall * Shutdown timeout of init(8). 555724447acSRalf S. Engelschall * Unused within kernel, but used to control init(8), hence do not remove. 556724447acSRalf S. Engelschall */ 557724447acSRalf S. Engelschall #ifndef INIT_SHUTDOWN_TIMEOUT 558724447acSRalf S. Engelschall #define INIT_SHUTDOWN_TIMEOUT 120 559724447acSRalf S. Engelschall #endif 560724447acSRalf S. Engelschall static int init_shutdown_timeout = INIT_SHUTDOWN_TIMEOUT; 561724447acSRalf S. Engelschall SYSCTL_INT(_kern, OID_AUTO, init_shutdown_timeout, 562724447acSRalf S. Engelschall CTLFLAG_RW, &init_shutdown_timeout, 0, ""); 563724447acSRalf S. Engelschall 564724447acSRalf S. Engelschall /* 5655f967b24SDag-Erling Smørgrav * Start the initial user process; try exec'ing each pathname in init_path. 566df8bae1dSRodney W. Grimes * The program is invoked with one argument containing the boot flags. 567df8bae1dSRodney W. Grimes */ 568df8bae1dSRodney W. Grimes static void 56937b087a6SPeter Wemm start_init(void *dummy) 570df8bae1dSRodney W. Grimes { 571df8bae1dSRodney W. Grimes vm_offset_t addr; 572df8bae1dSRodney W. Grimes struct execve_args args; 5735f967b24SDag-Erling Smørgrav int options, error; 5745f967b24SDag-Erling Smørgrav char *var, *path, *next, *s; 5755f967b24SDag-Erling Smørgrav char *ucp, **uap, *arg0, *arg1; 576b40ce416SJulian Elischer struct thread *td; 5779c8b8baaSPeter Wemm struct proc *p; 578df8bae1dSRodney W. Grimes 5799ed346baSBosko Milekic mtx_lock(&Giant); 5800384fff8SJason Evans 5810cddd8f0SMatthew Dillon GIANT_REQUIRED; 5820cddd8f0SMatthew Dillon 583b40ce416SJulian Elischer td = curthread; 584b40ce416SJulian Elischer p = td->td_proc; 585df8bae1dSRodney W. Grimes 586563af2ecSMaxime Henrion vfs_mountroot(); 587fb92273bSPoul-Henning Kamp 588b7116168SPeter Wemm /* 589df8bae1dSRodney W. Grimes * Need just enough stack to hold the faked-up "execve()" arguments. 590df8bae1dSRodney W. Grimes */ 59105ba50f5SJake Burkholder addr = p->p_sysent->sv_usrstack - PAGE_SIZE; 5925f967b24SDag-Erling Smørgrav if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 5935f967b24SDag-Erling Smørgrav FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 594df8bae1dSRodney W. Grimes panic("init: couldn't allocate argument space"); 595df8bae1dSRodney W. Grimes p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 59626f9a767SRodney W. Grimes p->p_vmspace->vm_ssize = 1; 597df8bae1dSRodney W. Grimes 5985f967b24SDag-Erling Smørgrav if ((var = getenv("init_path")) != NULL) { 599e80fb434SRobert Drehmel strlcpy(init_path, var, sizeof(init_path)); 600d786139cSMaxime Henrion freeenv(var); 6015f967b24SDag-Erling Smørgrav } 6025f967b24SDag-Erling Smørgrav 60367481196SJohn Birrell for (path = init_path; *path != '\0'; path = next) { 604e4082284SJohn Birrell while (*path == ':') 6055f967b24SDag-Erling Smørgrav path++; 60667481196SJohn Birrell if (*path == '\0') 6075f967b24SDag-Erling Smørgrav break; 608e4082284SJohn Birrell for (next = path; *next != '\0' && *next != ':'; next++) 6095f967b24SDag-Erling Smørgrav /* nothing */ ; 6105f967b24SDag-Erling Smørgrav if (bootverbose) 611ba41a07dSDmitrij Tejblum printf("start_init: trying %.*s\n", (int)(next - path), 612ba41a07dSDmitrij Tejblum path); 6135f967b24SDag-Erling Smørgrav 614df8bae1dSRodney W. Grimes /* 615df8bae1dSRodney W. Grimes * Move out the boot flag argument. 616df8bae1dSRodney W. Grimes */ 617df8bae1dSRodney W. Grimes options = 0; 61805ba50f5SJake Burkholder ucp = (char *)p->p_sysent->sv_usrstack; 619df8bae1dSRodney W. Grimes (void)subyte(--ucp, 0); /* trailing zero */ 620df8bae1dSRodney W. Grimes if (boothowto & RB_SINGLE) { 621df8bae1dSRodney W. Grimes (void)subyte(--ucp, 's'); 622df8bae1dSRodney W. Grimes options = 1; 623df8bae1dSRodney W. Grimes } 624df8bae1dSRodney W. Grimes #ifdef notyet 625df8bae1dSRodney W. Grimes if (boothowto & RB_FASTBOOT) { 626df8bae1dSRodney W. Grimes (void)subyte(--ucp, 'f'); 627df8bae1dSRodney W. Grimes options = 1; 628df8bae1dSRodney W. Grimes } 629df8bae1dSRodney W. Grimes #endif 63017755ac8SPoul-Henning Kamp 63117755ac8SPoul-Henning Kamp #ifdef BOOTCDROM 63217755ac8SPoul-Henning Kamp (void)subyte(--ucp, 'C'); 63317755ac8SPoul-Henning Kamp options = 1; 63417755ac8SPoul-Henning Kamp #endif 635db901281SPoul-Henning Kamp 636df8bae1dSRodney W. Grimes if (options == 0) 637df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); 638df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); /* leading hyphen */ 639df8bae1dSRodney W. Grimes arg1 = ucp; 640df8bae1dSRodney W. Grimes 641df8bae1dSRodney W. Grimes /* 642df8bae1dSRodney W. Grimes * Move out the file name (also arg 0). 643df8bae1dSRodney W. Grimes */ 6445f967b24SDag-Erling Smørgrav (void)subyte(--ucp, 0); 6455f967b24SDag-Erling Smørgrav for (s = next - 1; s >= path; s--) 6465f967b24SDag-Erling Smørgrav (void)subyte(--ucp, *s); 647df8bae1dSRodney W. Grimes arg0 = ucp; 648df8bae1dSRodney W. Grimes 649df8bae1dSRodney W. Grimes /* 650df8bae1dSRodney W. Grimes * Move out the arg pointers. 651df8bae1dSRodney W. Grimes */ 652a20d7755SDoug Rabson uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); 653c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)0); /* terminator */ 654c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); 655c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); 656df8bae1dSRodney W. Grimes 657df8bae1dSRodney W. Grimes /* 658df8bae1dSRodney W. Grimes * Point at the arguments. 659df8bae1dSRodney W. Grimes */ 660df8bae1dSRodney W. Grimes args.fname = arg0; 66126f9a767SRodney W. Grimes args.argv = uap; 66226f9a767SRodney W. Grimes args.envv = NULL; 663df8bae1dSRodney W. Grimes 664df8bae1dSRodney W. Grimes /* 665df8bae1dSRodney W. Grimes * Now try to exec the program. If can't for any reason 666df8bae1dSRodney W. Grimes * other than it doesn't exist, complain. 6672b14f991SJulian Elischer * 66837b087a6SPeter Wemm * Otherwise, return via fork_trampoline() all the way 6699c8b8baaSPeter Wemm * to user mode as init! 670df8bae1dSRodney W. Grimes */ 671b40ce416SJulian Elischer if ((error = execve(td, &args)) == 0) { 6729ed346baSBosko Milekic mtx_unlock(&Giant); 673df8bae1dSRodney W. Grimes return; 674db72809dSJohn Baldwin } 675df8bae1dSRodney W. Grimes if (error != ENOENT) 676ba41a07dSDmitrij Tejblum printf("exec %.*s: error %d\n", (int)(next - path), 677ba41a07dSDmitrij Tejblum path, error); 678df8bae1dSRodney W. Grimes } 679580e7e5aSGreg Lehey printf("init: not found in path %s\n", init_path); 680df8bae1dSRodney W. Grimes panic("no init"); 681df8bae1dSRodney W. Grimes } 68237b087a6SPeter Wemm 68337b087a6SPeter Wemm /* 68437b087a6SPeter Wemm * Like kthread_create(), but runs in it's own address space. 68537b087a6SPeter Wemm * We do this early to reserve pid 1. 68637b087a6SPeter Wemm * 68737b087a6SPeter Wemm * Note special case - do not make it runnable yet. Other work 68837b087a6SPeter Wemm * in progress will change this more. 68937b087a6SPeter Wemm */ 69037b087a6SPeter Wemm static void 69137b087a6SPeter Wemm create_init(const void *udata __unused) 69237b087a6SPeter Wemm { 6935a06cb0cSRobert Watson struct ucred *newcred, *oldcred; 69437b087a6SPeter Wemm int error; 69537b087a6SPeter Wemm 696316ec49aSScott Long error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc); 69737b087a6SPeter Wemm if (error) 69837b087a6SPeter Wemm panic("cannot fork init: %d\n", error); 699bafc8f25SRobert Watson KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); 7005a06cb0cSRobert Watson /* divorce init's credentials from the kernel's */ 7015a06cb0cSRobert Watson newcred = crget(); 702f202965eSJohn Baldwin PROC_LOCK(initproc); 703f202965eSJohn Baldwin initproc->p_flag |= P_SYSTEM; 7045a06cb0cSRobert Watson oldcred = initproc->p_ucred; 7055a06cb0cSRobert Watson crcopy(newcred, oldcred); 70640244964SRobert Watson #ifdef MAC 70740244964SRobert Watson mac_create_proc1(newcred); 70840244964SRobert Watson #endif 7093683665bSRobert Watson #ifdef AUDIT 7103683665bSRobert Watson audit_proc_init(initproc); 7113683665bSRobert Watson #endif 7125a06cb0cSRobert Watson initproc->p_ucred = newcred; 713f202965eSJohn Baldwin PROC_UNLOCK(initproc); 7145a06cb0cSRobert Watson crfree(oldcred); 7154d1a4bb7SRobert Watson cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); 7169ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 717f202965eSJohn Baldwin initproc->p_sflag |= PS_INMEM; 7189ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 719079b7badSJulian Elischer cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); 72037b087a6SPeter Wemm } 72137b087a6SPeter Wemm SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) 72237b087a6SPeter Wemm 72337b087a6SPeter Wemm /* 72437b087a6SPeter Wemm * Make it runnable now. 72537b087a6SPeter Wemm */ 72637b087a6SPeter Wemm static void 72737b087a6SPeter Wemm kick_init(const void *udata __unused) 72837b087a6SPeter Wemm { 729079b7badSJulian Elischer struct thread *td; 730f202965eSJohn Baldwin 731079b7badSJulian Elischer td = FIRST_THREAD_IN_PROC(initproc); 7329ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 73371fad9fdSJulian Elischer TD_SET_CAN_RUN(td); 7342630e4c9SJulian Elischer setrunqueue(td, SRQ_BORING); /* XXXKSE */ 7359ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 73637b087a6SPeter Wemm } 73737b087a6SPeter Wemm SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) 738