From ec8b9640e2cdad763cc008a5263abf70276effa4 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 22 Apr 2023 15:35:32 +0300 Subject: [PATCH] Kernel: Usespace programs are now ran through ELF files only 64 bit elf files are supported for now. --- kernel/include/kernel/Process.h | 2 +- kernel/kernel/Process.cpp | 52 ++++++++++++++++++++++++++++++--- kernel/kernel/kernel.cpp | 11 +------ userspace/test.c | 4 ++- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 826af39d..4b392c74 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -24,7 +24,7 @@ namespace Kernel public: static BAN::ErrorOr create_kernel(entry_t, void*); - static BAN::ErrorOr create_userspace(void(*)()); + static BAN::ErrorOr create_userspace(BAN::StringView); ~Process(); [[noreturn]] void exit(); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 496ffb16..f0824a9c 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1,8 +1,11 @@ #include #include #include +#include #include #include +#include +#include #include @@ -33,25 +36,65 @@ namespace Kernel return process; } - BAN::ErrorOr Process::create_userspace(void(*entry)()) + BAN::ErrorOr Process::create_userspace(BAN::StringView path) { + auto* elf = TRY(LibELF::ELF::load_from_file(path)); + auto* process = create_process(); TRY(process->m_working_directory.push_back('/')); TRY(process->init_stdio()); process->m_mmu = new MMU(); ASSERT(process->m_mmu); + auto& elf_file_header = elf->file_header64(); + for (size_t i = 0; i < elf_file_header.e_phnum; i++) + { + auto& elf_program_header = elf->program_header64(i); + + switch (elf_program_header.p_type) + { + case LibELF::PT_NULL: + break; + case LibELF::PT_LOAD: + { + size_t page_start = elf_program_header.p_vaddr / 4096; + size_t page_end = BAN::Math::div_round_up(elf_program_header.p_vaddr + elf_program_header.p_memsz, 4096); + for (size_t page = page_start; page <= page_end; page++) + { + auto addr = Memory::Heap::get().take_free_page(); + process->m_mmu->map_page_at(addr, page * 4096, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); + } + process->m_mmu->load(); + memset((void*)elf_program_header.p_vaddr, 0, elf_program_header.p_memsz); + memcpy((void*)elf_program_header.p_vaddr, elf->data() + elf_program_header.p_offset, elf_program_header.p_filesz); + Process::current().mmu().load(); + + dwarnln("mapped {8H}->{8H} to {8H}->{8H}", + elf_program_header.p_offset, + elf_program_header.p_offset + elf_program_header.p_filesz, + elf_program_header.p_vaddr, + elf_program_header.p_vaddr + elf_program_header.p_memsz + ); + break; + } + default: + ASSERT_NOT_REACHED(); + } + } + TRY(process->add_thread( - [](void* entry_func) + [](void* entry) { Thread& current = Thread::current(); current.process().m_mmu->map_range(current.stack_base(), current.stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); current.process().m_mmu->load(); - current.jump_userspace((uintptr_t)entry_func); + current.jump_userspace((uintptr_t)entry); ASSERT_NOT_REACHED(); - }, (void*)entry + }, (void*)elf_file_header.e_entry )); + delete elf; + return process; } @@ -105,6 +148,7 @@ namespace Kernel s_processes.remove(i); s_process_lock.unlock(); + // FIXME: we can't assume this is the current process Scheduler::get().set_current_process_done(); } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 0cd3f722..042b60be 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -186,15 +186,6 @@ static void init2(void* tty1) ((TTY*)tty1)->initialize_device(); - MUST(Process::create_kernel( - [](void*) - { - if (auto res = LibELF::ELF::load_from_file("/boot/banan-os.kernel"sv); res.is_error()) - dwarnln("{}", res.error()); - Process::current().exit(); - }, nullptr - )); - jump_userspace(); return; @@ -216,5 +207,5 @@ static void jump_userspace() MMU::get().map_range((uintptr_t)&g_userspace_start, (uintptr_t)&g_userspace_end - (uintptr_t)&g_userspace_start, MMU::Flags::UserSupervisor | MMU::Flags::Present); MMU::get().map_range((uintptr_t)&g_kernel_start, (uintptr_t)&g_kernel_end - (uintptr_t)&g_kernel_start, MMU::Flags::UserSupervisor | MMU::Flags::Present); - MUST(Process::create_userspace(userspace_entry)); + MUST(Process::create_userspace("/bin/test"sv)); } diff --git a/userspace/test.c b/userspace/test.c index ffacf6e6..04e7f20a 100644 --- a/userspace/test.c +++ b/userspace/test.c @@ -1,5 +1,7 @@ +#include + int main() { + puts("Hello World!"); return 0; } -