1df8bae1dSRodney W. Grimes /* 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 42c3aac50fSPeter Wemm * $FreeBSD$ 43df8bae1dSRodney W. Grimes */ 44df8bae1dSRodney W. Grimes 4567481196SJohn Birrell #include "opt_init_path.h" 4640244964SRobert Watson #include "opt_mac.h" 474bd49128SPeter Wemm 48df8bae1dSRodney W. Grimes #include <sys/param.h> 499e209b12SAlfred Perlstein #include <sys/kernel.h> 50f36ba452SJake Burkholder #include <sys/exec.h> 51b3c5c18dSBruce Evans #include <sys/file.h> 52df8bae1dSRodney W. Grimes #include <sys/filedesc.h> 530384fff8SJason Evans #include <sys/ktr.h> 541005a129SJohn Baldwin #include <sys/lock.h> 5540244964SRobert Watson #include <sys/mac.h> 56ac0ad63fSBruce Evans #include <sys/mount.h> 5735e0e5b3SJohn Baldwin #include <sys/mutex.h> 588f19eb88SIan Dowse #include <sys/syscallsubr.h> 59946bb7a2SPoul-Henning Kamp #include <sys/sysctl.h> 60df8bae1dSRodney W. Grimes #include <sys/proc.h> 61df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 62df8bae1dSRodney W. Grimes #include <sys/systm.h> 6336240ea5SDoug Rabson #include <sys/signalvar.h> 64df8bae1dSRodney W. Grimes #include <sys/vnode.h> 65f3f0ca60SSøren Schmidt #include <sys/sysent.h> 66df8bae1dSRodney W. Grimes #include <sys/reboot.h> 671005a129SJohn Baldwin #include <sys/sx.h> 68ad7507e2SSteven Wallace #include <sys/sysproto.h> 69efeaf95aSDavid Greenman #include <sys/vmmeter.h> 7074b2192aSJohn Dyson #include <sys/unistd.h> 7194e9d7c1SPeter Wemm #include <sys/malloc.h> 72db901281SPoul-Henning Kamp #include <sys/conf.h> 73df8bae1dSRodney W. Grimes 74df8bae1dSRodney W. Grimes #include <machine/cpu.h> 75df8bae1dSRodney W. Grimes 76df8bae1dSRodney W. Grimes #include <vm/vm.h> 77efeaf95aSDavid Greenman #include <vm/vm_param.h> 78efeaf95aSDavid Greenman #include <vm/pmap.h> 79efeaf95aSDavid Greenman #include <vm/vm_map.h> 80efeaf95aSDavid Greenman #include <sys/user.h> 816faaa756SWolfram Schneider #include <sys/copyright.h> 82df8bae1dSRodney W. Grimes 8337b087a6SPeter Wemm void mi_startup(void); /* Should be elsewhere */ 84df8bae1dSRodney W. Grimes 85df8bae1dSRodney W. Grimes /* Components of the first process -- never freed. */ 86154c04e5SPoul-Henning Kamp static struct session session0; 87154c04e5SPoul-Henning Kamp static struct pgrp pgrp0; 88df8bae1dSRodney W. Grimes struct proc proc0; 89079b7badSJulian Elischer struct thread thread0; 904f0db5e0SJulian Elischer struct kse kse0; 914f0db5e0SJulian Elischer struct ksegrp ksegrp0; 926626c604SJulian Elischer static struct procsig procsig0; 93154c04e5SPoul-Henning Kamp static struct filedesc0 filedesc0; 94154c04e5SPoul-Henning Kamp static struct plimit limit0; 95154c04e5SPoul-Henning Kamp static struct vmspace vmspace0; 962b14f991SJulian Elischer struct proc *initproc; 97df8bae1dSRodney W. Grimes 98dedb7b62SPeter Wemm int cmask = CMASK; 99828c9e13SDavid E. O'Brien extern int fallback_elf_brand; 100df8bae1dSRodney W. Grimes 1012976b7f1SDavid Greenman struct vnode *rootvp; 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 176f41325dbSPeter Wemm if (sysinit == NULL) { 177f41325dbSPeter Wemm sysinit = SET_BEGIN(sysinit_set); 178f41325dbSPeter Wemm sysinit_end = SET_LIMIT(sysinit_set); 179f41325dbSPeter Wemm } 180f41325dbSPeter Wemm 18194e9d7c1SPeter Wemm restart: 1822b14f991SJulian Elischer /* 1832b14f991SJulian Elischer * Perform a bubble sort of the system initialization objects by 1842b14f991SJulian Elischer * their subsystem (primary key) and order (secondary key). 1852b14f991SJulian Elischer */ 186f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 187f41325dbSPeter Wemm for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { 1882b14f991SJulian Elischer if ((*sipp)->subsystem < (*xipp)->subsystem || 1892b14f991SJulian Elischer ((*sipp)->subsystem == (*xipp)->subsystem && 190af4b2d2dSPeter Wemm (*sipp)->order <= (*xipp)->order)) 1912b14f991SJulian Elischer continue; /* skip*/ 1922b14f991SJulian Elischer save = *sipp; 1932b14f991SJulian Elischer *sipp = *xipp; 1942b14f991SJulian Elischer *xipp = save; 1952b14f991SJulian Elischer } 1962b14f991SJulian Elischer } 1972b14f991SJulian Elischer 1982b14f991SJulian Elischer /* 1992b14f991SJulian Elischer * Traverse the (now) ordered list of system initialization tasks. 2002b14f991SJulian Elischer * Perform each task, and continue on to the next task. 2012b14f991SJulian Elischer * 2022b14f991SJulian Elischer * The last item on the list is expected to be the scheduler, 2032b14f991SJulian Elischer * which will not return. 2042b14f991SJulian Elischer */ 205f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 20674b2192aSJohn Dyson 2072b14f991SJulian Elischer if ((*sipp)->subsystem == SI_SUB_DUMMY) 2082b14f991SJulian Elischer continue; /* skip dummy task(s)*/ 2092b14f991SJulian Elischer 21094e9d7c1SPeter Wemm if ((*sipp)->subsystem == SI_SUB_DONE) 21194e9d7c1SPeter Wemm continue; 21294e9d7c1SPeter Wemm 2139c8b8baaSPeter Wemm /* Call function */ 2142b14f991SJulian Elischer (*((*sipp)->func))((*sipp)->udata); 21594e9d7c1SPeter Wemm 21694e9d7c1SPeter Wemm /* Check off the one we're just done */ 21794e9d7c1SPeter Wemm (*sipp)->subsystem = SI_SUB_DONE; 21894e9d7c1SPeter Wemm 21994e9d7c1SPeter Wemm /* Check if we've installed more sysinit items via KLD */ 22094e9d7c1SPeter Wemm if (newsysinit != NULL) { 221f41325dbSPeter Wemm if (sysinit != SET_BEGIN(sysinit_set)) 22294e9d7c1SPeter Wemm free(sysinit, M_TEMP); 22394e9d7c1SPeter Wemm sysinit = newsysinit; 224f41325dbSPeter Wemm sysinit_end = newsysinit_end; 22594e9d7c1SPeter Wemm newsysinit = NULL; 226f41325dbSPeter Wemm newsysinit_end = NULL; 22794e9d7c1SPeter Wemm goto restart; 22894e9d7c1SPeter Wemm } 2292b14f991SJulian Elischer } 2302b14f991SJulian Elischer 231477a642cSPeter Wemm panic("Shouldn't get here!"); 2322b14f991SJulian Elischer /* NOTREACHED*/ 2332b14f991SJulian Elischer } 2342b14f991SJulian Elischer 2352b14f991SJulian Elischer 2362b14f991SJulian Elischer /* 2372b14f991SJulian Elischer *************************************************************************** 2382b14f991SJulian Elischer **** 2392b14f991SJulian Elischer **** The following SYSINIT's belong elsewhere, but have not yet 2402b14f991SJulian Elischer **** been moved. 2412b14f991SJulian Elischer **** 2422b14f991SJulian Elischer *************************************************************************** 2432b14f991SJulian Elischer */ 2449ef6c28aSBruce Evans static void 24537b087a6SPeter Wemm print_caddr_t(void *data __unused) 2469ef6c28aSBruce Evans { 2479ef6c28aSBruce Evans printf("%s", (char *)data); 2489ef6c28aSBruce Evans } 249d841aaa7SBruce Evans SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 2507a08bae6SJohn Baldwin SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version) 2517a08bae6SJohn Baldwin 2527a08bae6SJohn Baldwin static void 2537a08bae6SJohn Baldwin set_boot_verbose(void *data __unused) 2547a08bae6SJohn Baldwin { 2557a08bae6SJohn Baldwin 2567a08bae6SJohn Baldwin if (boothowto & RB_VERBOSE) 2577a08bae6SJohn Baldwin bootverbose++; 2587a08bae6SJohn Baldwin } 2597a08bae6SJohn Baldwin SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL) 2602b14f991SJulian Elischer 261f36ba452SJake Burkholder struct sysentvec null_sysvec = { 262f36ba452SJake Burkholder 0, 263f36ba452SJake Burkholder NULL, 264f36ba452SJake Burkholder 0, 265f36ba452SJake Burkholder 0, 266f36ba452SJake Burkholder NULL, 267f36ba452SJake Burkholder 0, 268f36ba452SJake Burkholder NULL, 269f36ba452SJake Burkholder NULL, 270f36ba452SJake Burkholder NULL, 271f36ba452SJake Burkholder NULL, 272f36ba452SJake Burkholder NULL, 273f36ba452SJake Burkholder NULL, 274f36ba452SJake Burkholder NULL, 275f36ba452SJake Burkholder "null", 276f36ba452SJake Burkholder NULL, 277f36ba452SJake Burkholder NULL, 278f36ba452SJake Burkholder 0, 279f36ba452SJake Burkholder PAGE_SIZE, 280f36ba452SJake Burkholder VM_MIN_ADDRESS, 281f36ba452SJake Burkholder VM_MAXUSER_ADDRESS, 282f36ba452SJake Burkholder USRSTACK, 283f36ba452SJake Burkholder PS_STRINGS, 284f36ba452SJake Burkholder VM_PROT_ALL, 285f36ba452SJake Burkholder NULL, 286f36ba452SJake Burkholder NULL 287f36ba452SJake Burkholder }; 2883ebc1248SPeter Wemm 2892b14f991SJulian Elischer /* 2902b14f991SJulian Elischer *************************************************************************** 2912b14f991SJulian Elischer **** 2922b14f991SJulian Elischer **** The two following SYSINT's are proc0 specific glue code. I am not 2932b14f991SJulian Elischer **** convinced that they can not be safely combined, but their order of 2942b14f991SJulian Elischer **** operation has been maintained as the same as the original init_main.c 2952b14f991SJulian Elischer **** for right now. 2962b14f991SJulian Elischer **** 2972b14f991SJulian Elischer **** These probably belong in init_proc.c or kern_proc.c, since they 2982b14f991SJulian Elischer **** deal with proc0 (the fork template process). 2992b14f991SJulian Elischer **** 3002b14f991SJulian Elischer *************************************************************************** 3012b14f991SJulian Elischer */ 3022b14f991SJulian Elischer /* ARGSUSED*/ 303154c04e5SPoul-Henning Kamp static void 30437b087a6SPeter Wemm proc0_init(void *dummy __unused) 3052b14f991SJulian Elischer { 306df8bae1dSRodney W. Grimes register struct proc *p; 307df8bae1dSRodney W. Grimes register struct filedesc0 *fdp; 30892579404SAlexander Langer register unsigned i; 309b40ce416SJulian Elischer struct thread *td; 310079b7badSJulian Elischer struct ksegrp *kg; 311079b7badSJulian Elischer struct kse *ke; 312df8bae1dSRodney W. Grimes 3130cddd8f0SMatthew Dillon GIANT_REQUIRED; 314df8bae1dSRodney W. Grimes p = &proc0; 315079b7badSJulian Elischer td = &thread0; 3164f0db5e0SJulian Elischer ke = &kse0; 3174f0db5e0SJulian Elischer kg = &ksegrp0; 318df8bae1dSRodney W. Grimes 319df8bae1dSRodney W. Grimes /* 3200384fff8SJason Evans * Initialize magic number. 3210384fff8SJason Evans */ 3220384fff8SJason Evans p->p_magic = P_MAGIC; 3230384fff8SJason Evans 3240384fff8SJason Evans /* 325079b7badSJulian Elischer * Initialize thread, process and pgrp structures. 326a3bfb996SJeffrey Hsu */ 327a3bfb996SJeffrey Hsu procinit(); 328e602ba25SJulian Elischer threadinit(); 329a3bfb996SJeffrey Hsu 330a3bfb996SJeffrey Hsu /* 331b1508c72SDavid Greenman * Initialize sleep queue hash table 332b1508c72SDavid Greenman */ 333b1508c72SDavid Greenman sleepinit(); 334b1508c72SDavid Greenman 335b1508c72SDavid Greenman /* 3363075778bSJohn Dyson * additional VM structures 3373075778bSJohn Dyson */ 3383075778bSJohn Dyson vm_init2(); 3393075778bSJohn Dyson 3403075778bSJohn Dyson /* 341df8bae1dSRodney W. Grimes * Create process 0 (the swapper). 342df8bae1dSRodney W. Grimes */ 343a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&allproc, p, p_list); 3447b531e60SJohn Baldwin LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); 3456008862bSJohn Baldwin mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); 346df8bae1dSRodney W. Grimes p->p_pgrp = &pgrp0; 347a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 348a3bfb996SJeffrey Hsu LIST_INIT(&pgrp0.pg_members); 349a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 350a3bfb996SJeffrey Hsu 351df8bae1dSRodney W. Grimes pgrp0.pg_session = &session0; 3526008862bSJohn Baldwin mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); 353df8bae1dSRodney W. Grimes session0.s_count = 1; 354df8bae1dSRodney W. Grimes session0.s_leader = p; 355df8bae1dSRodney W. Grimes 3563ebc1248SPeter Wemm p->p_sysent = &null_sysvec; 357f3f0ca60SSøren Schmidt 358e602ba25SJulian Elischer /* 359e602ba25SJulian Elischer * proc_linkup was already done in init_i386() or alphainit() etc. 360e602ba25SJulian Elischer * because the earlier code needed to follow td->td_proc. Otherwise 361e602ba25SJulian Elischer * I would have done it here.. maybe this means this should be 362e602ba25SJulian Elischer * done earlier too. 363e602ba25SJulian Elischer */ 364f202965eSJohn Baldwin p->p_flag = P_SYSTEM; 365f202965eSJohn Baldwin p->p_sflag = PS_INMEM; 366e602ba25SJulian Elischer p->p_state = PRS_NORMAL; 367e602ba25SJulian Elischer td->td_state = TDS_RUNNING; 368e602ba25SJulian Elischer kg->kg_nice = NZERO; 3692c100766SJulian Elischer kg->kg_pri_class = PRI_TIMESHARE; 3702c100766SJulian Elischer kg->kg_user_pri = PUSER; 3712c100766SJulian Elischer td->td_priority = PVM; 3722c100766SJulian Elischer td->td_base_pri = PUSER; 373e602ba25SJulian Elischer td->td_kse = ke; /* XXXKSE */ 374e602ba25SJulian Elischer ke->ke_oncpu = 0; 375c3b98db0SJulian Elischer ke->ke_state = KES_THREAD; 376e602ba25SJulian Elischer ke->ke_thread = td; 3772c1011f7SJohn Dyson p->p_peers = 0; 3782c1011f7SJohn Dyson p->p_leader = p; 379e602ba25SJulian Elischer 3802c1011f7SJohn Dyson 381df8bae1dSRodney W. Grimes bcopy("swapper", p->p_comm, sizeof ("swapper")); 382df8bae1dSRodney W. Grimes 3834f559836SJake Burkholder callout_init(&p->p_itcallout, 0); 384b40ce416SJulian Elischer callout_init(&td->td_slpcallout, 1); 3854f559836SJake Burkholder 386df8bae1dSRodney W. Grimes /* Create credentials. */ 387df8bae1dSRodney W. Grimes p->p_ucred = crget(); 388df8bae1dSRodney W. Grimes p->p_ucred->cr_ngroups = 1; /* group 0 */ 389f535380cSDon Lewis p->p_ucred->cr_uidinfo = uifind(0); 390b1fc0ec1SRobert Watson p->p_ucred->cr_ruidinfo = uifind(0); 39191421ba2SRobert Watson p->p_ucred->cr_prison = NULL; /* Don't jail it. */ 39240244964SRobert Watson #ifdef MAC 39340244964SRobert Watson mac_create_proc0(p->p_ucred); 39440244964SRobert Watson #endif 3958e2e767bSJohn Baldwin td->td_ucred = crhold(p->p_ucred); 39675c13541SPoul-Henning Kamp 3976626c604SJulian Elischer /* Create procsig. */ 3986626c604SJulian Elischer p->p_procsig = &procsig0; 39975ffaf59SLuoqi Chen p->p_procsig->ps_refcnt = 1; 4006626c604SJulian Elischer 40137b087a6SPeter Wemm /* Initialize signal state for process 0. */ 40237b087a6SPeter Wemm siginit(&proc0); 40337b087a6SPeter Wemm 404df8bae1dSRodney W. Grimes /* Create the file descriptor table. */ 405df8bae1dSRodney W. Grimes fdp = &filedesc0; 406df8bae1dSRodney W. Grimes p->p_fd = &fdp->fd_fd; 4076008862bSJohn Baldwin mtx_init(&fdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_DEF); 408df8bae1dSRodney W. Grimes fdp->fd_fd.fd_refcnt = 1; 409df8bae1dSRodney W. Grimes fdp->fd_fd.fd_cmask = cmask; 410df8bae1dSRodney W. Grimes fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 411df8bae1dSRodney W. Grimes fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 412df8bae1dSRodney W. Grimes fdp->fd_fd.fd_nfiles = NDFILE; 413df8bae1dSRodney W. Grimes 414df8bae1dSRodney W. Grimes /* Create the limits structures. */ 415df8bae1dSRodney W. Grimes p->p_limit = &limit0; 416df8bae1dSRodney W. Grimes for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 417df8bae1dSRodney W. Grimes limit0.pl_rlimit[i].rlim_cur = 418df8bae1dSRodney W. Grimes limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 419b3c5c18dSBruce Evans limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = 420b3c5c18dSBruce Evans limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; 421b3c5c18dSBruce Evans limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = 422b3c5c18dSBruce Evans limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 423df8bae1dSRodney W. Grimes i = ptoa(cnt.v_free_count); 424df8bae1dSRodney W. Grimes limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 425df8bae1dSRodney W. Grimes limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 426df8bae1dSRodney W. Grimes limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 427df8bae1dSRodney W. Grimes limit0.p_refcnt = 1; 4285715307fSJohn Baldwin p->p_cpulimit = RLIM_INFINITY; 429df8bae1dSRodney W. Grimes 430df8bae1dSRodney W. Grimes /* Allocate a prototype map so we have something to fork. */ 431b1028ad1SLuoqi Chen pmap_pinit0(vmspace_pmap(&vmspace0)); 432df8bae1dSRodney W. Grimes p->p_vmspace = &vmspace0; 433df8bae1dSRodney W. Grimes vmspace0.vm_refcnt = 1; 43405ba50f5SJake Burkholder vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser, 43505ba50f5SJake Burkholder p->p_sysent->sv_maxuser); 436b1028ad1SLuoqi Chen vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 437df8bae1dSRodney W. Grimes 43839fb8e6bSJulian Elischer /* 439df8bae1dSRodney W. Grimes * We continue to place resource usage info and signal 440df8bae1dSRodney W. Grimes * actions in the user struct so they're pageable. 441df8bae1dSRodney W. Grimes */ 442b40ce416SJulian Elischer p->p_stats = &p->p_uarea->u_stats; 443b40ce416SJulian Elischer p->p_sigacts = &p->p_uarea->u_sigacts; 444df8bae1dSRodney W. Grimes 445df8bae1dSRodney W. Grimes /* 446a3bfb996SJeffrey Hsu * Charge root for one process. 447df8bae1dSRodney W. Grimes */ 448b1fc0ec1SRobert Watson (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); 44926f9a767SRodney W. Grimes } 4502b14f991SJulian Elischer SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 4512b14f991SJulian Elischer 4522b14f991SJulian Elischer /* ARGSUSED*/ 453154c04e5SPoul-Henning Kamp static void 45437b087a6SPeter Wemm proc0_post(void *dummy __unused) 4552b14f991SJulian Elischer { 45600af9731SPoul-Henning Kamp struct timespec ts; 45737b087a6SPeter Wemm struct proc *p; 458a6fc8288SPeter Wemm 4592b14f991SJulian Elischer /* 4601b0b259eSBruce Evans * Now we can look at the time, having had a chance to verify the 4611b0b259eSBruce Evans * time from the filesystem. Pretend that proc0 started now. 4622b14f991SJulian Elischer */ 4631005a129SJohn Baldwin sx_slock(&allproc_lock); 46437b087a6SPeter Wemm LIST_FOREACH(p, &allproc, p_list) { 46537b087a6SPeter Wemm microtime(&p->p_stats->p_start); 4661cbb9c3bSPoul-Henning Kamp p->p_runtime.sec = 0; 4671cbb9c3bSPoul-Henning Kamp p->p_runtime.frac = 0; 46837b087a6SPeter Wemm } 4691005a129SJohn Baldwin sx_sunlock(&allproc_lock); 470e2256f43SPeter Wemm binuptime(PCPU_PTR(switchtime)); 4710384fff8SJason Evans PCPU_SET(switchticks, ticks); 4722b14f991SJulian Elischer 473a6fc8288SPeter Wemm /* 474a6fc8288SPeter Wemm * Give the ``random'' number generator a thump. 475a6fc8288SPeter Wemm */ 47600af9731SPoul-Henning Kamp nanotime(&ts); 47700af9731SPoul-Henning Kamp srandom(ts.tv_sec ^ ts.tv_nsec); 4782b14f991SJulian Elischer } 4792b14f991SJulian Elischer SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 4802b14f991SJulian Elischer 481df8bae1dSRodney W. Grimes /* 4822b14f991SJulian Elischer *************************************************************************** 4832b14f991SJulian Elischer **** 4842b14f991SJulian Elischer **** The following SYSINIT's and glue code should be moved to the 4852b14f991SJulian Elischer **** respective files on a per subsystem basis. 4862b14f991SJulian Elischer **** 4872b14f991SJulian Elischer *************************************************************************** 488df8bae1dSRodney W. Grimes */ 489df8bae1dSRodney W. Grimes 490df8bae1dSRodney W. Grimes 491df8bae1dSRodney W. Grimes /* 4922b14f991SJulian Elischer *************************************************************************** 4932b14f991SJulian Elischer **** 4942b14f991SJulian Elischer **** The following code probably belongs in another file, like 49537b087a6SPeter Wemm **** kern/init_init.c. 4962b14f991SJulian Elischer **** 4972b14f991SJulian Elischer *************************************************************************** 498df8bae1dSRodney W. Grimes */ 499df8bae1dSRodney W. Grimes 500df8bae1dSRodney W. Grimes /* 501df8bae1dSRodney W. Grimes * List of paths to try when searching for "init". 502df8bae1dSRodney W. Grimes */ 5035f967b24SDag-Erling Smørgrav static char init_path[MAXPATHLEN] = 50467481196SJohn Birrell #ifdef INIT_PATH 50567481196SJohn Birrell __XSTRING(INIT_PATH); 50667481196SJohn Birrell #else 507e4082284SJohn Birrell "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; 50867481196SJohn Birrell #endif 509af1408e3SLuigi Rizzo SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, 510af1408e3SLuigi Rizzo "Path used to search the init process"); 511df8bae1dSRodney W. Grimes 512df8bae1dSRodney W. Grimes /* 5135f967b24SDag-Erling Smørgrav * Start the initial user process; try exec'ing each pathname in init_path. 514df8bae1dSRodney W. Grimes * The program is invoked with one argument containing the boot flags. 515df8bae1dSRodney W. Grimes */ 516df8bae1dSRodney W. Grimes static void 51737b087a6SPeter Wemm start_init(void *dummy) 518df8bae1dSRodney W. Grimes { 519df8bae1dSRodney W. Grimes vm_offset_t addr; 520df8bae1dSRodney W. Grimes struct execve_args args; 5215f967b24SDag-Erling Smørgrav int options, error; 5225f967b24SDag-Erling Smørgrav char *var, *path, *next, *s; 5235f967b24SDag-Erling Smørgrav char *ucp, **uap, *arg0, *arg1; 524b40ce416SJulian Elischer struct thread *td; 5259c8b8baaSPeter Wemm struct proc *p; 526b7116168SPeter Wemm int init_does_devfs = 0; 527df8bae1dSRodney W. Grimes 5289ed346baSBosko Milekic mtx_lock(&Giant); 5290384fff8SJason Evans 5300cddd8f0SMatthew Dillon GIANT_REQUIRED; 5310cddd8f0SMatthew Dillon 532b40ce416SJulian Elischer td = curthread; 533b40ce416SJulian Elischer p = td->td_proc; 534df8bae1dSRodney W. Grimes 535563af2ecSMaxime Henrion vfs_mountroot(); 536fb92273bSPoul-Henning Kamp 53737b087a6SPeter Wemm /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */ 53837b087a6SPeter Wemm if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode)) 53937b087a6SPeter Wemm panic("cannot find root vnode"); 540426da3bcSAlfred Perlstein FILEDESC_LOCK(p->p_fd); 54137b087a6SPeter Wemm p->p_fd->fd_cdir = rootvnode; 54237b087a6SPeter Wemm VREF(p->p_fd->fd_cdir); 54337b087a6SPeter Wemm p->p_fd->fd_rdir = rootvnode; 544a90ef2aeSIan Dowse VREF(p->p_fd->fd_rdir); 545426da3bcSAlfred Perlstein FILEDESC_UNLOCK(p->p_fd); 546b40ce416SJulian Elischer VOP_UNLOCK(rootvnode, 0, td); 547a87cdf83SRobert Watson #ifdef MAC 548a87cdf83SRobert Watson mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist)); 549a87cdf83SRobert Watson #endif 55037b087a6SPeter Wemm 551b7116168SPeter Wemm if (devfs_present) { 552b7116168SPeter Wemm /* 553b7116168SPeter Wemm * For disk based systems, we probably cannot do this yet 554b7116168SPeter Wemm * since the fs will be read-only. But a NFS root 555b7116168SPeter Wemm * might be ok. It is worth a shot. 556b7116168SPeter Wemm */ 5578f19eb88SIan Dowse error = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700); 558b7116168SPeter Wemm if (error == EEXIST) 559b7116168SPeter Wemm error = 0; 560b7116168SPeter Wemm if (error == 0) 5616dbde1feSMaxime Henrion error = kernel_vmount(0, "fstype", "devfs", 5626dbde1feSMaxime Henrion "fspath", "/dev", NULL); 563b7116168SPeter Wemm if (error != 0) 564b7116168SPeter Wemm init_does_devfs = 1; 565b7116168SPeter Wemm } 566b7116168SPeter Wemm 567df8bae1dSRodney W. Grimes /* 568df8bae1dSRodney W. Grimes * Need just enough stack to hold the faked-up "execve()" arguments. 569df8bae1dSRodney W. Grimes */ 57005ba50f5SJake Burkholder addr = p->p_sysent->sv_usrstack - PAGE_SIZE; 5715f967b24SDag-Erling Smørgrav if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 5725f967b24SDag-Erling Smørgrav FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 573df8bae1dSRodney W. Grimes panic("init: couldn't allocate argument space"); 574df8bae1dSRodney W. Grimes p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 57526f9a767SRodney W. Grimes p->p_vmspace->vm_ssize = 1; 576df8bae1dSRodney W. Grimes 5775f967b24SDag-Erling Smørgrav if ((var = getenv("init_path")) != NULL) { 578b83308b0SDag-Erling Smørgrav strncpy(init_path, var, sizeof init_path); 5795f967b24SDag-Erling Smørgrav init_path[sizeof init_path - 1] = 0; 580d786139cSMaxime Henrion freeenv(var); 5815f967b24SDag-Erling Smørgrav } 582d786139cSMaxime Henrion if ((var = getenv("kern.fallback_elf_brand")) != NULL) { 583828c9e13SDavid E. O'Brien fallback_elf_brand = strtol(var, NULL, 0); 584d786139cSMaxime Henrion freeenv(var); 585d786139cSMaxime Henrion } 5865f967b24SDag-Erling Smørgrav 58767481196SJohn Birrell for (path = init_path; *path != '\0'; path = next) { 588e4082284SJohn Birrell while (*path == ':') 5895f967b24SDag-Erling Smørgrav path++; 59067481196SJohn Birrell if (*path == '\0') 5915f967b24SDag-Erling Smørgrav break; 592e4082284SJohn Birrell for (next = path; *next != '\0' && *next != ':'; next++) 5935f967b24SDag-Erling Smørgrav /* nothing */ ; 5945f967b24SDag-Erling Smørgrav if (bootverbose) 595ba41a07dSDmitrij Tejblum printf("start_init: trying %.*s\n", (int)(next - path), 596ba41a07dSDmitrij Tejblum path); 5975f967b24SDag-Erling Smørgrav 598df8bae1dSRodney W. Grimes /* 599df8bae1dSRodney W. Grimes * Move out the boot flag argument. 600df8bae1dSRodney W. Grimes */ 601df8bae1dSRodney W. Grimes options = 0; 60205ba50f5SJake Burkholder ucp = (char *)p->p_sysent->sv_usrstack; 603df8bae1dSRodney W. Grimes (void)subyte(--ucp, 0); /* trailing zero */ 604df8bae1dSRodney W. Grimes if (boothowto & RB_SINGLE) { 605df8bae1dSRodney W. Grimes (void)subyte(--ucp, 's'); 606df8bae1dSRodney W. Grimes options = 1; 607df8bae1dSRodney W. Grimes } 608df8bae1dSRodney W. Grimes #ifdef notyet 609df8bae1dSRodney W. Grimes if (boothowto & RB_FASTBOOT) { 610df8bae1dSRodney W. Grimes (void)subyte(--ucp, 'f'); 611df8bae1dSRodney W. Grimes options = 1; 612df8bae1dSRodney W. Grimes } 613df8bae1dSRodney W. Grimes #endif 61417755ac8SPoul-Henning Kamp 61517755ac8SPoul-Henning Kamp #ifdef BOOTCDROM 61617755ac8SPoul-Henning Kamp (void)subyte(--ucp, 'C'); 61717755ac8SPoul-Henning Kamp options = 1; 61817755ac8SPoul-Henning Kamp #endif 619b7116168SPeter Wemm if (init_does_devfs) { 6203f54a085SPoul-Henning Kamp (void)subyte(--ucp, 'd'); 6213f54a085SPoul-Henning Kamp options = 1; 622db901281SPoul-Henning Kamp } 623db901281SPoul-Henning Kamp 624df8bae1dSRodney W. Grimes if (options == 0) 625df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); 626df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); /* leading hyphen */ 627df8bae1dSRodney W. Grimes arg1 = ucp; 628df8bae1dSRodney W. Grimes 629df8bae1dSRodney W. Grimes /* 630df8bae1dSRodney W. Grimes * Move out the file name (also arg 0). 631df8bae1dSRodney W. Grimes */ 6325f967b24SDag-Erling Smørgrav (void)subyte(--ucp, 0); 6335f967b24SDag-Erling Smørgrav for (s = next - 1; s >= path; s--) 6345f967b24SDag-Erling Smørgrav (void)subyte(--ucp, *s); 635df8bae1dSRodney W. Grimes arg0 = ucp; 636df8bae1dSRodney W. Grimes 637df8bae1dSRodney W. Grimes /* 638df8bae1dSRodney W. Grimes * Move out the arg pointers. 639df8bae1dSRodney W. Grimes */ 640a20d7755SDoug Rabson uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); 641c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)0); /* terminator */ 642c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); 643c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); 644df8bae1dSRodney W. Grimes 645df8bae1dSRodney W. Grimes /* 646df8bae1dSRodney W. Grimes * Point at the arguments. 647df8bae1dSRodney W. Grimes */ 648df8bae1dSRodney W. Grimes args.fname = arg0; 64926f9a767SRodney W. Grimes args.argv = uap; 65026f9a767SRodney W. Grimes args.envv = NULL; 651df8bae1dSRodney W. Grimes 652df8bae1dSRodney W. Grimes /* 653df8bae1dSRodney W. Grimes * Now try to exec the program. If can't for any reason 654df8bae1dSRodney W. Grimes * other than it doesn't exist, complain. 6552b14f991SJulian Elischer * 65637b087a6SPeter Wemm * Otherwise, return via fork_trampoline() all the way 6579c8b8baaSPeter Wemm * to user mode as init! 658df8bae1dSRodney W. Grimes */ 659b40ce416SJulian Elischer if ((error = execve(td, &args)) == 0) { 6609ed346baSBosko Milekic mtx_unlock(&Giant); 661df8bae1dSRodney W. Grimes return; 662db72809dSJohn Baldwin } 663df8bae1dSRodney W. Grimes if (error != ENOENT) 664ba41a07dSDmitrij Tejblum printf("exec %.*s: error %d\n", (int)(next - path), 665ba41a07dSDmitrij Tejblum path, error); 666df8bae1dSRodney W. Grimes } 667580e7e5aSGreg Lehey printf("init: not found in path %s\n", init_path); 668df8bae1dSRodney W. Grimes panic("no init"); 669df8bae1dSRodney W. Grimes } 67037b087a6SPeter Wemm 67137b087a6SPeter Wemm /* 67237b087a6SPeter Wemm * Like kthread_create(), but runs in it's own address space. 67337b087a6SPeter Wemm * We do this early to reserve pid 1. 67437b087a6SPeter Wemm * 67537b087a6SPeter Wemm * Note special case - do not make it runnable yet. Other work 67637b087a6SPeter Wemm * in progress will change this more. 67737b087a6SPeter Wemm */ 67837b087a6SPeter Wemm static void 67937b087a6SPeter Wemm create_init(const void *udata __unused) 68037b087a6SPeter Wemm { 6815a06cb0cSRobert Watson struct ucred *newcred, *oldcred; 68237b087a6SPeter Wemm int error; 68337b087a6SPeter Wemm 684316ec49aSScott Long error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc); 68537b087a6SPeter Wemm if (error) 68637b087a6SPeter Wemm panic("cannot fork init: %d\n", error); 6875a06cb0cSRobert Watson /* divorce init's credentials from the kernel's */ 6885a06cb0cSRobert Watson newcred = crget(); 689f202965eSJohn Baldwin PROC_LOCK(initproc); 690f202965eSJohn Baldwin initproc->p_flag |= P_SYSTEM; 6915a06cb0cSRobert Watson oldcred = initproc->p_ucred; 6925a06cb0cSRobert Watson crcopy(newcred, oldcred); 69340244964SRobert Watson #ifdef MAC 69440244964SRobert Watson mac_create_proc1(newcred); 69540244964SRobert Watson #endif 6965a06cb0cSRobert Watson initproc->p_ucred = newcred; 697f202965eSJohn Baldwin PROC_UNLOCK(initproc); 6985a06cb0cSRobert Watson crfree(oldcred); 6994d1a4bb7SRobert Watson cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); 7009ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 701f202965eSJohn Baldwin initproc->p_sflag |= PS_INMEM; 7029ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 703079b7badSJulian Elischer cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); 70437b087a6SPeter Wemm } 70537b087a6SPeter Wemm SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) 70637b087a6SPeter Wemm 70737b087a6SPeter Wemm /* 70837b087a6SPeter Wemm * Make it runnable now. 70937b087a6SPeter Wemm */ 71037b087a6SPeter Wemm static void 71137b087a6SPeter Wemm kick_init(const void *udata __unused) 71237b087a6SPeter Wemm { 713079b7badSJulian Elischer struct thread *td; 714f202965eSJohn Baldwin 715079b7badSJulian Elischer td = FIRST_THREAD_IN_PROC(initproc); 7169ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 71771fad9fdSJulian Elischer TD_SET_CAN_RUN(td); 718e602ba25SJulian Elischer setrunqueue(td); /* XXXKSE */ 7199ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 72037b087a6SPeter Wemm } 72137b087a6SPeter Wemm SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) 722