diff options
Diffstat (limited to 'arch/x86_64/kexec.c')
-rw-r--r-- | arch/x86_64/kexec.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/x86_64/kexec.c b/arch/x86_64/kexec.c new file mode 100644 index 0000000..406e8e7 --- /dev/null +++ b/arch/x86_64/kexec.c @@ -0,0 +1,50 @@ +#include "tasking.h" +#include "memory.h" +#include "string.h" +#include "arch/cpu.h" + +#define UMODE_STACK_TOP (USERLAND_MEMORY_LIMIT) +#define UMODE_STACKW PAGE_SIZE + +static void* +s_umode_stack(void) +{ + uintptr_t top = UMODE_STACK_TOP; + uintptr_t bottom = top - (UMODE_STACKW - 1); + + vm_ensure(bottom, top, (page_flags_t) { + .present = true, + .writeable = true, + .useraccess = true, + .executable = false + }); + return (void*)top; +} + +static inline void* +s_stack_push(void *sp, void *data, size_t len) +{ + sp = (void*)((uintptr_t)sp - len); + memcpy(sp, data, len); + return sp; +} + +void +kexec(void *ip, int kargc, char **kargv, int kenvc, char **kenvp) +{ + /* Allocate a page for the user stack. */ + void *sp = s_umode_stack(); + + intmax_t argc = kargc; + sp = s_stack_push(sp, &argc, sizeof(intmax_t)); + + /* TODO: Proper argv, envp*/ + sp = s_stack_push(sp, &kargv, sizeof(char**)); + + intmax_t envc = kenvc; + sp = s_stack_push(sp, &envc, sizeof(intmax_t)); + + sp = s_stack_push(sp, &kenvp, sizeof(char**)); + + umode_enter(ip, sp); +} |