NetBSD-current /sbin/initが起動されるまで(3)
pack.ep_esch->es_emulはstruct emulのポインタになっており、NetBSDアプリケーションを実行する時はcompat/netbsd32/netbsd32_netbsd.cに定義されているemul_netbsd32が代入されている。
const struct emul emul_netbsd32 = { "netbsd32", "/emul/netbsd32", #ifndef __HAVE_MINIMAL_EMUL 0, NULL, NETBSD32_SYS_syscall, NETBSD32_SYS_NSYSENT, #endif netbsd32_sysent, #ifdef SYSCALL_DEBUG netbsd32_syscallnames, #else NULL, #endif netbsd32_sendsig, trapsignal, NULL, #ifdef COMPAT_16 netbsd32_sigcode, netbsd32_esigcode, &emul_netbsd32_object, #else NULL, NULL, NULL, #endif netbsd32_setregs, NULL, NULL, NULL, NULL, NULL, #ifdef __HAVE_SYSCALL_INTERN netbsd32_syscall_intern, #else syscall, #endif &netbsd32_sysctl_root, NULL, netbsd32_vm_default_addr, NULL, sizeof(ucontext32_t), startlwp32, };
netbsd32_setregsでgrepしてみると、以下の結果が得られた:
arch/sparc64/sparc64/netbsd32_machdep.c:netbsd32_setregs(struct lwp *l, struct exec_package *pack, u_long stack)
arch/sparc64/sparc64/svr4_32_machdep.c: netbsd32_setregs(l, epp, stack);
arch/amd64/amd64/netbsd32_machdep.c:netbsd32_setregs(struct lwp *l, struct exec_package *pack, u_long stack)
arch/powerpc/include/netbsd32_machdep.h:void netbsd32_setregs (struct lwp *, struct exec_package *, u_long);
mipsには同じ関数が見当たらないのだが、arch/mips/mips/mips_machdep.cの
void setregs(l, pack, stack)
がそれに当たる関数だと思う。
/* * Set registers on exec. * Clear all registers except sp, pc, and t9. * $sp is set to the stack pointer passed in. $pc is set to the entry * point given by the exec_package passed in, as is $t9 (used for PIC * code by the MIPS elf abi). */ void setregs(l, pack, stack) struct lwp *l; struct exec_package *pack; u_long stack; { struct frame *f = (struct frame *)l->l_md.md_regs; memset(f, 0, sizeof(struct frame)); f->f_regs[_R_SP] = (int)stack; f->f_regs[_R_PC] = (int)pack->ep_entry & ~3; f->f_regs[_R_T9] = (int)pack->ep_entry & ~3; /* abicall requirement */ f->f_regs[_R_SR] = PSL_USERSET; /* * Set up arguments for _start(): * _start(stack, obj, cleanup, ps_strings); * * Notes: * - obj and cleanup are the auxiliary and termination * vectors. They are fixed up by ld.elf_so. * - ps_strings is a NetBSD extension. */ f->f_regs[_R_A0] = (uintptr_t)stack; f->f_regs[_R_A1] = 0; f->f_regs[_R_A2] = 0; f->f_regs[_R_A3] = (intptr_t)l->l_proc->p_psstr; if ((l->l_md.md_flags & MDP_FPUSED) && l == fpcurlwp) fpcurlwp = NULL; memset(&l->l_addr->u_pcb.pcb_fpregs, 0, sizeof(struct fpreg)); l->l_md.md_flags &= ~MDP_FPUSED; l->l_md.md_ss_addr = 0; }
struct emulでは、e_setregsの次にe_proc_execが定義されている:
struct emul { const char *e_name; /* Symbolic name */ const char *e_path; /* Extra emulation path (NULL if none)*/ #ifndef __HAVE_MINIMAL_EMUL int e_flags; /* Miscellaneous flags, see above */ /* Syscall handling function */ const int *e_errno; /* Errno array */ int e_nosys; /* Offset of the nosys() syscall */ int e_nsysent; /* Number of system call entries */ #endif const struct sysent *e_sysent; /* System call array */ const char * const *e_syscallnames; /* System call name array */ /* Signal sending function */ void (*e_sendsig)(const struct ksiginfo *, const sigset_t *); void (*e_trapsignal)(struct lwp *, struct ksiginfo *); int (*e_tracesig)(struct proc *, int); char *e_sigcode; /* Start of sigcode */ char *e_esigcode; /* End of sigcode */ /* Set registers before execution */ struct uvm_object **e_sigobject;/* shared sigcode object */ void (*e_setregs)(struct lwp *, struct exec_package *, u_long); /* Per-process hooks */ void (*e_proc_exec)(struct proc *, struct exec_package *);
emul_netbsd32ではnetbsd32_setregsの次はNULLとされているので、proc_exec hookは実行されない。
if (pack.ep_esch->es_emul->e_proc_exec)
(*pack.ep_esch->es_emul->e_proc_exec)(p, &pack);
さて、プログラムをメモリにロードして、メモリ空間を用意し、レジスタをフレームに設定する所までは出来ました。
このプロセスのロードは、通常のスケジューリングによるコンテキスト切り替えから、という事でよいのかな?