51#include "opt_init_path.h"
52#include "opt_verbose_sysinit.h"
56#include <sys/boottrace.h>
58#include <sys/cpuset.h>
59#include <sys/dtrace_bsd.h>
61#include <sys/eventhandler.h>
64#include <sys/filedesc.h>
65#include <sys/imgact.h>
67#include <sys/kernel.h>
70#include <sys/loginclass.h>
71#include <sys/malloc.h>
76#include <sys/reboot.h>
77#include <sys/resourcevar.h>
79#include <sys/signalvar.h>
81#include <sys/syscallsubr.h>
82#include <sys/sysctl.h>
83#include <sys/sysent.h>
84#include <sys/sysproto.h>
85#include <sys/unistd.h>
86#include <sys/vmmeter.h>
89#include <machine/cpu.h>
91#include <security/audit/audit.h>
92#include <security/mac/mac_framework.h>
95#include <vm/vm_param.h>
96#include <vm/vm_extern.h>
99#include <sys/copyright.h>
102#include <ddb/db_sym.h>
126 "Boot control flags, passed from loader");
133 "Control the output of verbose kernel messages");
135#ifdef VERBOSE_SYSINIT
143int verbose_sysinit = VERBOSE_SYSINIT;
144TUNABLE_INT(
"debug.verbose_sysinit", &verbose_sysinit);
148FEATURE(invariants,
"Kernel compiled with INVARIANTS, may affect performance");
156SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL);
183 newset =
malloc(
count *
sizeof(*sipp), M_TEMP, M_NOWAIT);
185 panic(
"cannot malloc for sysinit");
193 for (sipp =
set; sipp < set_end; sipp++)
201#if defined (DDB) && defined(VERBOSE_SYSINIT)
211 sym = db_search_symbol(va, strategy, &offset);
214 db_symbol_values(
sym, &
name, NULL);
239#if defined(VERBOSE_SYSINIT)
249 sysinit = SET_BEGIN(sysinit_set);
259 for (xipp = sipp + 1; xipp <
sysinit_end; xipp++) {
260 if ((*sipp)->subsystem < (*xipp)->subsystem ||
261 ((*sipp)->subsystem == (*xipp)->subsystem &&
262 (*sipp)->order <= (*xipp)->order))
270 last = SI_SUB_COPYRIGHT;
271#if defined(VERBOSE_SYSINIT)
274 printf(
"VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n");
283 if ((*sipp)->subsystem == SI_SUB_DUMMY)
286 if ((*sipp)->subsystem == SI_SUB_DONE)
289 if ((*sipp)->subsystem > last)
290 BOOTTRACE_INIT(
"sysinit 0x%7x", (*sipp)->subsystem);
292#if defined(VERBOSE_SYSINIT)
293 if ((*sipp)->subsystem > last && verbose_sysinit != 0) {
295 printf(
"subsystem %x\n", last);
299 const char *func, *
data;
305 if (func != NULL &&
data != NULL)
307 else if (func != NULL)
308 printf(
" %s(%p)... ", func, (*sipp)->udata);
311 printf(
" %p(%p)... ", (*sipp)->func,
317 (*((*sipp)->func))((*sipp)->udata);
319#if defined(VERBOSE_SYSINIT)
325 last = (*sipp)->subsystem;
326 (*sipp)->subsystem = SI_SUB_DONE;
330 if (
sysinit != SET_BEGIN(sysinit_set))
341 BOOTTRACE(
"mi_startup done");
343 mtx_assert(&
Giant, MA_OWNED | MA_NOTRECURSED);
365 len = strlen(version);
366 while (len > 0 && version[len - 1] ==
'\n')
368 printf(
"%.*s %s\n", len, version, machine);
369 printf(
"%s\n", compiler_version);
379static char wit_warn[] =
380 "WARNING: WITNESS option enabled, expect reduced performance.\n";
381SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_FOURTH,
383SYSINIT(witwarn2, SI_SUB_LAST, SI_ORDER_FOURTH,
388static char diag_warn[] =
389 "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n";
390SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_FIFTH,
392SYSINIT(diagwarn2, SI_SUB_LAST, SI_ORDER_FIFTH,
400 panic(
"null_fetch_syscall_args");
407 panic(
"null_set_syscall_retval");
419 .sv_transtrap = NULL,
423 .sv_szsigcode = NULL,
426 .sv_imgact_try = NULL,
428 .sv_minuser = VM_MIN_ADDRESS,
429 .sv_maxuser = VM_MAXUSER_ADDRESS,
430 .sv_usrstack = USRSTACK,
431 .sv_psstrings = PS_STRINGS,
432 .sv_psstringssz =
sizeof(
struct ps_strings),
433 .sv_stackprot = VM_PROT_ALL,
434 .sv_copyout_strings = NULL,
441 .sv_syscallnames = NULL,
442 .sv_schedtail = NULL,
443 .sv_thread_detach = NULL,
446 .sv_regset_begin = NULL,
447 .sv_regset_end = NULL,
462 struct ucred *newcred;
463 struct uidinfo tmpuinfo;
464 struct loginclass tmplc = {
467 vm_paddr_t pageablemem;
477 p->p_magic = P_MAGIC;
478 p->p_osrel = osreldate;
495 LIST_INSERT_HEAD(&
allproc, p, p_list);
496 LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
497 mtx_init(&
pgrp0.pg_mtx,
"process group", NULL, MTX_DEF | MTX_DUPOK);
499 LIST_INSERT_HEAD(PGRPHASH(0), &
pgrp0, pg_hash);
500 LIST_INIT(&
pgrp0.pg_members);
501 LIST_INSERT_HEAD(&
pgrp0.pg_members, p, p_pglist);
504 mtx_init(&
session0.s_mtx,
"session", NULL, MTX_DEF);
505 refcount_init(&
session0.s_count, 1);
509 p->p_flag = P_SYSTEM | P_INMEM | P_KPROC;
511 p->p_state = PRS_NORMAL;
513 STAILQ_INIT(&p->p_ktr);
515 td->td_tid = THREAD0_TID;
517 TD_SET_STATE(td, TDS_RUNNING);
518 td->td_pri_class = PRI_TIMESHARE;
519 td->td_user_pri = PUSER;
520 td->td_base_user_pri = PUSER;
521 td->td_lend_user_pri = PRI_MAX;
522 td->td_priority = PVM;
523 td->td_base_pri = PVM;
524 td->td_oncpu = curcpu;
525 td->td_flags = TDF_INMEM;
526 td->td_pflags = TDP_KTHREAD;
528 td->td_domain.dr_policy = td->td_cpuset->cs_domain;
533 p->p_treeflag |= P_TREE_REAPER;
534 LIST_INIT(&p->p_reaplist);
536 strncpy(p->p_comm,
"kernel", sizeof (p->p_comm));
537 strncpy(td->td_name,
"swapper", sizeof (td->td_name));
539 callout_init_mtx(&p->p_itcallout, &p->p_mtx, 0);
540 callout_init_mtx(&p->p_limco, &p->p_mtx, 0);
542 TAILQ_INIT(&p->p_kqtim_stop);
546 newcred->cr_ngroups = 1;
548 curthread->td_ucred = newcred;
550 newcred->cr_uidinfo = newcred->cr_ruidinfo = &tmpuinfo;
551 newcred->cr_uidinfo =
uifind(0);
552 newcred->cr_ruidinfo =
uifind(0);
553 newcred->cr_loginclass = &tmplc;
556 curthread->td_ucred = NULL;
563 audit_cred_kproc0(newcred);
566 mac_cred_create_swapper(newcred);
575 p->p_pd =
pdinit(NULL,
false);
581 for (i = 0; i < RLIM_NLIMITS; i++)
582 p->p_limit->pl_rlimit[i].rlim_cur =
583 p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY;
584 p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur =
585 p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max =
maxfiles;
586 p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur =
587 p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max =
maxproc;
588 p->p_limit->pl_rlimit[RLIMIT_DATA].rlim_cur =
dfldsiz;
589 p->p_limit->pl_rlimit[RLIMIT_DATA].rlim_max =
maxdsiz;
590 p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur =
dflssiz;
591 p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_max =
maxssiz;
593 pageablemem = ptoa((vm_paddr_t)vm_free_count());
594 p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_cur =
595 p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = pageablemem;
596 p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = pageablemem / 3;
597 p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = pageablemem;
598 p->p_cpulimit = RLIM_INFINITY;
605 racct_create(&p->p_racct);
611 refcount_init(&
vmspace0.vm_refcnt, 1);
612 pmap_pinit0(vmspace_pmap(&
vmspace0));
619 p->p_sysent->sv_minuser, p->p_sysent->sv_maxuser);
625 EVENTHANDLER_DIRECT_INVOKE(process_init, p);
631 EVENTHANDLER_DIRECT_INVOKE(process_ctor, p);
637 (void)
chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0);
639 racct_add_force(p, RACCT_NPROC, 1);
657 FOREACH_PROC_IN_SYSTEM(p) {
659 if (p->p_state == PRS_NEW) {
666 p->p_rux.rux_runtime = 0;
667 p->p_rux.rux_uticks = 0;
668 p->p_rux.rux_sticks = 0;
669 p->p_rux.rux_iticks = 0;
671 FOREACH_THREAD_IN_PROC(p, td) {
678 PCPU_SET(switchticks,
ticks);
696 __XSTRING(INIT_PATH);
698 "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init";
701 "Path used to search the init process");
707#ifndef INIT_SHUTDOWN_TIMEOUT
708#define INIT_SHUTDOWN_TIMEOUT 120
713 "Unused within kernel, but used to control init(8)");
722 struct image_args args;
725 char *free_init_path, *tmp_init_path;
728 struct vmspace *oldvmspace;
743 printf(
"Dual Console: Serial Primary, Video Secondary\n");
745 printf(
"Dual Console: Video Primary, Serial Secondary\n");
752 free_init_path = tmp_init_path = strdup(
init_path, M_TEMP);
754 while ((
path = strsep(&tmp_init_path,
":")) != NULL) {
758 memset(&args, 0,
sizeof(args));
761 panic(
"%s: Can't allocate space for init arguments %d",
766 panic(
"%s: Can't add fname %d", __func__, error);
769 panic(
"%s: Can't add argv[0] %d", __func__, error);
773 panic(
"%s: Can't add argv[0] %d", __func__, error);
782 KASSERT((td->td_pflags & TDP_EXECVMSPC) == 0,
784 oldvmspace = p->p_vmspace;
787 (
"kern_execve returned success, not EJUSTRETURN"));
788 if (error == EJUSTRETURN) {
790 free(free_init_path, M_TEMP);
797 free(free_init_path, M_TEMP);
811 struct ucred *newcred, *oldcred;
815 bzero(&fr,
sizeof(fr));
816 fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
818 error =
fork1(&thread0, &fr);
820 panic(
"cannot fork init: %d\n", error);
821 KASSERT(
initproc->p_pid == 1, (
"create_init: initproc->p_pid != 1"));
826 initproc->p_flag |= P_SYSTEM | P_INMEM;
827 initproc->p_treeflag |= P_TREE_REAPER;
831 mac_cred_create_init(newcred);
834 audit_cred_proc1(newcred);
837 td = FIRST_THREAD_IN_PROC(
initproc);
840 td->td_ucred = td->td_realucred;
844 cpu_fork_kthread_handler(FIRST_THREAD_IN_PROC(
initproc),
857 td = FIRST_THREAD_IN_PROC(
initproc);
869db_show_print_syinit(
struct sysinit *sip,
bool ddb)
871 const char *sname, *funcname;
877 db_printf(__VA_ARGS__); \
882 xprint(
"%s: no sysinit * given\n", __func__);
886 sym = db_search_symbol((vm_offset_t)sip, DB_STGY_ANY, &offset);
887 db_symbol_values(
sym, &sname, NULL);
888 sym = db_search_symbol((vm_offset_t)sip->func, DB_STGY_PROC, &offset);
889 db_symbol_values(
sym, &funcname, NULL);
890 xprint(
"%s(%p)\n", (sname != NULL) ? sname :
"", sip);
891 xprint(
" %#08x %#08x\n", sip->subsystem, sip->order);
892 xprint(
" %p(%s)(%p)\n",
893 sip->func, (funcname != NULL) ? funcname :
"", sip->udata);
897DB_SHOW_COMMAND(
sysinit, db_show_sysinit)
901 db_printf(
"SYSINIT vs Name(Ptr)\n");
902 db_printf(
" Subsystem Order\n");
903 db_printf(
" Function(Name)(Arg)\n");
905 db_show_print_syinit(*sipp,
true);
static int init_shutdown_timeout
static void create_init(const void *udata __unused)
void sysinit_add(struct sysinit **set, struct sysinit **set_end)
static void null_set_fork_retval(struct thread *td __unused)
static char init_path[MAXPATHLEN]
struct sysinit ** sysinit
static int null_fetch_syscall_args(struct thread *td __unused)
static void print_caddr_t(void *data)
static void kick_init(const void *udata __unused)
static void start_init(void *dummy)
static void proc0_post(void *dummy __unused)
struct sysinit ** newsysinit_end
SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "Boot control flags, passed from loader")
static struct session session0
static void print_version(void *data __unused)
struct sysentvec null_sysvec
struct sysinit ** sysinit_end
struct thread0_storage thread0_st __aligned(32)
struct sysinit ** newsysinit
int(* lkpi_alloc_current)(struct thread *, int)
static void null_set_syscall_retval(struct thread *td __unused, int error __unused)
SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
int linux_alloc_current_noop(struct thread *td __unused, int flags __unused)
SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, "Path used to search the init process")
static void proc0_init(void *dummy __unused)
#define INIT_SHUTDOWN_TIMEOUT
SET_DECLARE(sysinit_set, struct sysinit)
TUNABLE_INT("kern.eventtimer.periodic", &want_periodic)
struct cpuset * cpuset_thread0(void)
struct pwddesc * pdinit(struct pwddesc *pdp, bool keeplock)
struct filedesc * fdinit(void)
void kdtrace_proc_ctor(struct proc *p)
FEATURE(kdtrace_hooks, "Kernel DTrace hooks which are required to load DTrace kernel modules")
void kdtrace_thread_ctor(struct thread *td)
char * kern_getenv(const char *name)
int kern_unsetenv(const char *name)
struct knlist * knlist_alloc(struct mtx *lock)
void exec_cleanup(struct thread *td, struct vmspace *oldvmspace)
int kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p, struct vmspace *oldvmspace)
int exec_args_add_arg(struct image_args *args, const char *argp, enum uio_seg segflg)
int exec_args_add_fname(struct image_args *args, const char *fname, enum uio_seg segflg)
int exec_alloc_args(struct image_args *args)
int fork1(struct thread *td, struct fork_req *fr)
struct loginclass * loginclass_find(const char *name)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
struct mtx __exclusive_cache_line Giant
struct pstats * pstats_alloc(void)
struct sx __exclusive_cache_line proctree_lock
struct sx __exclusive_cache_line allproc_lock
struct ucred * crget(void)
void crcopy(struct ucred *dest, struct ucred *src)
struct ucred * crcowget(struct ucred *cr)
void proc_set_cred(struct proc *p, struct ucred *newcred)
void proc_set_cred_init(struct proc *p, struct ucred *newcred)
void crfree(struct ucred *cr)
void crcowfree(struct thread *td)
void rufetch(struct proc *p, struct rusage *ru)
struct plimit * lim_alloc()
struct uidinfo * uifind(uid_t uid)
int chgproccnt(struct uidinfo *uip, int diff, rlim_t max)
void panic(const char *fmt,...)
struct sigacts * sigacts_alloc(void)
void siginit(struct proc *p)
void microuptime(struct timeval *tvp)
void tidhash_add(struct thread *td)
void thread_cow_get_proc(struct thread *newtd, struct proc *p)
static int thread_init(void *mem, int size, int flags)
static int thread_ctor(void *mem, int size, void *arg, int flags)
void callout_init(struct callout *c, int mpsafe)
static const char * symbol_name(elf_file_t ef, Elf_Size r_info)
void sched_add(struct thread *td, int flags)
int printf(const char *fmt,...)