kernel: Move Thread::self_directory to UserVM

Since this is only used by user threads, UserVM is a convenient/related place to store the PageDirectory in a RAII manner.
This commit is contained in:
apio 2023-07-09 20:32:42 +02:00
parent 5c9503ac71
commit 5e564e9ae3
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 38 additions and 22 deletions

View File

@ -15,6 +15,8 @@ Result<OwnedPtr<UserVM>> 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<OwnedPtr<UserVM>> 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<u64> 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<VMRegion*> UserVM::split_region(VMRegion* parent, u64 boundary)
UserVM::~UserVM()
{
m_regions.consume([](VMRegion* region) { delete region; });
MMU::delete_userspace_page_directory(m_directory);
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "arch/MMU.h"
#include <luna/LinkedList.h>
#include <luna/OwnedPtr.h>
#include <luna/Result.h>
@ -19,6 +20,8 @@ class UserVM
UserVM();
~UserVM();
UserVM& operator=(UserVM&& other);
Result<u64> alloc_region(usize count, bool persistent = false);
Result<bool> test_and_alloc_region(u64 address, usize count, bool persistent = false)
@ -35,6 +38,11 @@ class UserVM
Result<OwnedPtr<UserVM>> clone();
PageDirectory* page_directory() const
{
return m_directory;
}
private:
Result<bool> set_region(u64 address, usize count, bool used, bool persistent);
Result<void> create_default_region();
@ -43,4 +51,5 @@ class UserVM
void merge_contiguous_regions(VMRegion* a, VMRegion* b);
Result<VMRegion*> split_region(VMRegion* parent, u64 boundary);
LinkedList<VMRegion> m_regions;
PageDirectory* m_directory;
};

View File

@ -70,7 +70,7 @@ Result<u64> 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<u64> 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<u64> 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<u64> 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(&current->regs, regs, sizeof(*regs));

View File

@ -191,8 +191,6 @@ namespace Scheduler
}
}
if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->self_directory);
delete thread;
CPU::enable_interrupts();

View File

@ -97,7 +97,11 @@ struct Thread : public LinkedListNode<Thread>
Thread* parent { nullptr };
Option<pid_t> 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);

View File

@ -36,14 +36,9 @@ Result<OwnedPtr<ThreadImage>> ThreadImage::try_load_from_elf(SharedPtr<VFS::Inod
auto old_directory = MMU::get_page_directory();
auto new_directory = TRY(MMU::create_page_directory_for_userspace());
MMU::switch_page_directory(vm_allocator->page_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<OwnedPtr<ThreadImage>> ThreadImage::try_load_from_elf(SharedPtr<VFS::Inod
guard.deactivate();
image->m_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<OwnedPtr<ThreadImage>> 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);
}

View File

@ -29,7 +29,6 @@ class ThreadImage
private:
OwnedPtr<UserVM> m_vm_allocator;
PageDirectory* m_directory { nullptr };
Stack m_user_stack;
Stack m_kernel_stack;
ELFData m_loaded_image_data;