diff --git a/arch/x86_64/thread.c b/arch/x86_64/thread.c index 70d696c..a1937fa 100644 --- a/arch/x86_64/thread.c +++ b/arch/x86_64/thread.c @@ -1,6 +1,14 @@ #include #include +#define MAX_REG_ARGS 6 +#define REG_ARG_0 rdi +#define REG_ARG_1 rsi +#define REG_ARG_2 rdx +#define REG_ARG_3 rcx +#define REG_ARG_4 r8 +#define REG_ARG_5 r9 + /* this is the context information restored by ml_thread_switch. * since ml_thread_switch only jumps to kernel-mode, IRETQ isn't used, * and the extra register values needed by IRETQ aren't present. */ @@ -23,10 +31,12 @@ void ml_thread_prepare_kernel_context(uintptr_t ip, uintptr_t *sp) ctx->rfl = 0x202; } -extern void ml_thread_prepare_user_context( +extern kern_status_t ml_thread_prepare_user_context( virt_addr_t ip, virt_addr_t user_sp, - virt_addr_t *kernel_sp) + virt_addr_t *kernel_sp, + const uintptr_t *args, + size_t nr_args) { (*kernel_sp) -= sizeof(struct ml_cpu_context); @@ -39,4 +49,31 @@ extern void ml_thread_prepare_user_context( ctx->rflags = 0x202; ctx->rdi = 0; // arg 0 ctx->rsi = 0; // arg 1 + + for (size_t i = 0; i < nr_args; i++) { + switch (i) { + case 0: + ctx->REG_ARG_0 = args[i]; + break; + case 1: + ctx->REG_ARG_1 = args[i]; + break; + case 2: + ctx->REG_ARG_2 = args[i]; + break; + case 3: + ctx->REG_ARG_3 = args[i]; + break; + case 4: + ctx->REG_ARG_4 = args[i]; + break; + case 5: + ctx->REG_ARG_5 = args[i]; + break; + default: + return KERN_INVALID_ARGUMENT; + } + } + + return KERN_OK; } diff --git a/kernel/bsp.c b/kernel/bsp.c index df5808a..1db9a98 100644 --- a/kernel/bsp.c +++ b/kernel/bsp.c @@ -179,15 +179,52 @@ kern_status_t bsp_launch_async(struct bsp *bsp, struct task *task) return status; } + status = vm_region_map_object( + task->t_address_space, + VM_REGION_ANY_OFFSET, + bsp->bsp_vmo, + 0, + bsp->bsp_trailer.bsp_exec_offset, + VM_PROT_READ | VM_PROT_USER, + &bsp_data_base); + + if (status != KERN_OK) { + return status; + } + + status = map_executable(bsp, task, &entry); + if (status != KERN_OK) { + return status; + } #ifdef TRACE - vm_region_dump(task->t_address_space, 0); + vm_region_dump(task->t_address_space); #endif sp = stack_buffer + BOOTSTRAP_STACK_SIZE; tracek("bootstrap: entry=%llx, sp=%llx", entry, sp); + kern_handle_t self, self_address_space; + task_open_handle(task, &task->t_base, 0, &self); + task_open_handle( + task, + &task->t_address_space->vr_base, + 0, + &self_address_space); + + const uintptr_t args[] = { + 0, // int argc + 0, // const char ** argv + self, // kern_handle_t task + self_address_space, // kern_handle_t address_space + + /* this parameter is specific to the bsp bootstrap program, so + * that it can access the rest of the bsp image. */ + bsp_data_base, + }; + const size_t nr_args = sizeof args / sizeof args[0]; + struct thread *init_thread = task_create_thread(task); - thread_init_user(init_thread, entry, sp); + thread_init_user(init_thread, entry, sp, args, nr_args); schedule_thread_on_cpu(init_thread); return KERN_OK; diff --git a/sched/thread.c b/sched/thread.c index 36c73eb..d4d240e 100644 --- a/sched/thread.c +++ b/sched/thread.c @@ -54,7 +54,9 @@ kern_status_t thread_init_kernel(struct thread *thr, virt_addr_t ip) kern_status_t thread_init_user( struct thread *thr, virt_addr_t ip, - virt_addr_t sp) + virt_addr_t sp, + const uintptr_t *args, + size_t nr_args) { thr->tr_id = thr->tr_parent->t_next_thread_id++; @@ -84,7 +86,7 @@ kern_status_t thread_init_user( /* this context will be used by ml_user_return to jump to userspace * with the specified instruction pointer and user stack */ - ml_thread_prepare_user_context(ip, sp, &thr->tr_sp); + ml_thread_prepare_user_context(ip, sp, &thr->tr_sp, args, nr_args); /* this context will be used by the scheduler and ml_thread_switch to * jump to ml_user_return in kernel mode with the thread's kernel stack. */