diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/proc_machdep.c | 60 | ||||
-rw-r--r-- | sys/include/sys/exec.h | 16 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 5 |
3 files changed, 81 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c index ee38f21..2b4368b 100644 --- a/sys/arch/amd64/amd64/proc_machdep.c +++ b/sys/arch/amd64/amd64/proc_machdep.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/errno.h> +#include <sys/exec.h> #include <machine/frame.h> #include <machine/gdt.h> #include <vm/physmem.h> @@ -39,6 +40,65 @@ #include <string.h> void +md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog) +{ + uintptr_t *sp = stack_top; + uintptr_t old_sp; + size_t argc, envc, len; + char **argvp = prog->argp; + char **envp = prog->envp; + struct auxval auxval = prog->auxval; + struct trapframe *tfp; + + /* Copy strings */ + old_sp = (uintptr_t)sp; + for (argc = 0; argvp[argc] != NULL; ++argc) { + len = strlen(argvp[argc]) + 1; + sp = (void *)((char *)sp - len); + memcpy((char *)sp, argvp[argc], len); + } + for (envc = 0; envp[envc] != NULL; ++envc) { + len = strlen(envp[envc]) + 1; + sp = (void *)((char *)sp - len); + memcpy((char *)sp, envp[envc], len); + } + + /* Ensure the stack is aligned */ + sp = (void *)ALIGN_DOWN((uintptr_t)sp, 16); + if (((argc + envc + 1) & 1) != 0) + --sp; + + AUXVAL(sp, AT_NULL, 0x0); + AUXVAL(sp, AT_SECURE, 0x0); + AUXVAL(sp, AT_ENTRY, auxval.at_entry); + AUXVAL(sp, AT_PHDR, auxval.at_phdr); + AUXVAL(sp, AT_PHNUM, auxval.at_phnum); + AUXVAL(sp, AT_PAGESIZE, DEFAULT_PAGESIZE); + STACK_PUSH(sp, 0); + + /* Copy envp pointers */ + sp -= envc; + for (int i = 0; i < envc; ++i) { + len = strlen(envp[i]) + 1; + old_sp -= len; + sp[i] = (uintptr_t)old_sp - VM_HIGHER_HALF; + } + + /* Copy argvp pointers */ + STACK_PUSH(sp, 0); + sp -= argc; + for (int i = 0; i < argc; ++i) { + len = strlen(argvp[i]) + 1; + old_sp -= len; + sp[i] = (uintptr_t)old_sp - VM_HIGHER_HALF; + } + + STACK_PUSH(sp, argc); + tfp = &td->tf; + tfp->rsp = (uintptr_t)sp - VM_HIGHER_HALF; +} + +void setregs(struct proc *td, struct exec_prog *prog, uintptr_t stack) { struct trapframe *tfp = &td->tf; diff --git a/sys/include/sys/exec.h b/sys/include/sys/exec.h index 4910ff2..73eae01 100644 --- a/sys/include/sys/exec.h +++ b/sys/include/sys/exec.h @@ -34,7 +34,23 @@ #if defined(_KERNEL) +/* Danger: Do not change these !! */ +#define AT_NULL 0 +#define AT_ENTRY 1 +#define AT_PHDR 2 +#define AT_PHENT 3 +#define AT_PHNUM 4 +#define AT_EXECPATH 5 +#define AT_SECURE 6 +#define AT_RANDOM 7 +#define AT_EXECFN 8 +#define AT_PAGESIZE 9 + #define MAX_PHDRS 32 +#define STACK_PUSH(PTR, VAL) *(--(PTR)) = VAL +#define AUXVAL(PTR, TAG, VAL) \ + STACK_PUSH(PTR, VAL); \ + STACK_PUSH(PTR, TAG); struct exec_range { uintptr_t start; diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 5303072..0c3cd33 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -43,6 +43,8 @@ #define PROC_STACK_PAGES 8 #define PROC_STACK_SIZE (PROC_STACK_PAGES * DEFAULT_PAGESIZE) +struct exec_prog; + struct proc { pid_t pid; struct trapframe tf; @@ -57,6 +59,9 @@ struct proc { struct proc *this_td(void); int md_fork(struct proc *p, struct proc *parent, uintptr_t ip); + +void md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog); + int fork1(struct proc *cur, int flags, void(*ip)(void), struct proc **newprocp); int exit1(struct proc *td); |