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:
parent
5c9503ac71
commit
5e564e9ae3
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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(¤t->regs, regs, sizeof(*regs));
|
||||
|
||||
|
@ -191,8 +191,6 @@ namespace Scheduler
|
||||
}
|
||||
}
|
||||
|
||||
if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->self_directory);
|
||||
|
||||
delete thread;
|
||||
|
||||
CPU::enable_interrupts();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user