Luna/kernel/src/sys/exec.cpp

101 lines
2.2 KiB
C++
Raw Normal View History

#define MODULE "exec"
#include "errno.h"
#include "interrupts/Interrupts.h"
#include "kassert.h"
2022-10-16 16:23:33 +00:00
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
#include "memory/VMM.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/Syscall.h"
#include "sys/elf/ELFLoader.h"
#include "thread/Scheduler.h"
2022-10-14 16:00:33 +00:00
void sys_exec(Context* context, const char* pathname)
{
2022-10-14 16:00:33 +00:00
/*context->rax = -ENOSYS; // FIXME: Make exec() work under separate address spaces.
return;*/
2022-10-14 16:00:33 +00:00
char* kpathname = Syscall::strdup_from_user(pathname);
if (!kpathname)
{
2022-10-12 17:25:35 +00:00
context->rax = -EFAULT;
return;
}
kinfoln("exec(): executing %s", kpathname);
VFS::Node* program = VFS::resolve_path(kpathname);
if (!program)
{
kfree(kpathname);
context->rax = -ENOENT;
return;
}
if (program->type == VFS_DIRECTORY)
{
kfree(kpathname);
context->rax = -EISDIR;
return;
}
long memusage;
if ((memusage = ELFLoader::check_elf_image(program)) < 0)
{
kfree(kpathname);
context->rax = -ENOEXEC;
return;
}
if ((uint64_t)memusage > PMM::get_free())
{
kfree(kpathname);
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.
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.
Scheduler::reset_task(task, image);
task->restore_context(context);
kfree(kpathname);
return;
}
void sys_spawn(Context* context, const char* pathname)
{
char* kpathname = Syscall::strdup_from_user(pathname);
if (!kpathname)
{
context->rax = -EFAULT;
return;
}
kinfoln("spawn(): spawning %s", kpathname);
Task* current_task = Scheduler::current_task();
context->rax = Scheduler::load_user_task(kpathname);
kfree(kpathname);
VMM::switch_to_user_address_space(current_task->address_space);
2022-10-14 16:00:33 +00:00
return;
}