#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/pcb.h>
#include <sys/systm.h>
#include <sys/signal.h>
#include <sys/cred.h>
#include <sys/user.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/priocntl.h>
#include <sys/procset.h>
#include <sys/disp.h>
#include <sys/callo.h>
#include <sys/callb.h>
#include <sys/debug.h>
#include <sys/conf.h>
#include <sys/bootconf.h>
#include <sys/utsname.h>
#include <sys/cmn_err.h>
#include <sys/vmparam.h>
#include <sys/modctl.h>
#include <sys/vm.h>
#include <sys/callb.h>
#include <sys/ddi_periodic.h>
#include <sys/kmem.h>
#include <sys/vmem.h>
#include <sys/cpuvar.h>
#include <sys/cladm.h>
#include <sys/corectl.h>
#include <sys/exec.h>
#include <sys/syscall.h>
#include <sys/reboot.h>
#include <sys/task.h>
#include <sys/exacct.h>
#include <sys/autoconf.h>
#include <sys/errorq.h>
#include <sys/class.h>
#include <sys/stack.h>
#include <sys/brand.h>
#include <sys/mmapobj.h>
#include <sys/smt.h>
#include <vm/as.h>
#include <vm/seg_kmem.h>
#include <sys/dc_ki.h>
#include <c2/audit.h>
#include <sys/bootprops.h>
proc_t *proc_sched;
proc_t *proc_init;
proc_t *proc_pageout;
proc_t *proc_fsflush;
pgcnt_t maxmem;
pgcnt_t freemem;
int interrupts_unleashed;
kmem_cache_t *process_cache;
int audit_active = C2AUDIT_DISABLED;
lwpdir_t p0_lwpdir[2];
tidhash_t p0_tidhash[2];
lwpent_t p0_lep;
int cluster_bootflags = 0;
void
cluster_wrapper(void)
{
cluster();
panic("cluster() returned");
}
char initname[INITNAME_SZ] = "/sbin/init";
char initargs[BOOTARGS_MAX] = "";
int
exec_init(const char *initpath, const char *args)
{
uintptr_t ucp;
uintptr_t uap;
uintptr_t *argv;
uintptr_t exec_fnamep;
char *scratchargs;
int i, sarg;
size_t argvlen, alen;
size_t wlen = sizeof (uintptr_t);
boolean_t in_arg;
int argc = 0;
int error = 0, count = 0;
proc_t *p = ttoproc(curthread);
klwp_t *lwp = ttolwp(curthread);
int brand_action;
if (args == NULL)
args = "";
alen = strlen(initpath) + 1 + strlen(args) + 1;
scratchargs = kmem_alloc(alen, KM_SLEEP);
(void) snprintf(scratchargs, alen, "%s %s", initpath, args);
in_arg = B_FALSE;
for (i = 0; i < strlen(scratchargs); i++) {
if (scratchargs[i] == ' ' || scratchargs[i] == '\0') {
if (in_arg) {
in_arg = B_FALSE;
argc++;
}
} else {
in_arg = B_TRUE;
}
}
argvlen = sizeof (uintptr_t) * (argc + 1);
argv = kmem_zalloc(argvlen, KM_SLEEP);
ucp = (uintptr_t)p->p_usrstack;
argc = 0;
in_arg = B_FALSE;
sarg = 0;
for (i = 0; i < alen; i++) {
if (scratchargs[i] == ' ' || scratchargs[i] == '\0') {
if (in_arg == B_TRUE) {
in_arg = B_FALSE;
scratchargs[i] = '\0';
argv[argc++] = ucp - (alen - sarg);
}
} else if (in_arg == B_FALSE) {
in_arg = B_TRUE;
sarg = i;
}
}
exec_fnamep = argv[0];
ucp -= alen;
error |= copyout(scratchargs, (caddr_t)ucp, alen);
if (p->p_model == DATAMODEL_ILP32) {
uintptr32_t *argv32;
argv32 = kmem_zalloc(argvlen / 2, KM_SLEEP);
for (i = 0; i < argc; i++)
argv32[i] = (uintptr32_t)argv[i];
kmem_free(argv, argvlen);
argv = (uintptr_t *)argv32;
argvlen /= 2;
wlen = sizeof (uintptr32_t);
}
uap = P2ALIGN(ucp, wlen);
uap -= wlen;
uap -= (argc + 1) * wlen;
error |= copyout(argv, (caddr_t)uap, argvlen);
if (error != 0) {
zcmn_err(p->p_zone->zone_id, CE_WARN,
"Could not construct stack for init.\n");
kmem_free(argv, argvlen);
kmem_free(scratchargs, alen);
return (EFAULT);
}
kmem_free(argv, argvlen);
kmem_free(scratchargs, alen);
lwp->lwp_ap = lwp->lwp_arg;
lwp->lwp_arg[0] = exec_fnamep;
lwp->lwp_arg[1] = uap;
lwp->lwp_arg[2] = 0;
curthread->t_post_sys = 1;
curthread->t_sysnum = SYS_execve;
sigemptyset(&curthread->t_hold);
brand_action = ZONE_IS_BRANDED(p->p_zone) ? EBA_BRAND : EBA_NONE;
again:
error = exec_common((const char *)exec_fnamep,
(const char **)uap, NULL, NULL, brand_action);
reset_syscall_args();
switch (error) {
case 0:
return (0);
case ENOENT:
zcmn_err(p->p_zone->zone_id, CE_WARN,
"exec(%s) failed (file not found).\n", initpath);
return (ENOENT);
case EAGAIN:
case EINTR:
++count;
if (count < 5) {
zcmn_err(p->p_zone->zone_id, CE_WARN,
"exec(%s) failed with errno %d. Retrying...\n",
initpath, error);
goto again;
}
}
zcmn_err(p->p_zone->zone_id, CE_WARN,
"exec(%s) failed with errno %d.", initpath, error);
return (error);
}
int
start_init_common()
{
proc_t *p = curproc;
ASSERT_STACK_ALIGNED();
p->p_zone->zone_proc_initpid = p->p_pid;
p->p_cstime = p->p_stime = p->p_cutime = p->p_utime = 0;
p->p_usrstack = (caddr_t)USRSTACK32;
p->p_model = DATAMODEL_ILP32;
p->p_stkprot = PROT_ZFOD & ~PROT_EXEC;
p->p_datprot = PROT_ZFOD & ~PROT_EXEC;
p->p_stk_ctl = INT32_MAX;
p->p_as = as_alloc();
p->p_as->a_proc = p;
p->p_as->a_userlimit = (caddr_t)USERLIMIT32;
(void) hat_setup(p->p_as->a_hat, HAT_INIT);
init_core();
init_mstate(curthread, LMS_SYSTEM);
return (exec_init(p->p_zone->zone_initname, p->p_zone->zone_bootargs));
}
static void
start_init(void)
{
proc_init = curproc;
ASSERT(curproc->p_zone->zone_initname != NULL);
if (start_init_common() != 0)
halt("unix: Could not start init");
lwp_rtt();
}
void
main(void)
{
proc_t *p = ttoproc(curthread);
int (**initptr)();
extern void sched();
extern void fsflush();
extern int (*init_tbl[])();
extern int (*mp_init_tbl[])();
extern id_t syscid, defaultcid;
extern int swaploaded;
extern int netboot;
extern ib_boot_prop_t *iscsiboot_prop;
extern void vm_init(void);
extern void cbe_init_pre(void);
extern void cbe_init(void);
extern void clock_tick_init_pre(void);
extern void clock_tick_init_post(void);
extern void clock_init(void);
extern void physio_bufs_init(void);
extern void pm_cfb_setup_intr(void);
extern int pm_adjust_timestamps(dev_info_t *, void *);
extern void start_other_cpus(int);
extern void sysevent_evc_thrinit();
extern kmutex_t ualock;
#if defined(__x86)
extern void fastboot_post_startup(void);
extern void progressbar_start(void);
#endif
ASSERT(CPU == CPU->cpu_self);
ASSERT(curthread == CPU->cpu_thread);
ASSERT_STACK_ALIGNED();
mutex_enter(&ualock);
lgrp_init(LGRP_INIT_STAGE2);
startup();
segkmem_gc();
callb_init();
cbe_init_pre();
ddi_periodic_init();
cbe_init();
callout_init();
clock_tick_init_pre();
clock_init();
#if defined(__x86)
progressbar_start();
#endif
init_mstate(&t0, LMS_SYSTEM);
init_cpu_mstate(CPU, CMS_SYSTEM);
lgrp_init(LGRP_INIT_STAGE3);
for (initptr = &init_tbl[0]; *initptr; initptr++)
(**initptr)();
ld_ib_prop();
vm_init();
physio_bufs_init();
ttolwp(curthread)->lwp_error = 0;
(void) spl0();
interrupts_unleashed = 1;
process_cache = kmem_cache_create("process_cache", sizeof (proc_t),
0, NULL, NULL, NULL, NULL, NULL, 0);
vfs_mountroot();
errorq_init();
cpu_kstat_init(CPU);
ddi_walk_devs(ddi_root_node(), pm_adjust_timestamps, NULL);
post_startup();
swaploaded = 1;
audit_init();
vmem_update(NULL);
if (netboot == 0 && iscsiboot_prop == NULL)
(void) strplumb();
gethrestime(&PTOU(curproc)->u_start);
curthread->t_start = PTOU(curproc)->u_start.tv_sec;
p->p_mstart = gethrtime();
consconfig();
#ifndef __sparc
release_bootstrap();
#endif
i_ddi_forceattach_drivers();
setupclock();
p->p_lwpdir = p->p_lwpfree = p0_lwpdir;
p->p_lwpdir->ld_next = p->p_lwpdir + 1;
p->p_lwpdir_sz = 2;
p->p_tidhash = p0_tidhash;
p->p_tidhash_sz = 2;
p0_lep.le_thread = curthread;
p0_lep.le_lwpid = curthread->t_tid;
p0_lep.le_start = curthread->t_start;
lwp_hash_in(p, &p0_lep, p0_tidhash, 2, 0);
exacct_init();
sysevent_evc_thrinit();
lgrp_init(LGRP_INIT_STAGE4);
start_other_cpus(0);
#ifdef __sparc
release_bootstrap();
#endif
lgrp_init(LGRP_INIT_STAGE5);
kmem_mp_init();
clock_tick_init_post();
for (initptr = &mp_init_tbl[0]; *initptr; initptr++)
(**initptr)();
pm_cfb_setup_intr();
#if defined(__x86)
fastboot_post_startup();
smt_late_init();
#endif
if (newproc(start_init, NULL, defaultcid, 59, NULL,
FAMOUS_PID_INIT))
panic("main: unable to fork init.");
if (newproc(pageout, NULL, syscid, maxclsyspri - 1, NULL,
FAMOUS_PID_PAGEOUT))
panic("main: unable to fork pageout()");
if (newproc(fsflush, NULL, syscid, minclsyspri, NULL,
FAMOUS_PID_FSFLUSH))
panic("main: unable to fork fsflush()");
if (cluster_bootflags & CLUSTER_BOOTED) {
if (newproc(cluster_wrapper, NULL, syscid, minclsyspri,
NULL, 0)) {
panic("main: unable to fork cluster()");
}
}
(void) thread_create(NULL, 0, (void (*)())mod_uninstall_daemon,
NULL, 0, &p0, TS_RUN, minclsyspri);
(void) thread_create(NULL, 0, seg_pasync_thread,
NULL, 0, &p0, TS_RUN, minclsyspri);
pid_setmin();
mutex_exit(&ualock);
bcopy("sched", PTOU(curproc)->u_psargs, 6);
bcopy("sched", PTOU(curproc)->u_comm, 5);
sched();
}