From 145ea4094538b4ca7ca29257b9443a328c948426 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 15 Oct 2022 20:30:54 +0200 Subject: [PATCH] fork() is almost working --- kernel/src/interrupts/Entry.cpp | 9 +++++-- kernel/src/std/string.cpp | 19 +++++++++++++-- kernel/src/sys/exec.cpp | 42 ++++----------------------------- kernel/src/thread/Scheduler.cpp | 6 ++--- 4 files changed, 30 insertions(+), 46 deletions(-) diff --git a/kernel/src/interrupts/Entry.cpp b/kernel/src/interrupts/Entry.cpp index f6562ae4..cd9ee88d 100644 --- a/kernel/src/interrupts/Entry.cpp +++ b/kernel/src/interrupts/Entry.cpp @@ -46,13 +46,18 @@ extern "C" void common_handler(Context* context) { kerrorln("Page fault in ring 3 (RIP %lx), while trying to access %lx, error code %ld", context->rip, context->cr2, context->error_code); + + if (Scheduler::current_task()) + { + kinfoln("Page fault ocurred while in task: %ld", Scheduler::current_task()->id); + } + + hang(); // FIXME: Remove this when multiple address spaces are working. kinfoln("Stack trace:"); StackTracer tracer(context->rbp); tracer.trace_with_ip(context->rip); - hang(); // FIXME: Remove this when multiple address spaces are working. - Scheduler::task_misbehave(context, -3); } } diff --git a/kernel/src/std/string.cpp b/kernel/src/std/string.cpp index c133e9fa..d6540ca2 100644 --- a/kernel/src/std/string.cpp +++ b/kernel/src/std/string.cpp @@ -87,7 +87,22 @@ char* strcat(char* dest, const char* src) char* strstr(char* haystack, const char* needle) { - return (char*)memmem(haystack, strlen(haystack), needle, strlen(needle)); + size_t needle_size = strlen(needle); + size_t haystack_size = strlen(haystack); + while (*haystack) + { + if (*haystack == *needle) + { + if (needle_size <= haystack_size) + { + if (!strncmp(haystack, needle, needle_size)) return haystack; + } + else { return NULL; } + } + haystack++; + haystack_size--; + } + return NULL; } void* memmem(void* haystack, size_t haystacklen, const void* needle, size_t needlelen) @@ -100,7 +115,7 @@ void* memmem(void* haystack, size_t haystacklen, const void* needle, size_t need { if (needlelen <= haystacklen) { - if (!memcmp(hs, nd, needlelen)) return (void*)const_cast(hs); + if (!memcmp(hs, nd, needlelen)) return (void*)(const_cast(hs)); } else { return NULL; } } diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index ddb708cf..bf559a19 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -6,6 +6,7 @@ #include "memory/MemoryManager.h" #include "memory/PMM.h" #include "memory/VMM.h" +#include "misc/hang.h" #include "std/stdlib.h" #include "std/string.h" #include "sys/Syscall.h" @@ -13,8 +14,7 @@ #include "thread/Scheduler.h" #include "utils/Addresses.h" -void sys_fork(Context* context) // FIXME: Even though both processes's address spaces are the same in content, writing - // to one should not affect the other. +void sys_fork(Context* context) { kinfoln("fork(): attempting fork"); @@ -30,16 +30,10 @@ void sys_fork(Context* context) // FIXME: Even though both processes's address s } for (int i = 0; i < TASK_MAX_FDS; i++) { child->files[i] = parent->files[i]; } - size_t stack_bytes = get_top_of_stack(parent->allocated_stack, TASK_PAGES_IN_STACK) - parent->regs.rsp; - - child->regs.rsp = get_top_of_stack(child->allocated_stack, TASK_PAGES_IN_STACK) - stack_bytes; - - memcpy((void*)child->regs.rsp, (void*)parent->regs.rsp, stack_bytes); - - child->regs.rsp += sizeof(uintptr_t) * 2; // I don't know why this is... - child->address_space = parent->address_space.clone(); + child->regs.rsp += (2 * sizeof(uintptr_t)); + child->regs.rax = 0; context->rax = child->id; @@ -87,20 +81,9 @@ void sys_exec(Context* context, const char* pathname) return; } - uint64_t allocated_stack = (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); - if (!allocated_stack) - { - kfree(kpathname); - context->rax = -ENOMEM; - return; - } - - uint64_t allocated_stack_phys = VMM::get_physical(allocated_stack); - if ((uint64_t)memusage > PMM::get_free()) { kfree(kpathname); - MemoryManager::release_pages((void*)allocated_stack, TASK_PAGES_IN_STACK); context->rax = -ENOMEM; return; } @@ -111,29 +94,12 @@ void sys_exec(Context* context, const char* pathname) Task* task = Scheduler::current_task(); ASSERT(task); - if (task->address_space.is_cloned()) - { - kdbgln("Detaching cloned address space, %p, %s", (void*)task->address_space.get_pml4(), - task->address_space.is_cloned() ? "is cloned" : "is not cloned"); - task->address_space.detach(); - VMM::switch_to_user_address_space(task->address_space); - kdbgln("Detached cloned address space, %p, %s", (void*)task->address_space.get_pml4(), - task->address_space.is_cloned() ? "is cloned" : "is not cloned"); - } - // At this point, pretty much nothing can fail. ELFImage* image = ELFLoader::load_elf_from_vfs(program); ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly // wrong. - task->allocated_stack = allocated_stack; - - for (uint64_t i = 0; i < TASK_PAGES_IN_STACK; i++) - { - VMM::map(allocated_stack + (i * PAGE_SIZE), allocated_stack_phys + (i * PAGE_SIZE), MAP_READ_WRITE | MAP_USER); - } - Scheduler::reset_task(task, image); set_context_from_task(*task, context); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 3544bb9d..4a9fa0bb 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -132,8 +132,8 @@ void Scheduler::load_user_task(const char* filename) new_task->user_task = true; new_task->regs.rip = image->entry; new_task->image = image; - new_task->allocated_stack = (uint64_t)MemoryManager::get_pages( - TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right? + new_task->allocated_stack = (uint64_t)MemoryManager::get_pages_at( + 0x100000, TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right? new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); new_task->regs.cs = 0x18 | 0x03; new_task->regs.ss = 0x20 | 0x03; @@ -185,8 +185,6 @@ void Scheduler::reap_task(Task* task) VMM::switch_to_user_address_space(exiting_task->address_space); } kinfoln("reaping task %ld, exited with code %ld", exiting_task->id, exiting_task->exit_status); - if (exiting_task->allocated_stack) - MemoryManager::release_pages((void*)exiting_task->allocated_stack, TASK_PAGES_IN_STACK); if (exiting_task->image) // FIXME: Also free pages the task has mmap-ed but not munmap-ed. { // ELFLoader::release_elf_image(exiting_task->image);