From df4eeefc8f2436b1cf2829e63c9c2fc149b14111 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 30 Jan 2020 15:16:13 +0200 Subject: [PATCH] Userspace exec() --- sys/amd64/sched_s.S | 40 +++++++++++++++++++++++--- sys/amd64/syscall.c | 4 +-- sys/sched.c | 70 ++++++++++++++++++++++++++++++--------------- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/sys/amd64/sched_s.S b/sys/amd64/sched_s.S index 1414ac8..dca5ead 100644 --- a/sys/amd64/sched_s.S +++ b/sys/amd64/sched_s.S @@ -1,10 +1,6 @@ #include "sys/amd64/asm/asm_cpu.h" .section .text .global context_enter -.global context_enter_forked -context_enter_forked: - nop - nop context_enter: popq %rax popq %rdi @@ -18,6 +14,42 @@ context_enter: iretq +.global context_exec_enter +context_exec_enter: + // %rdi - arg + // %rsi - thread + // %rdx - stack + // %rcx - entry + movq (%rsi), %rsp + + pushq $0x1B + pushq %rdx + + pushq $0x200 + + pushq $0x23 + pushq %rcx + + // Zero registers before entry + xorq %rax, %rax + xorq %rcx, %rcx + xorq %rdx, %rdx + xorq %rbx, %rbx + + xorq %rsi, %rsi + xorq %rbp, %rbp + + xorq %r8, %r8 + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + xorq %r14, %r14 + xorq %r15, %r15 + + iretq + .global context_switch_first .global context_switch_to .type context_switch_to, %function diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index 8172474..d8e8021 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -6,11 +6,11 @@ #define MSR_IA32_SFMASK 0xC0000084 extern void syscall_entry(void); -extern void sys_fork(void); +extern int sys_exec(void *(*)(void *), void *arg); void *syscall_table[256] = { NULL, - [123] = sys_fork, + [124] = sys_exec, }; void syscall_undefined(uint64_t rax) { diff --git a/sys/sched.c b/sys/sched.c index 600bbb2..67f5bae 100644 --- a/sys/sched.c +++ b/sys/sched.c @@ -11,6 +11,8 @@ // Enter a newly-created task extern void context_enter(struct thread *thr); +// Enter a task from exec +extern void context_exec_enter(void *arg, struct thread *thr, uintptr_t stack3, uintptr_t entry); // Stores current task context, loads new one's extern void context_switch_to(struct thread *thr, struct thread *from); // No current task, only load the first task to begin execution @@ -218,6 +220,17 @@ struct sys_fork_frame { uint64_t rip; }; +int sys_exec(void *(*func)(void *), void *arg) { + _assert(func); + struct thread *thr = thread_current; + thr->data.rsp0 = thr->data.rsp0_top; + + uintptr_t rsp3 = thr->data.rsp3_base + thr->data.rsp3_size; + context_exec_enter(arg, thr, rsp3, (uintptr_t) func); + + panic("No\n"); +} + int sys_fork(struct sys_fork_frame *frame) { static int nfork = 0; static struct thread forkt[3] = {0}; @@ -235,6 +248,9 @@ int sys_fork(struct sys_fork_frame *frame) { mm_space_t space = amd64_mm_pool_alloc(); mm_space_fork(space, (mm_space_t) MM_VIRTUALIZE(src->data.cr3), MM_CLONE_FLG_KERNEL | MM_CLONE_FLG_USER); + dst->data.rsp3_base = src->data.rsp3_base; + dst->data.rsp3_size = src->data.rsp3_size; + space[AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 39] |= MM_PAGE_USER; uint64_t *pdpt = (uint64_t *) MM_VIRTUALIZE(space[AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 39] & ~0xFFF); for (uint64_t i = 0; i < 4; ++i) { @@ -317,28 +333,42 @@ int sys_fork(struct sys_fork_frame *frame) { return dst->pid; } +static void *u1(void *arg) { + uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(arg); + + *ptr = 0; + while (1) { + *ptr ^= '1' | 0xC00; + for (size_t i = 0; i < 1000000; ++i); + } + + return 0; +} + static void *u0(void *arg) { int r; asm volatile ("syscall":"=a"(r):"a"(123)); if (r == 0) { - arg = (void *) ((uint64_t) arg + 5); - uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8000 + (uint64_t) arg * 2); - *ptr = 0; - while (1) { - for (size_t i = 0; i < 10000000; ++i); - - *ptr ^= 'A' | 0x1200; - } + (void) u1; + asm volatile ("leaq u1(%rip), %rdi; movq $0xB8040, %rsi; movq $124, %rax; syscall"); } - uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8000 + (uint64_t) arg * 2); + + asm volatile ("syscall":"=a"(r):"a"(123)); + + if (r == 0) { + (void) u1; + asm volatile ("leaq u1(%rip), %rdi; movq $0xB8050, %rsi; movq $124, %rax; syscall"); + } + + uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8030); + *ptr = 0; - while (1) { - for (size_t i = 0; i < 10000000; ++i); - - *ptr ^= 'A' | 0x1200; + *ptr ^= '0' | 0xD00; + for (size_t i = 0; i < 1000000; ++i); } + return 0; } @@ -362,31 +392,25 @@ static struct thread t_n[3] = {0}; static struct thread t_u[3] = {0}; void sched_init(void) { + init_thread(&thread_idle, idle, 0, 0); + thread_idle.pid = -1; + init_thread(&t_n[0], t0, (void *) 0, 0); init_thread(&t_n[1], t0, (void *) 1, 0); init_thread(&t_n[2], t0, (void *) 2, 0); - init_thread(&t_u[0], u0, (void *) 5, 1); - init_thread(&t_u[1], u0, (void *) 6, 1); - init_thread(&t_u[2], u0, (void *) 7, 1); - init_thread(&thread_idle, idle, 0, 0); - - thread_idle.pid = -1; t_n[0].pid = 1; t_n[1].pid = 2; t_n[2].pid = 3; + init_thread(&t_u[0], u0, (void *) 0, 1); t_u[0].pid = 10; - t_u[1].pid = 11; - t_u[2].pid = 12; sched_queue(&t_n[0]); sched_queue(&t_n[1]); sched_queue(&t_n[2]); sched_queue(&t_u[0]); - sched_queue(&t_u[1]); - sched_queue(&t_u[2]); } void sched_enter(void) {