#include <sys/param.h>
#include <sys/filedesc.h>
#include <sys/errno.h>
#include <sys/kthread.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/clockintr.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/tty.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/socketvar.h>
#include <sys/lockf.h>
#include <sys/reboot.h>
#ifdef SYSVSHM
#include <sys/shm.h>
#endif
#ifdef SYSVSEM
#include <sys/sem.h>
#endif
#ifdef SYSVMSG
#include <sys/msg.h>
#endif
#include <sys/domain.h>
#include <sys/event.h>
#include <sys/msgbuf.h>
#include <sys/mbuf.h>
#include <sys/pipe.h>
#include <sys/witness.h>
#include <sys/smr.h>
#include <sys/evcount.h>
#include <sys/syscallargs.h>
#include <uvm/uvm_extern.h>
#include <net/if.h>
#include <net/rtable.h>
#if defined(CRYPTO)
#include <crypto/cryptodev.h>
#include <crypto/cryptosoft.h>
#endif
#if defined(KUBSAN)
extern void kubsan_init(void);
#endif
#if defined(NFSSERVER) || defined(NFSCLIENT)
extern void nfs_init(void);
#endif
#include "stoeplitz.h"
#if NSTOEPLITZ > 0
extern void stoeplitz_init(void);
#endif
#include "mpath.h"
#include "vscsi.h"
#include "softraid.h"
const char copyright[] =
"Copyright (c) 1982, 1986, 1989, 1991, 1993\n"
"\tThe Regents of the University of California. All rights reserved.\n"
"Copyright (c) 1995-2026 OpenBSD. All rights reserved. https://www.OpenBSD.org\n";
struct session session0;
struct pgrp pgrp0;
struct proc proc0;
struct process process0;
struct plimit limit0;
struct vmspace vmspace0;
struct sigacts sigacts0;
struct process *initprocess;
struct proc *reaperproc;
extern struct user *proc0paddr;
struct vnode *rootvp, *swapdev_vp;
int boothowto;
int db_active = 0;
int ncpus = 1;
int ncpusfound = 1;
volatile int start_init_exec;
#if !defined(NO_PROPOLICE)
long __guard_local __attribute__((section(".openbsd.randomdata")));
#endif
int main(void *);
void check_console(struct proc *);
void start_init(void *);
void db_ctf_init(void);
void prof_init(void);
void init_exec(void);
void futex_init(void);
void tslp_init(void);
void taskq_init(void);
void timeout_proc_init(void);
void pool_gc_pages(void *);
void percpu_init(void);
#ifdef DIAGNOSTIC
int pdevinit_done = 0;
#endif
int
main(void *framep)
{
struct proc *p;
struct process *pr;
struct pdevinit *pdev;
extern struct pdevinit pdevinit[];
extern void disk_init(void);
curproc = p = &proc0;
p->p_cpu = curcpu();
timeout_startup();
config_init();
consinit();
printf("%s\n", copyright);
#ifdef KUBSAN
kubsan_init();
#endif
WITNESS_INITIALIZE();
KERNEL_LOCK_INIT();
SCHED_LOCK_INIT();
rw_obj_init();
uvm_init();
disk_init();
tty_init();
cpu_startup();
random_start(boothowto & RB_GOODRANDOM);
mbinit();
#if NSTOEPLITZ > 0
stoeplitz_init();
#endif
soinit();
srp_startup();
smr_startup();
procinit();
lf_init();
filedesc_init();
pipe_init();
kqueue_init();
futex_init();
tslp_init();
p->p_ucred = crget();
p->p_ucred->cr_ngroups = 1;
pr = &process0;
process_initialize(pr, p);
LIST_INSERT_HEAD(&allprocess, pr, ps_list);
LIST_INSERT_HEAD(PIDHASH(0), pr, ps_hash);
atomic_setbits_int(&pr->ps_flags, PS_SYSTEM);
process0.ps_rtableid = 0;
LIST_INSERT_HEAD(&allproc, p, p_list);
pr->ps_pgrp = &pgrp0;
LIST_INSERT_HEAD(TIDHASH(0), p, p_hash);
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
LIST_INIT(&pgrp0.pg_members);
LIST_INSERT_HEAD(&pgrp0.pg_members, pr, ps_pglist);
pgrp0.pg_session = &session0;
session0.s_count = 1;
session0.s_leader = pr;
atomic_setbits_int(&p->p_flag, P_SYSTEM);
p->p_stat = SONPROC;
pr->ps_nice = NZERO;
strlcpy(pr->ps_comm, "swapper", sizeof(pr->ps_comm));
timeout_set(&p->p_sleep_to, endtsleep, p);
signal_init();
siginit(&sigacts0);
pr->ps_sigacts = &sigacts0;
p->p_fd = pr->ps_fd = fdinit();
lim_startup(&limit0);
pr->ps_limit = &limit0;
uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
trunc_page(VM_MAX_ADDRESS), TRUE, TRUE);
p->p_vmspace = pr->ps_vmspace = &vmspace0;
p->p_addr = proc0paddr;
(void)chgproccnt(0, 1);
sched_init();
sleep_queue_init();
clockqueue_init(&curcpu()->ci_queue);
sched_init_cpu(curcpu());
p->p_cpu->ci_randseed = (arc4random() & 0x7fffffff) + 1;
timeout_proc_init();
taskq_init();
ifinit();
softnet_init();
KERNEL_LOCK();
#if NMPATH > 0
config_rootfound("mpath", NULL);
#endif
cpu_configure();
uvm_init_limits(&limit0);
percpu_init();
softnet_percpu();
#if defined(NFSSERVER) || defined(NFSCLIENT)
nfs_init();
#endif
vfsinit();
initclocks();
#ifdef SYSVSHM
shminit();
#endif
#ifdef SYSVSEM
seminit();
#endif
#ifdef SYSVMSG
msginit();
#endif
rtable_init();
for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
if (pdev->pdev_count > 0)
(*pdev->pdev_attach)(pdev->pdev_count);
#ifdef DIAGNOSTIC
pdevinit_done = 1;
#endif
#ifdef CRYPTO
crypto_init();
swcr_init();
#endif
domaininit();
initconsbuf();
#if defined(GPROF) || defined(DDBPROF)
prof_init();
#endif
mbcpuinit();
kqueue_init_percpu();
pmap_init_percpu();
uvm_init_percpu();
evcount_init_percpu();
init_exec();
scheduler_start();
{
struct proc *initproc;
if (fork1(p, FORK_FORK, start_init, NULL, NULL, &initproc))
panic("fork init");
initprocess = initproc->p_p;
}
kthread_run_deferred_queue();
while (config_pending)
tsleep_nsec(&config_pending, PWAIT, "cfpend", INFSLP);
dostartuphooks();
#if NVSCSI > 0
config_rootfound("vscsi", NULL);
#endif
#if NSOFTRAID > 0
config_rootfound("softraid", NULL);
#endif
diskconf();
#ifdef DDB
db_ctf_init();
#endif
if (mountroot == NULL || ((*mountroot)() != 0))
panic("cannot mount root");
TAILQ_FIRST(&mountlist)->mnt_flag |= MNT_ROOTFS;
if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
panic("cannot find root vnode");
p->p_fd->fd_cdir = rootvnode;
vref(p->p_fd->fd_cdir);
VOP_UNLOCK(rootvnode);
p->p_fd->fd_rdir = NULL;
initprocess->ps_fd->fd_cdir = rootvnode;
vref(initprocess->ps_fd->fd_cdir);
initprocess->ps_fd->fd_rdir = NULL;
LIST_FOREACH(pr, &allprocess, ps_list) {
nanouptime(&pr->ps_start);
}
nanouptime(&curcpu()->ci_schedstate.spc_runtime);
uvm_swap_init();
if (kthread_create(uvm_pageout, NULL, NULL, "pagedaemon"))
panic("fork pagedaemon");
if (kthread_create(reaper, NULL, &reaperproc, "reaper"))
panic("fork reaper");
if (kthread_create(buf_daemon, NULL, &cleanerproc, "cleaner"))
panic("fork cleaner");
if (kthread_create(syncer_thread, NULL, &syncerproc, "update"))
panic("fork update");
if (kthread_create(uvm_aiodone_daemon, NULL, NULL, "aiodoned"))
panic("fork aiodoned");
#if !defined(__hppa__)
if (kthread_create(uvm_pagezero_thread, NULL, NULL, "zerothread"))
panic("fork zerothread");
#endif
#if defined(MULTIPROCESSOR)
cpu_boot_secondary_processors();
#endif
smr_startup_thread();
config_process_deferred_mountroot();
start_init_exec = 1;
wakeup((void *)&start_init_exec);
#if defined(MULTIPROCESSOR)
pool_gc_pages(NULL);
#endif
start_periodic_resettodr();
while (1)
tsleep_nsec(&proc0, PVM, "scheduler", INFSLP);
}
static char *initpaths[] = {
"/sbin/init",
"/sbin/oinit",
"/sbin/init.bak",
NULL,
};
void
check_console(struct proc *p)
{
struct nameidata nd;
int error;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
error = namei(&nd);
if (error) {
if (error == ENOENT)
printf("warning: /dev/console does not exist\n");
else
printf("warning: /dev/console error %d\n", error);
} else
vrele(nd.ni_vp);
}
void
start_init(void *arg)
{
struct proc *p = arg;
vaddr_t addr;
struct sys_execve_args
args;
int options, error;
long i;
register_t retval[2];
char flags[4], *flagsp;
char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
while (start_init_exec == 0)
tsleep_nsec(&start_init_exec, PWAIT, "initexec", INFSLP);
check_console(p);
p->p_p->ps_sigacts->ps_sigflags = 0;
#ifdef MACHINE_STACK_GROWS_UP
addr = USRSTACK;
#else
addr = USRSTACK - PAGE_SIZE;
#endif
p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
p->p_vmspace->vm_minsaddr = (caddr_t)(addr + PAGE_SIZE);
if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
NULL, UVM_UNKNOWN_OFFSET, 0,
UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_MASK, MAP_INHERIT_COPY,
MADV_NORMAL,
UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW|UVM_FLAG_STACK)))
panic("init: couldn't allocate argument space");
for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
#ifdef MACHINE_STACK_GROWS_UP
ucp = (char *)addr;
#else
ucp = (char *)(addr + PAGE_SIZE);
#endif
flagsp = flags;
*flagsp++ = '-';
options = 0;
if (boothowto & RB_SINGLE) {
*flagsp++ = 's';
options = 1;
}
#ifdef notyet
if (boothowto & RB_FASTBOOT) {
*flagsp++ = 'f';
options = 1;
}
#endif
if (options != 0) {
*flagsp++ = '\0';
i = flagsp - flags;
#ifdef DEBUG
printf("init: copying out flags `%s' %ld\n", flags, i);
#endif
#ifdef MACHINE_STACK_GROWS_UP
arg1 = ucp;
(void)copyout((caddr_t)flags, (caddr_t)ucp, i);
ucp += i;
#else
(void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
arg1 = ucp;
#endif
}
i = strlen(path) + 1;
#ifdef DEBUG
printf("init: copying out path `%s' %ld\n", path, i);
#endif
#ifdef MACHINE_STACK_GROWS_UP
arg0 = ucp;
(void)copyout((caddr_t)path, (caddr_t)ucp, i);
ucp += i;
ucp = (caddr_t)ALIGN((u_long)ucp);
uap = (char **)ucp + 3;
#else
(void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
arg0 = ucp;
uap = (char **)((u_long)ucp & ~ALIGNBYTES);
#endif
i = 0;
copyout(&i, (caddr_t)--uap, sizeof(register_t));
if (options != 0)
copyout(&arg1, (caddr_t)--uap, sizeof(register_t));
copyout(&arg0, (caddr_t)--uap, sizeof(register_t));
SCARG(&args, path) = arg0;
SCARG(&args, argp) = uap;
SCARG(&args, envp) = NULL;
if ((error = sys_execve(p, &args, retval)) == EJUSTRETURN) {
KERNEL_UNLOCK();
return;
}
if (error != ENOENT)
printf("exec %s: error %d\n", path, error);
}
printf("init: not found\n");
panic("no init");
}