Compare commits

...

2 Commits

Author SHA1 Message Date
7f8a8cdcaf
kernel, libc: Add an usleep() system call and use that to implement usleep() and sleep() in libc 2023-01-22 15:00:20 +01:00
d5b1d72396
x86_64/MMU: Map the kernel page directory to virtual memory
This avoids depending on the kernel address space to create a new userspace one,
since there is no physical memory access.

This was fine for a single process, since its address space was created from the kernel one
and no more address spaces were created,
but for two or more, this started to become problematic, since we would create one address space
while being in another process's address space, which has no direct mapping of physical memory.
2023-01-22 14:46:03 +01:00
8 changed files with 48 additions and 3 deletions
kernel
libc
luna/include/luna

@ -22,6 +22,7 @@ set(SOURCES
src/sys/console_write.cpp src/sys/console_write.cpp
src/sys/clock_gettime.cpp src/sys/clock_gettime.cpp
src/sys/allocate_memory.cpp src/sys/allocate_memory.cpp
src/sys/usleep.cpp
src/InitRD.cpp src/InitRD.cpp
src/ELF.cpp src/ELF.cpp
) )

@ -1,4 +1,5 @@
#include "arch/MMU.h" #include "arch/MMU.h"
#include "Log.h"
#include "memory/MemoryManager.h" #include "memory/MemoryManager.h"
#include <luna/CString.h> #include <luna/CString.h>
#include <luna/Result.h> #include <luna/Result.h>
@ -9,6 +10,7 @@
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
PageDirectory* g_kernel_directory; PageDirectory* g_kernel_directory;
u64 g_kernel_directory_virt;
void PageTableEntry::set_address(u64 addr) void PageTableEntry::set_address(u64 addr)
{ {
@ -278,12 +280,18 @@ namespace MMU
{ {
PageDirectory* const dir = get_page_directory(); PageDirectory* const dir = get_page_directory();
g_kernel_directory = dir; g_kernel_directory = dir;
const u64 paddr = (u64)dir; const u64 paddr = (u64)dir;
PageTableEntry& recursive_entry = dir->entries[rindex]; PageTableEntry& recursive_entry = dir->entries[rindex];
recursive_entry.read_write = true; recursive_entry.read_write = true;
recursive_entry.present = true; recursive_entry.present = true;
recursive_entry.set_address(paddr); recursive_entry.set_address(paddr);
flush_all(); flush_all();
g_kernel_directory_virt =
MemoryManager::get_kernel_mapping_for_frames((u64)dir, 1, MMU::ReadWrite | MMU::NoExecute).value();
kdbgln("MMU init page directory (ring0): virt %#.16lx, phys %p", g_kernel_directory_virt, g_kernel_directory);
} }
Result<PageDirectory*> create_page_directory_for_userspace() Result<PageDirectory*> create_page_directory_for_userspace()
@ -298,7 +306,9 @@ namespace MMU
recursive_entry.present = true; recursive_entry.present = true;
recursive_entry.set_address(directory_phys); recursive_entry.set_address(directory_phys);
directory->entries[511] = g_kernel_directory->entries[511]; kdbgln("MMU init page directory (ring3): virt %p, phys %#.16lx", directory, directory_phys);
directory->entries[511] = ((PageDirectory*)g_kernel_directory_virt)->entries[511];
// From now on, we're only going to use the physical address, since accessing the PageDirectory will be dealt // From now on, we're only going to use the physical address, since accessing the PageDirectory will be dealt
// with using recursive mapping. So let's make sure we don't leak any VM. // with using recursive mapping. So let's make sure we don't leak any VM.

12
kernel/src/sys/usleep.cpp Normal file

@ -0,0 +1,12 @@
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include <sys/types.h>
Result<u64> sys_usleep(Registers*, SyscallArgs args)
{
useconds_t us = (useconds_t)args[0];
kernel_sleep(us / 1000);
return 0;
}

@ -1,4 +1,4 @@
file(GLOB HEADERS include/*.h) file(GLOB_RECURSE HEADERS include/*.h)
set(SOURCES set(SOURCES
${HEADERS} ${HEADERS}

@ -11,5 +11,6 @@
typedef int pid_t; typedef int pid_t;
typedef __i64_t time_t; typedef __i64_t time_t;
typedef __u16_t mode_t; typedef __u16_t mode_t;
typedef __u64_t useconds_t;
#endif #endif

@ -24,6 +24,12 @@ extern "C"
/* Calls the operating system kernel for a specific service. */ /* Calls the operating system kernel for a specific service. */
long syscall(long num, ...); long syscall(long num, ...);
/* Sleeps for X microseconds. */
int usleep(useconds_t us);
/* Sleeps for X seconds. */
unsigned long sleep(unsigned long seconds);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -1,5 +1,7 @@
#include <bits/errno-return.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
extern "C" long arch_invoke_syscall(long, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern "C" long arch_invoke_syscall(long, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
@ -23,4 +25,16 @@ extern "C"
return rc; return rc;
} }
int usleep(useconds_t us)
{
long rc = syscall(SYS_usleep, us);
__errno_return(rc, int);
}
unsigned long sleep(unsigned long seconds)
{
syscall(SYS_usleep, seconds * 1000000);
return 0;
}
} }

@ -1,6 +1,7 @@
#pragma once #pragma once
#define enumerate_syscalls(_e) _e(exit) _e(console_write) _e(clock_gettime) _e(allocate_memory) _e(deallocate_memory) #define enumerate_syscalls(_e) \
_e(exit) _e(console_write) _e(clock_gettime) _e(allocate_memory) _e(deallocate_memory) _e(usleep)
enum Syscalls enum Syscalls
{ {