Luna/kernel/src/sys/exec.cpp
apio 69a9f7f06a Kernel: Move VMM from a class to a namespace
Also, rename the ugly Paging::VirtualMemoryManager name to just 'VMM'. Which is now used instead of kernelVMM.
2022-10-12 20:02:25 +02:00

80 lines
1.9 KiB
C++

#define MODULE "exec"
#include "assert.h"
#include "errno.h"
#include "interrupts/Interrupts.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/elf/ELFLoader.h"
#include "thread/Scheduler.h"
void sys_exec(Context* context, const char* pathname)
{
if (!pathname)
{
context->rax = -EFAULT;
return;
}
kinfoln("exec(): executing %s", pathname);
VFS::Node* program = VFS::resolve_path(pathname);
if (!program)
{
context->rax = -ENOENT;
return;
}
if (program->type == VFS_DIRECTORY)
{
context->rax = -EISDIR;
return;
}
long memusage;
if ((memusage = ELFLoader::check_elf_image(program)) < 0)
{
context->rax = -ENOEXEC;
return;
}
uint64_t allocated_stack = (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER);
if (!allocated_stack)
{
context->rax = -ENOMEM;
return;
}
if ((uint64_t)memusage > PMM::get_free())
{
MemoryManager::release_pages((void*)allocated_stack, TASK_PAGES_IN_STACK);
context->rax = -ENOMEM;
return;
}
Interrupts::disable();
ASSERT(!Interrupts::are_enabled()); // This part is pretty sensitive.
Task* task = Scheduler::current_task();
ASSERT(task);
// At this point, pretty much nothing can fail.
ELFLoader::release_elf_image(Scheduler::current_task()->image);
ELFImage* image = ELFLoader::load_elf_from_vfs(program);
ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly
// wrong.
MemoryManager::release_pages((void*)task->allocated_stack, TASK_PAGES_IN_STACK);
task->allocated_stack = allocated_stack;
Scheduler::reset_task(task, image);
set_context_from_task(*task, context);
return;
}