diff options
-rw-r--r-- | sys/include/sys/loader.h | 7 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 6 | ||||
-rw-r--r-- | sys/include/sys/sched.h | 1 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_loader.c | 58 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 61 |
6 files changed, 68 insertions, 67 deletions
diff --git a/sys/include/sys/loader.h b/sys/include/sys/loader.h index 9b38a55..43ad36e 100644 --- a/sys/include/sys/loader.h +++ b/sys/include/sys/loader.h @@ -60,8 +60,15 @@ struct auxval { uint64_t at_phnum; }; +struct exec_args { + char **argp, **envp; + struct auxval auxv; + struct vas vas; +}; + #if defined(_KERNEL) +uintptr_t loader_init_stack(void *stack_top, struct exec_args args); int loader_unload(struct vas vas, struct vm_range *exec_range); int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, size_t load_base, char **ld_path, struct vm_range *prog_range); diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 85dd912..ec7d25e 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -61,12 +61,6 @@ #define USER_TO_KERN(user) PHYS_TO_VIRT(user) #define KERN_TO_USER(kern) VIRT_TO_PHYS(kern) -struct exec_args { - char **argp, **envp; - struct auxval auxv; - struct vas vas; -}; - enum { ADDR_RANGE_EXEC = 0, /* Program address range */ ADDR_RANGE_STACK /* Stack address range */ diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index 01a58fe..8245120 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -43,7 +43,6 @@ void sched_init(void); void sched_exit(void); void sched_context_switch(struct trapframe *tf); void sched_rest(void); -uintptr_t sched_init_stack(void *stack_top, struct exec_args args); __noreturn uint64_t sys_exit(struct syscall_args *args); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 0386ffd..c76179a 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -118,7 +118,7 @@ exec_set_stack(struct proc *td, struct exec_args args) stack_range = &td->addr_range[ADDR_RANGE_STACK]; stack_top = stack_range->start + (PROC_STACK_SIZE); - sp = sched_init_stack((void *)stack_top, args); + sp = loader_init_stack((void *)stack_top, args); return sp; } diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c index a7f15e5..091a92b 100644 --- a/sys/kern/kern_loader.c +++ b/sys/kern/kern_loader.c @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/syslog.h> #include <sys/errno.h> +#include <sys/proc.h> #include <vm/vm.h> #include <vm/map.h> #include <vm/physseg.h> @@ -65,6 +66,63 @@ loader_unload(struct vas vas, struct vm_range *exec_range) return vm_map_destroy(vas, start, (end - start)); } +uintptr_t +loader_init_stack(void *stack_top, struct exec_args args) +{ + uintptr_t *sp = stack_top; + uintptr_t old_sp = 0; + size_t argc, envc, len; + char **argvp = args.argp; + char **envp = args.envp; + struct auxval auxv = args.auxv; + + /* 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, auxv.at_entry); + AUXVAL(sp, AT_PHDR, auxv.at_phdr); + AUXVAL(sp, AT_PHNUM, auxv.at_phnum); + AUXVAL(sp, AT_PAGESIZE, vm_get_page_size()); + 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] = KERN_TO_USER(old_sp); + } + + /* 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] = KERN_TO_USER(old_sp); + } + + STACK_PUSH(sp, argc); + return (uintptr_t)sp; +} + int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, size_t load_base, char **ld_path, struct vm_range *prog_range) { diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 669d255..0aebf5b 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -151,7 +151,7 @@ sched_create_stack(struct vas vas, bool user, struct exec_args args, stack = (uintptr_t)dynalloc(PROC_STACK_SIZE); stack_range->start = (uintptr_t)stack; stack_range->end = (uintptr_t)stack + PROC_STACK_SIZE; - return sched_init_stack((void *)(stack + PROC_STACK_SIZE), args); + return loader_init_stack((void *)(stack + PROC_STACK_SIZE), args); } stack = vm_alloc_pageframe(PROC_STACK_PAGES); @@ -165,7 +165,7 @@ sched_create_stack(struct vas vas, bool user, struct exec_args args, } memset(USER_TO_KERN(stack), 0, PROC_STACK_SIZE); - stack = sched_init_stack((void *)USER_TO_KERN(stack + PROC_STACK_SIZE), args); + stack = loader_init_stack((void *)USER_TO_KERN(stack + PROC_STACK_SIZE), args); return stack; } @@ -288,63 +288,6 @@ sched_make_idletd(void) sched_enqueue_td(td); } -uintptr_t -sched_init_stack(void *stack_top, struct exec_args args) -{ - uintptr_t *sp = stack_top; - uintptr_t old_sp = 0; - size_t argc, envc, len; - char **argvp = args.argp; - char **envp = args.envp; - struct auxval auxv = args.auxv; - - /* 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, auxv.at_entry); - AUXVAL(sp, AT_PHDR, auxv.at_phdr); - AUXVAL(sp, AT_PHNUM, auxv.at_phnum); - AUXVAL(sp, AT_PAGESIZE, vm_get_page_size()); - 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] = KERN_TO_USER(old_sp); - } - - /* 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] = KERN_TO_USER(old_sp); - } - - STACK_PUSH(sp, argc); - return (uintptr_t)sp; -} - /* * Cause an early preemption and lets * the next thread run. |