71 lines
1.9 KiB
C++
71 lines
1.9 KiB
C++
|
#include "thread/ThreadImage.h"
|
||
|
#include "memory/MemoryManager.h"
|
||
|
#include "thread/Thread.h"
|
||
|
|
||
|
static Result<void> create_stacks(Stack& user_stack, Stack& kernel_stack)
|
||
|
{
|
||
|
const u64 THREAD_STACK_BASE = 0x10000;
|
||
|
|
||
|
TRY(MemoryManager::alloc_at(THREAD_STACK_BASE, 4, MMU::ReadWrite | MMU::NoExecute | MMU::User));
|
||
|
|
||
|
auto guard = make_scope_guard([&] { MemoryManager::unmap_owned(THREAD_STACK_BASE, 4); });
|
||
|
|
||
|
const u64 kernel_stack_base = TRY(MemoryManager::alloc_for_kernel(4, MMU::ReadWrite | MMU::NoExecute));
|
||
|
|
||
|
guard.deactivate();
|
||
|
|
||
|
user_stack = { THREAD_STACK_BASE, 4 * ARCH_PAGE_SIZE };
|
||
|
kernel_stack = { kernel_stack_base, 4 * ARCH_PAGE_SIZE };
|
||
|
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
Result<OwnedPtr<ThreadImage>> ThreadImage::try_load_from_elf(SharedPtr<VFS::Inode> inode)
|
||
|
{
|
||
|
auto image = TRY(make_owned<ThreadImage>());
|
||
|
|
||
|
auto vm_allocator = TRY(UserVM::try_create());
|
||
|
|
||
|
auto old_directory = MMU::get_page_directory();
|
||
|
|
||
|
auto new_directory = TRY(MMU::create_page_directory_for_userspace());
|
||
|
|
||
|
MMU::switch_page_directory(new_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));
|
||
|
|
||
|
Stack user_stack;
|
||
|
Stack kernel_stack;
|
||
|
TRY(create_stacks(user_stack, kernel_stack));
|
||
|
|
||
|
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;
|
||
|
image->m_vm_allocator = move(vm_allocator);
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
void ThreadImage::apply(Thread* thread)
|
||
|
{
|
||
|
thread->init_regs_user();
|
||
|
|
||
|
thread->set_ip(m_loaded_image_data.entry);
|
||
|
|
||
|
thread->kernel_stack = m_kernel_stack;
|
||
|
thread->stack = m_user_stack;
|
||
|
thread->set_sp(m_user_stack.top());
|
||
|
|
||
|
thread->directory = m_directory;
|
||
|
|
||
|
thread->vm_allocator = move(m_vm_allocator);
|
||
|
}
|