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_null_region());
|
||||||
TRY(ptr->create_default_region());
|
TRY(ptr->create_default_region());
|
||||||
|
|
||||||
|
ptr->m_directory = TRY(MMU::create_page_directory_for_userspace());
|
||||||
|
|
||||||
return move(ptr);
|
return move(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +56,8 @@ Result<OwnedPtr<UserVM>> UserVM::clone()
|
|||||||
ptr->m_regions.append(new_region);
|
ptr->m_regions.append(new_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptr->m_directory = TRY(MMU::clone_userspace_page_directory(m_directory));
|
||||||
|
|
||||||
return move(ptr);
|
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)
|
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))
|
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()
|
UserVM::~UserVM()
|
||||||
{
|
{
|
||||||
m_regions.consume([](VMRegion* region) { delete region; });
|
m_regions.consume([](VMRegion* region) { delete region; });
|
||||||
|
MMU::delete_userspace_page_directory(m_directory);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "arch/MMU.h"
|
||||||
#include <luna/LinkedList.h>
|
#include <luna/LinkedList.h>
|
||||||
#include <luna/OwnedPtr.h>
|
#include <luna/OwnedPtr.h>
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
@ -19,6 +20,8 @@ class UserVM
|
|||||||
UserVM();
|
UserVM();
|
||||||
~UserVM();
|
~UserVM();
|
||||||
|
|
||||||
|
UserVM& operator=(UserVM&& other);
|
||||||
|
|
||||||
Result<u64> alloc_region(usize count, bool persistent = false);
|
Result<u64> alloc_region(usize count, bool persistent = false);
|
||||||
|
|
||||||
Result<bool> test_and_alloc_region(u64 address, 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();
|
Result<OwnedPtr<UserVM>> clone();
|
||||||
|
|
||||||
|
PageDirectory* page_directory() const
|
||||||
|
{
|
||||||
|
return m_directory;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result<bool> set_region(u64 address, usize count, bool used, bool persistent);
|
Result<bool> set_region(u64 address, usize count, bool used, bool persistent);
|
||||||
Result<void> create_default_region();
|
Result<void> create_default_region();
|
||||||
@ -43,4 +51,5 @@ class UserVM
|
|||||||
void merge_contiguous_regions(VMRegion* a, VMRegion* b);
|
void merge_contiguous_regions(VMRegion* a, VMRegion* b);
|
||||||
Result<VMRegion*> split_region(VMRegion* parent, u64 boundary);
|
Result<VMRegion*> split_region(VMRegion* parent, u64 boundary);
|
||||||
LinkedList<VMRegion> m_regions;
|
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());
|
kdbgln("exec: attempting to replace current image with %s", path.chars());
|
||||||
#endif
|
#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));
|
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_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid();
|
||||||
if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid();
|
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);
|
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);
|
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 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));
|
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;
|
delete thread;
|
||||||
|
|
||||||
CPU::enable_interrupts();
|
CPU::enable_interrupts();
|
||||||
|
@ -97,7 +97,11 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
Thread* parent { nullptr };
|
Thread* parent { nullptr };
|
||||||
Option<pid_t> child_being_waited_for = {};
|
Option<pid_t> child_being_waited_for = {};
|
||||||
|
|
||||||
PageDirectory* self_directory;
|
PageDirectory* self_directory() const
|
||||||
|
{
|
||||||
|
return vm_allocator->page_directory();
|
||||||
|
}
|
||||||
|
|
||||||
PageDirectory* active_directory { nullptr };
|
PageDirectory* active_directory { nullptr };
|
||||||
|
|
||||||
[[noreturn]] void exit_and_signal_parent(u8 status);
|
[[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 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::switch_page_directory(old_directory); });
|
||||||
|
|
||||||
auto guard = make_scope_guard([=] {
|
|
||||||
MMU::delete_userspace_page_directory(new_directory);
|
|
||||||
MMU::switch_page_directory(old_directory);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ELFData data = TRY(ELFLoader::load(inode, vm_allocator.ptr()));
|
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();
|
guard.deactivate();
|
||||||
|
|
||||||
image->m_directory = new_directory;
|
|
||||||
image->m_kernel_stack = kernel_stack;
|
image->m_kernel_stack = kernel_stack;
|
||||||
image->m_user_stack = user_stack;
|
image->m_user_stack = user_stack;
|
||||||
image->m_loaded_image_data = data;
|
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 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 ELFData data = { .entry = parent->ip() };
|
||||||
|
|
||||||
const u64 kernel_stack_base = TRY(MemoryManager::alloc_for_kernel(4, MMU::ReadWrite | MMU::NoExecute));
|
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 };
|
Stack kernel_stack { kernel_stack_base, 4 * ARCH_PAGE_SIZE };
|
||||||
|
|
||||||
image->m_directory = new_directory;
|
|
||||||
image->m_kernel_stack = kernel_stack;
|
image->m_kernel_stack = kernel_stack;
|
||||||
image->m_user_stack = parent->stack;
|
image->m_user_stack = parent->stack;
|
||||||
image->m_loaded_image_data = data;
|
image->m_loaded_image_data = data;
|
||||||
@ -124,8 +115,7 @@ void ThreadImage::apply(Thread* thread)
|
|||||||
thread->stack = m_user_stack;
|
thread->stack = m_user_stack;
|
||||||
thread->set_sp(align_down<16>(m_sp));
|
thread->set_sp(align_down<16>(m_sp));
|
||||||
|
|
||||||
thread->self_directory = m_directory;
|
thread->active_directory = m_vm_allocator->page_directory();
|
||||||
thread->active_directory = m_directory;
|
|
||||||
|
|
||||||
thread->vm_allocator = move(m_vm_allocator);
|
thread->vm_allocator = move(m_vm_allocator);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ class ThreadImage
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
OwnedPtr<UserVM> m_vm_allocator;
|
OwnedPtr<UserVM> m_vm_allocator;
|
||||||
PageDirectory* m_directory { nullptr };
|
|
||||||
Stack m_user_stack;
|
Stack m_user_stack;
|
||||||
Stack m_kernel_stack;
|
Stack m_kernel_stack;
|
||||||
ELFData m_loaded_image_data;
|
ELFData m_loaded_image_data;
|
||||||
|
Loading…
Reference in New Issue
Block a user