aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/include/sys/loader.h7
-rw-r--r--sys/include/sys/proc.h6
-rw-r--r--sys/include/sys/sched.h1
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_loader.c58
-rw-r--r--sys/kern/kern_sched.c61
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.