Luna/kernel/src/thread/ThreadImage.cpp
apio 3032415bc0
All checks were successful
Build and test / build (push) Successful in 1m52s
kernel: Move "push_mem_on_stack" and "pop_mem_from_stack" to MemoryManager
2024-11-23 20:03:04 +01:00

103 lines
3.2 KiB
C++

#include "thread/ThreadImage.h"
#include "memory/MemoryManager.h"
#include "thread/Thread.h"
#include <bits/mmap-flags.h>
#include <luna/Alignment.h>
#include <luna/CString.h>
static constexpr usize DEFAULT_USER_STACK_PAGES = 6;
static constexpr usize DEFAULT_USER_STACK_SIZE = DEFAULT_USER_STACK_PAGES * ARCH_PAGE_SIZE;
static Result<void> create_user_stack(Stack& user_stack, AddressSpace* space)
{
auto base = TRY(space->alloc_region_near_end(DEFAULT_USER_STACK_PAGES, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, true));
TRY(MemoryManager::alloc_at_zeroed(base, DEFAULT_USER_STACK_PAGES, MMU::ReadWrite | MMU::NoExecute | MMU::User));
user_stack = { base, DEFAULT_USER_STACK_SIZE };
return {};
}
Result<OwnedPtr<ThreadImage>> ThreadImage::try_load_from_binary(SharedPtr<BinaryFormatLoader> loader)
{
auto image = TRY(make_owned<ThreadImage>());
auto address_space = TRY(AddressSpace::try_create());
auto old_directory = MMU::get_page_directory();
MMU::switch_page_directory(address_space->page_directory());
auto guard = make_scope_guard([=] { MMU::switch_page_directory(old_directory); });
const u64 entry = TRY(loader->load(address_space.ptr()));
Stack user_stack;
TRY(create_user_stack(user_stack, address_space.ptr()));
guard.deactivate();
image->m_user_stack = user_stack;
image->m_program_entry = entry;
image->m_address_space = move(address_space);
image->m_sp = user_stack.top();
return image;
}
Result<OwnedPtr<ThreadImage>> ThreadImage::clone_from_thread(Thread* parent)
{
auto image = TRY(make_owned<ThreadImage>());
auto address_space = TRY(parent->address_space->clone());
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_kernel_stack = kernel_stack;
image->m_user_stack = parent->stack;
image->m_program_entry = parent->ip();
image->m_address_space = move(address_space);
image->m_sp = parent->sp();
return image;
}
Result<u64> ThreadImage::push_mem_on_stack(const u8* mem, usize size)
{
return MemoryManager::push_mem_on_stack(mem, size, m_user_stack, m_sp);
}
Result<u64> ThreadImage::push_string_vector_on_stack(const Vector<String>& vec)
{
Vector<u64> user_vec;
TRY(user_vec.try_reserve(vec.size() + 1));
for (const auto& item : vec)
{
// Copy each individual string and retrieve a userspace pointer to said copy
u64 addr = TRY(push_mem_on_stack((const u8*)item.chars(), item.length() + 1));
TRY(user_vec.try_append(addr));
}
TRY(user_vec.try_append((u64) nullptr));
// Copy the actual vector of userspace pointers to the stack
return TRY(push_mem_on_stack((u8*)user_vec.data(), user_vec.size() * sizeof(u64)));
}
void ThreadImage::apply(Thread* thread)
{
thread->init_regs_user();
thread->set_ip(m_program_entry);
if (m_kernel_stack.bottom()) thread->kernel_stack = m_kernel_stack;
thread->stack = m_user_stack;
thread->set_sp(align_down<16>(m_sp));
thread->active_directory = m_address_space->page_directory();
thread->address_space = move(m_address_space);
}