diff --git a/kernel/src/memory/UserVM.cpp b/kernel/src/memory/UserVM.cpp index 44ca77e2..bfb13450 100644 --- a/kernel/src/memory/UserVM.cpp +++ b/kernel/src/memory/UserVM.cpp @@ -15,6 +15,8 @@ Result> UserVM::try_create() TRY(ptr->create_null_region()); TRY(ptr->create_default_region()); + ptr->m_directory = TRY(MMU::create_page_directory_for_userspace()); + return move(ptr); } @@ -54,6 +56,8 @@ Result> UserVM::clone() ptr->m_regions.append(new_region); } + ptr->m_directory = TRY(MMU::clone_userspace_page_directory(m_directory)); + return move(ptr); } @@ -61,6 +65,19 @@ UserVM::UserVM() { } +UserVM& UserVM::operator=(UserVM&& other) +{ + if (&other == this) return *this; + + m_regions.consume([](VMRegion* region) { delete region; }); + MMU::delete_userspace_page_directory(m_directory); + + m_regions = other.m_regions; + m_directory = other.m_directory; + + return *this; +} + Result UserVM::alloc_region(usize count, bool persistent) { for (auto* region = m_regions.expect_last(); region; region = m_regions.previous(region).value_or(nullptr)) @@ -198,4 +215,5 @@ Result UserVM::split_region(VMRegion* parent, u64 boundary) UserVM::~UserVM() { m_regions.consume([](VMRegion* region) { delete region; }); + MMU::delete_userspace_page_directory(m_directory); } diff --git a/kernel/src/memory/UserVM.h b/kernel/src/memory/UserVM.h index 01d50d19..08550c89 100644 --- a/kernel/src/memory/UserVM.h +++ b/kernel/src/memory/UserVM.h @@ -1,4 +1,5 @@ #pragma once +#include "arch/MMU.h" #include #include #include @@ -19,6 +20,8 @@ class UserVM UserVM(); ~UserVM(); + UserVM& operator=(UserVM&& other); + Result alloc_region(usize count, bool persistent = false); Result test_and_alloc_region(u64 address, usize count, bool persistent = false) @@ -35,6 +38,11 @@ class UserVM Result> clone(); + PageDirectory* page_directory() const + { + return m_directory; + } + private: Result set_region(u64 address, usize count, bool used, bool persistent); Result create_default_region(); @@ -43,4 +51,5 @@ class UserVM void merge_contiguous_regions(VMRegion* a, VMRegion* b); Result split_region(VMRegion* parent, u64 boundary); LinkedList m_regions; + PageDirectory* m_directory; }; diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 9283a463..5ef59522 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -70,7 +70,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) kdbgln("exec: attempting to replace current image with %s", path.chars()); #endif - auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); }); + auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory()); }); auto image = TRY(ThreadImage::try_load_from_elf(inode)); @@ -99,8 +99,6 @@ Result sys_execve(Registers* regs, SyscallArgs args) } } - MMU::delete_userspace_page_directory(current->self_directory); - if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid(); if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid(); @@ -108,7 +106,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) image->apply(current); - MMU::switch_page_directory(current->self_directory); + MMU::switch_page_directory(current->self_directory()); current->set_arguments(user_argc, user_argv, user_envc, user_envp); @@ -123,7 +121,7 @@ Result sys_fork(Registers* regs, SyscallArgs) { auto current = Scheduler::current(); - auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); }); + auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory()); }); memcpy(¤t->regs, regs, sizeof(*regs)); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 876069d0..faaf1419 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -191,8 +191,6 @@ namespace Scheduler } } - if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->self_directory); - delete thread; CPU::enable_interrupts(); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 7ac4f3b0..309d2d6b 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -97,7 +97,11 @@ struct Thread : public LinkedListNode Thread* parent { nullptr }; Option child_being_waited_for = {}; - PageDirectory* self_directory; + PageDirectory* self_directory() const + { + return vm_allocator->page_directory(); + } + PageDirectory* active_directory { nullptr }; [[noreturn]] void exit_and_signal_parent(u8 status); diff --git a/kernel/src/thread/ThreadImage.cpp b/kernel/src/thread/ThreadImage.cpp index 0c999bd8..744145b2 100644 --- a/kernel/src/thread/ThreadImage.cpp +++ b/kernel/src/thread/ThreadImage.cpp @@ -36,14 +36,9 @@ Result> ThreadImage::try_load_from_elf(SharedPtrpage_directory()); - MMU::switch_page_directory(new_directory); - - auto guard = make_scope_guard([=] { - MMU::delete_userspace_page_directory(new_directory); - MMU::switch_page_directory(old_directory); - }); + auto guard = make_scope_guard([=] { MMU::switch_page_directory(old_directory); }); const ELFData data = TRY(ELFLoader::load(inode, vm_allocator.ptr())); @@ -53,7 +48,6 @@ Result> ThreadImage::try_load_from_elf(SharedPtrm_directory = new_directory; image->m_kernel_stack = kernel_stack; image->m_user_stack = user_stack; image->m_loaded_image_data = data; @@ -69,14 +63,11 @@ Result> ThreadImage::clone_from_thread(Thread* parent) auto vm_allocator = TRY(parent->vm_allocator->clone()); - auto new_directory = TRY(MMU::clone_userspace_page_directory(parent->self_directory)); - const ELFData data = { .entry = parent->ip() }; const u64 kernel_stack_base = TRY(MemoryManager::alloc_for_kernel(4, MMU::ReadWrite | MMU::NoExecute)); Stack kernel_stack { kernel_stack_base, 4 * ARCH_PAGE_SIZE }; - image->m_directory = new_directory; image->m_kernel_stack = kernel_stack; image->m_user_stack = parent->stack; image->m_loaded_image_data = data; @@ -124,8 +115,7 @@ void ThreadImage::apply(Thread* thread) thread->stack = m_user_stack; thread->set_sp(align_down<16>(m_sp)); - thread->self_directory = m_directory; - thread->active_directory = m_directory; + thread->active_directory = m_vm_allocator->page_directory(); thread->vm_allocator = move(m_vm_allocator); } diff --git a/kernel/src/thread/ThreadImage.h b/kernel/src/thread/ThreadImage.h index e568a629..498fbe40 100644 --- a/kernel/src/thread/ThreadImage.h +++ b/kernel/src/thread/ThreadImage.h @@ -29,7 +29,6 @@ class ThreadImage private: OwnedPtr m_vm_allocator; - PageDirectory* m_directory { nullptr }; Stack m_user_stack; Stack m_kernel_stack; ELFData m_loaded_image_data;