Almost there...
exec() is not working yet. But the rest are!!
This commit is contained in:
parent
24272c57ef
commit
5d41b4b113
@ -20,6 +20,8 @@
|
|||||||
namespace Syscall
|
namespace Syscall
|
||||||
{
|
{
|
||||||
void entry(Context* context);
|
void entry(Context* context);
|
||||||
|
|
||||||
|
char* strdup_from_user(const char* user_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_exit(Context* context, int status);
|
void sys_exit(Context* context, int status);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
|
#include "std/string.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
void Syscall::entry(Context* context)
|
void Syscall::entry(Context* context)
|
||||||
@ -27,4 +28,11 @@ void Syscall::entry(Context* context)
|
|||||||
default: context->rax = -ENOSYS; break;
|
default: context->rax = -ENOSYS; break;
|
||||||
}
|
}
|
||||||
VMM::exit_syscall_context();
|
VMM::exit_syscall_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Syscall::strdup_from_user(const char* user_string)
|
||||||
|
{
|
||||||
|
uint64_t phys = VMM::get_physical((uint64_t)user_string);
|
||||||
|
if (phys == (uint64_t)-1) { return nullptr; }
|
||||||
|
return strdup((const char*)phys);
|
||||||
}
|
}
|
@ -5,30 +5,35 @@
|
|||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
|
#include "memory/VMM.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
#include "sys/Syscall.h"
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
void sys_exec(Context* context, const char* pathname)
|
void sys_exec(Context* context, const char* pathname)
|
||||||
{
|
{
|
||||||
if (!pathname)
|
char* kpathname = Syscall::strdup_from_user(pathname);
|
||||||
|
if (!kpathname)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
kinfoln("exec(): executing %s", pathname);
|
kinfoln("exec(): executing %s", kpathname);
|
||||||
|
|
||||||
VFS::Node* program = VFS::resolve_path(pathname);
|
VFS::Node* program = VFS::resolve_path(kpathname);
|
||||||
if (!program)
|
if (!program)
|
||||||
{
|
{
|
||||||
|
kfree(kpathname);
|
||||||
context->rax = -ENOENT;
|
context->rax = -ENOENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program->type == VFS_DIRECTORY)
|
if (program->type == VFS_DIRECTORY)
|
||||||
{
|
{
|
||||||
|
kfree(kpathname);
|
||||||
context->rax = -EISDIR;
|
context->rax = -EISDIR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -36,6 +41,7 @@ void sys_exec(Context* context, const char* pathname)
|
|||||||
long memusage;
|
long memusage;
|
||||||
if ((memusage = ELFLoader::check_elf_image(program)) < 0)
|
if ((memusage = ELFLoader::check_elf_image(program)) < 0)
|
||||||
{
|
{
|
||||||
|
kfree(kpathname);
|
||||||
context->rax = -ENOEXEC;
|
context->rax = -ENOEXEC;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -43,12 +49,16 @@ void sys_exec(Context* context, const char* pathname)
|
|||||||
uint64_t allocated_stack = (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER);
|
uint64_t allocated_stack = (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER);
|
||||||
if (!allocated_stack)
|
if (!allocated_stack)
|
||||||
{
|
{
|
||||||
|
kfree(kpathname);
|
||||||
context->rax = -ENOMEM;
|
context->rax = -ENOMEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t allocated_stack_phys = VMM::get_physical(allocated_stack);
|
||||||
|
|
||||||
if ((uint64_t)memusage > PMM::get_free())
|
if ((uint64_t)memusage > PMM::get_free())
|
||||||
{
|
{
|
||||||
|
kfree(kpathname);
|
||||||
MemoryManager::release_pages((void*)allocated_stack, TASK_PAGES_IN_STACK);
|
MemoryManager::release_pages((void*)allocated_stack, TASK_PAGES_IN_STACK);
|
||||||
context->rax = -ENOMEM;
|
context->rax = -ENOMEM;
|
||||||
return;
|
return;
|
||||||
@ -64,17 +74,29 @@ void sys_exec(Context* context, const char* pathname)
|
|||||||
|
|
||||||
ELFLoader::release_elf_image(Scheduler::current_task()->image);
|
ELFLoader::release_elf_image(Scheduler::current_task()->image);
|
||||||
|
|
||||||
|
MemoryManager::release_pages((void*)task->allocated_stack, TASK_PAGES_IN_STACK);
|
||||||
|
|
||||||
|
task->address_space.destroy();
|
||||||
|
task->address_space = AddressSpace::create();
|
||||||
|
|
||||||
|
VMM::switch_to_user_address_space(task->address_space);
|
||||||
|
|
||||||
ELFImage* image = ELFLoader::load_elf_from_vfs(program);
|
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
|
ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly
|
||||||
// wrong.
|
// wrong.
|
||||||
|
|
||||||
MemoryManager::release_pages((void*)task->allocated_stack, TASK_PAGES_IN_STACK);
|
|
||||||
|
|
||||||
task->allocated_stack = allocated_stack;
|
task->allocated_stack = allocated_stack;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < TASK_PAGES_IN_STACK; i++)
|
||||||
|
{
|
||||||
|
VMM::map(allocated_stack + (i * PAGE_SIZE), allocated_stack_phys + (i * PAGE_SIZE), MAP_READ_WRITE | MAP_USER);
|
||||||
|
}
|
||||||
|
|
||||||
Scheduler::reset_task(task, image);
|
Scheduler::reset_task(task, image);
|
||||||
|
|
||||||
set_context_from_task(*task, context);
|
set_context_from_task(*task, context);
|
||||||
|
|
||||||
|
kfree(kpathname);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -4,7 +4,10 @@
|
|||||||
#include "interrupts/Context.h"
|
#include "interrupts/Context.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
|
#include "memory/VMM.h"
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
|
#include "std/stdlib.h"
|
||||||
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
|
|||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ssize_t result = current_task->files[fd].write(size, addr);
|
ssize_t result = current_task->files[fd].write(size, (const char*)VMM::get_physical((uint64_t)addr));
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -99,9 +102,17 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Node* node = VFS::resolve_path(filename);
|
char* kernel_filename = Syscall::strdup_from_user(filename);
|
||||||
|
if (!kernel_filename)
|
||||||
|
{
|
||||||
|
context->rax = -EFAULT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFS::Node* node = VFS::resolve_path(kernel_filename);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
|
kfree(kernel_filename);
|
||||||
context->rax = -ENOENT;
|
context->rax = -ENOENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -110,16 +121,18 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
bool can_write = (flags & OPEN_WRITE) > 0;
|
bool can_write = (flags & OPEN_WRITE) > 0;
|
||||||
if (!can_read && !can_write)
|
if (!can_read && !can_write)
|
||||||
{
|
{
|
||||||
|
kfree(kernel_filename);
|
||||||
context->rax = -EINVAL;
|
context->rax = -EINVAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
kdbgln("open(): opening %s %s, allocated file descriptor %d", filename,
|
kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename,
|
||||||
(can_read && can_write) ? "rw"
|
(can_read && can_write) ? "rw"
|
||||||
: can_read ? "r-"
|
: can_read ? "r-"
|
||||||
: "-w",
|
: "-w",
|
||||||
fd);
|
fd);
|
||||||
|
|
||||||
|
kfree(kernel_filename);
|
||||||
current_task->files[fd].open(node, can_read, can_write);
|
current_task->files[fd].open(node, can_read, can_write);
|
||||||
context->rax = fd;
|
context->rax = fd;
|
||||||
return;
|
return;
|
||||||
@ -143,7 +156,7 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
|
|||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ssize_t result = current_task->files[fd].read(size, buffer);
|
ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer));
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user