Fix sleep syscall

This commit is contained in:
Alex 2023-06-11 01:36:39 +03:00
parent f552b8f6f0
commit 85c0de688d
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
14 changed files with 829 additions and 673 deletions

View File

@ -31,64 +31,69 @@ extern "C" void SystemCallHandlerStub();
extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub()
{
asmv("swapgs\n"); /* Swap GS to get the CPUData */
asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to CPUData->TempStack */
asmv("mov %gs:0x0, %rsp\n"); /* Get CPUData->SystemCallStack and set it as rsp */
asmv("push $0x1b\n"); /* Push user data segment for SyscallsFrame */
asmv("push %gs:0x8\n"); /* Push CPUData->TempStack (old rsp) for SyscallsFrame */
asmv("push %r11\n"); /* Push the flags for SyscallsFrame */
asmv("push $0x23\n"); /* Push user code segment for SyscallsFrame */
asmv("push %rcx\n"); /* Push the return address for SyscallsFrame + sysretq (https://www.felixcloutier.com/x86/sysret) */
asmv("swapgs\n"); /* Swap GS to get the TCB */
asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to TCB->TempStack */
asmv("mov %gs:0x0, %rsp\n"); /* Get TCB->SystemCallStack and set it as rsp */
asmv("push $0x1b\n"); /* Push user data segment for SyscallsFrame */
asmv("push %gs:0x8\n"); /* Push TCB->TempStack (old rsp) for SyscallsFrame */
asmv("push %r11\n"); /* Push the flags for SyscallsFrame */
asmv("push $0x23\n"); /* Push user code segment for SyscallsFrame */
asmv("push %rcx\n"); /* Push the return address for SyscallsFrame + sysretq (https://www.felixcloutier.com/x86/sysret) */
asmv("push %rax\n" /* Push registers */
"push %rbx\n"
"push %rcx\n"
"push %rdx\n"
"push %rsi\n"
"push %rdi\n"
"push %rbp\n"
"push %r8\n"
"push %r9\n"
"push %r10\n"
"push %r11\n"
"push %r12\n"
"push %r13\n"
"push %r14\n"
"push %r15\n");
/* Push registers */
asmv("push %rax\n"
"push %rbx\n"
"push %rcx\n"
"push %rdx\n"
"push %rsi\n"
"push %rdi\n"
"push %rbp\n"
"push %r8\n"
"push %r9\n"
"push %r10\n"
"push %r11\n"
"push %r12\n"
"push %r13\n"
"push %r14\n"
"push %r15\n");
asmv("mov %rsp, %rdi\n"); /* Set the first argument to the SyscallsFrame pointer */
asmv("mov $0, %rbp\n");
asmv("call SystemCallsHandler\n");
/* Set the first argument to the SyscallsFrame pointer */
asmv("mov %rsp, %rdi\n");
asmv("mov $0, %rbp\n");
asmv("call SystemCallsHandler\n");
asmv("pop %r15\n" /* Pop registers except rax */
"pop %r14\n"
"pop %r13\n"
"pop %r12\n"
"pop %r11\n"
"pop %r10\n"
"pop %r9\n"
"pop %r8\n"
"pop %rbp\n"
"pop %rdi\n"
"pop %rsi\n"
"pop %rdx\n"
"pop %rcx\n"
"pop %rbx\n");
/* Pop registers except rax */
asmv("pop %r15\n"
"pop %r14\n"
"pop %r13\n"
"pop %r12\n"
"pop %r11\n"
"pop %r10\n"
"pop %r9\n"
"pop %r8\n"
"pop %rbp\n"
"pop %rdi\n"
"pop %rsi\n"
"pop %rdx\n"
"pop %rcx\n"
"pop %rbx\n");
asmv("mov %gs:0x8, %rsp\n"); // Restore rsp from CPUData->TempStack
/* Restore rsp from TCB->TempStack */
asmv("mov %gs:0x8, %rsp\n");
#ifdef DEBUG
asmv("movq $0, %gs:0x8\n"); // Easier to debug stacks // FIXME: Can't use xor
/* Easier to debug stacks */
asmv("movq $0, %gs:0x8\n");
#endif
asmv("swapgs\n"); // Swap GS back to the user GS
asmv("sti\n"); // Enable interrupts
asmv("sysretq\n"); // Return to rcx address in user mode
asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
}
void InitializeSystemCalls()
{
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1);
wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48));
wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub);
wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9));
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1);
wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48));
wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub);
wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9));
}

View File

@ -52,7 +52,6 @@ namespace CrashHandler
if (cpu)
{
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode);
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread);

View File

@ -67,7 +67,6 @@ namespace Interrupts
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE);
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
@ -85,7 +84,6 @@ namespace Interrupts
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE);
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{

View File

@ -60,6 +60,7 @@ namespace Memory
uint64_t MemMgr::GetAllocatedMemorySize()
{
SmartLock(MgrLock);
uint64_t Size = 0;
foreach (auto ap in AllocatedPagesList)
Size += ap.PageCount;
@ -68,6 +69,7 @@ namespace Memory
bool MemMgr::Add(void *Address, size_t Count)
{
SmartLock(MgrLock);
if (Address == nullptr)
{
error("Address is null!");
@ -124,6 +126,7 @@ namespace Memory
void *MemMgr::RequestPages(size_t Count, bool User)
{
SmartLock(MgrLock);
void *Address = KernelAllocator.RequestPages(Count);
for (size_t i = 0; i < Count; i++)
{
@ -162,6 +165,7 @@ namespace Memory
void MemMgr::FreePages(void *Address, size_t Count)
{
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
@ -205,6 +209,7 @@ namespace Memory
void MemMgr::DetachAddress(void *Address)
{
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
@ -226,6 +231,7 @@ namespace Memory
MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory)
{
SmartLock(MgrLock);
if (Table)
this->Table = Table;
else
@ -243,6 +249,7 @@ namespace Memory
MemMgr::~MemMgr()
{
SmartLock(MgrLock);
foreach (auto ap in AllocatedPagesList)
{
KernelAllocator.FreePages(ap.Address, ap.PageCount);

View File

@ -60,22 +60,32 @@ EXTERNC __weak __noreturn __no_stack_protector void __stack_chk_fail(void)
debug("Current stack check guard value: %#lx", __stack_chk_guard);
KPrint("\eFF0000Stack smashing detected!");
#if defined(a86)
void *Stack = nullptr;
#if defined(a86)
#if defined(a64)
asmv("movq %%rsp, %0"
: "=r"(Stack));
#elif defined(a32)
asmv("movl %%esp, %0"
: "=r"(Stack));
#endif
#elif defined(aa64)
asmv("mov %%sp, %0"
: "=r"(Stack));
#endif
error("Stack address: %#lx", Stack);
while (1)
asmv("cli; hlt");
if (DebuggerIsAttached)
#ifdef a86
asmv("int $0x3");
#elif defined(aa64)
asmv("wfe");
asmv("brk #0");
#endif
CPU::Stop();
}

View File

@ -497,21 +497,20 @@ void KernelMainThread()
TaskManager->WaitForThread(ret.Thread);
ExitCode = ret.Thread->GetExitCode();
Exit:
if (ExitCode != 0)
{
KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode,
ExitCode < 0 ? ExitCode * -1 : ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
}
else
if (ExitCode == 0)
{
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
Config.InitPath, ExitCode);
KPrint("System Halted");
CPU::Halt(true);
}
KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode,
ExitCode < 0 ? -ExitCode : ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
CPU::Halt(true);
}

View File

@ -16,105 +16,75 @@
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../syscalls.h"
#include "../kernel.h"
#include "../ipc.h"
#define SysFrm SyscallsFrame
using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID;
using Tasking::Token;
using Tasking::TTL;
using Tasking::TaskStatus::Ready;
using Tasking::TaskStatus::Terminated;
using Tasking::TTL::Trusted;
using Tasking::TTL::TrustedByKernel;
using Tasking::TTL::UnknownTrustLevel;
using Tasking::TTL::Untrusted;
static inline bool CheckTrust(int TrustLevel)
__noreturn static void sys_exit(SysFrm *, int code)
{
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
if (likely(TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel)))
return true;
trace("Userspace thread %s(%d) exited with code %d (%#x)",
TaskManager->GetCurrentThread()->Name,
TaskManager->GetCurrentThread()->ID, code,
code < 0 ? -code : code);
warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level",
TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID,
KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0))));
debug("token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token));
return false;
}
static int sys_exit(SyscallsFrame *Frame, int code)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel))
return SYSCALL_ACCESS_DENIED;
trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code);
TaskManager->GetCurrentThread()->ExitCode = code;
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
TaskManager->GetCurrentThread()->Status = Terminated;
TaskManager->Schedule();
UNUSED(Frame);
return SYSCALL_OK;
__builtin_unreachable();
}
static int sys_print(SyscallsFrame *Frame, char Char, int Index)
static int sys_print(SysFrm *, char Char, int Index)
{
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char ret = Display->Print(Char, Index, true);
if (!Config.BootAnimation && Index == 0)
#ifdef DEBUG
Display->SetBuffer(Index);
#else
if (Char == '\n')
Display->SetBuffer(Index);
#endif
UNUSED(Frame);
return ret;
}
static uintptr_t sys_request_pages(SyscallsFrame *Frame, size_t Count)
static uintptr_t sys_request_pages(SysFrm *, size_t Count)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
UNUSED(Frame);
return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true);
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
return (uintptr_t)MemMgr->RequestPages(Count + 1, true);
}
static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count)
static int sys_free_pages(SysFrm *, uintptr_t Address, size_t Count)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1);
UNUSED(Frame);
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
MemMgr->FreePages((void *)Address, Count + 1);
return SYSCALL_OK;
}
static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address)
static int sys_detach_address(SysFrm *, uintptr_t Address)
{
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address);
UNUSED(Frame);
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
MemMgr->DetachAddress((void *)Address);
return SYSCALL_OK;
}
static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
static int sys_memory_map(SysFrm *, uintptr_t VirtualAddress,
uintptr_t PhysicalAddress, size_t Size,
enum MemoryMapFlags Flags)
{
if (!CheckTrust(TrustedByKernel))
return SYSCALL_ACCESS_DENIED;
if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */
return SYSCALL_INVALID_ARGUMENT;
@ -126,15 +96,12 @@ static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintpt
Size, Flags);
}
UNUSED(Frame);
return SYSCALL_OK;
}
static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size_t Size)
static int sys_memory_unmap(SysFrm *, uintptr_t VirtualAddress,
size_t Size)
{
if (!CheckTrust(TrustedByKernel))
return SYSCALL_ACCESS_DENIED;
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
{
Memory::Virtual vmm = Memory::Virtual(PageTable);
@ -142,19 +109,18 @@ static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size
Size);
}
UNUSED(Frame);
return SYSCALL_OK;
}
static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
static uintptr_t sys_kernelctl(SysFrm *,
enum KCtl Command,
uint64_t Arg1, uint64_t Arg2,
uint64_t Arg3, uint64_t Arg4)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
switch (Command)
{
case KCTL_GET_PID:
return TaskManager->GetCurrentThread()->Parent->ID;
return TaskManager->GetCurrentProcess()->ID;
case KCTL_GET_TID:
return TaskManager->GetCurrentThread()->ID;
case KCTL_GET_PAGE_SIZE:
@ -163,9 +129,6 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
return TaskManager->GetCurrentThread()->Security.IsCritical;
case KCTL_REGISTER_ELF_LIB:
{
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1;
const char *Path = (const char *)Arg2;
@ -175,7 +138,8 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
std::string FullPath = Path;
int retries = 0;
RetryReadPath:
debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str());
debug("KCTL_REGISTER_ELF_LIB: Trying to open %s",
FullPath.c_str());
VirtualFileSystem::File f = vfs->Open(FullPath.c_str());
if (!f.IsOK())
@ -194,7 +158,8 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
break;
case 3:
{
VirtualFileSystem::Node *cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
VirtualFileSystem::Node *cwd =
TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
FullPath = vfs->GetPathFromNode(cwd).get();
break;
}
@ -223,9 +188,6 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
}
case KCTL_GET_ELF_LIB_MEMORY_IMAGE:
{
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1;
if (!Identifier)
return 0;
@ -234,17 +196,16 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
if (!lib.MemoryImage)
{
debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage);
debug("Failed to get library memory image %#lx",
(uintptr_t)lib.MemoryImage);
}
debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier);
debug("Returning memory image %#lx (%s)",
(uintptr_t)lib.MemoryImage, Identifier);
return (uintptr_t)lib.MemoryImage;
}
case KCTL_GET_ABSOLUTE_PATH:
{
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1;
void *Buffer = (void *)Arg2;
size_t BufferSize = Arg3;
@ -274,15 +235,11 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
UNUSED(Arg2);
UNUSED(Arg3);
UNUSED(Arg4);
UNUSED(Frame);
}
static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags)
static uint64_t sys_file_open(SysFrm *, const char *Path, uint64_t Flags)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
debug("(Path: %s, Flags: %#lx)", Path, Flags);
function("%s, %#lx", Path, Flags);
VirtualFileSystem::Node *cwd = nullptr;
if (vfs->PathIsRelative(Path))
cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
@ -297,118 +254,111 @@ static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t F
return SYSCALL_INTERNAL_ERROR;
}
VirtualFileSystem::File *KernelPrivate = (VirtualFileSystem::File *)TaskManager->GetCurrentThread()->Memory->RequestPages(TO_PAGES(sizeof(VirtualFileSystem::File)));
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
constexpr size_t FileStructPages =
TO_PAGES(sizeof(VirtualFileSystem::File));
VirtualFileSystem::File *KernelPrivate =
(VirtualFileSystem::File *)MemMgr->RequestPages(FileStructPages);
*KernelPrivate = KPObj;
debug("Opened file %s (%d)", KPObj.Name, KPObj.Status);
return (uint64_t)KernelPrivate;
UNUSED(Frame);
UNUSED(Flags);
}
static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate)
static int sys_file_close(SysFrm *, void *KernelPrivate)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
debug("(KernelPrivate: %#lx)", KernelPrivate);
function("%#lx", KernelPrivate);
if (KernelPrivate)
{
VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate;
debug("Closed file %s (%d)", KPObj.Name, KPObj.Status);
vfs->Close(KPObj);
TaskManager->GetCurrentThread()->Memory->FreePages(KernelPrivate, TO_PAGES(sizeof(VirtualFileSystem::File)));
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
MemMgr->FreePages(KernelPrivate,
TO_PAGES(sizeof(VirtualFileSystem::File)));
return SYSCALL_OK;
}
return SYSCALL_INVALID_ARGUMENT;
UNUSED(Frame);
}
static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
static uint64_t sys_file_read(SysFrm *, void *KernelPrivate,
uint8_t *Buffer, uint64_t Size)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size);
return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size);
UNUSED(Frame);
}
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)",
KernelPrivate, Buffer, Size);
static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size);
return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size);
UNUSED(Frame);
}
static off_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, off_t Offset, int Whence)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
return vfs->Read(*KPObj, Buffer, (size_t)Size);
}
static uint64_t sys_file_write(SysFrm *, void *KernelPrivate,
uint8_t *Buffer, uint64_t Size)
{
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)",
KernelPrivate, Buffer, Size);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
return vfs->Write(*KPObj, Buffer, (size_t)Size);
}
static off_t sys_file_seek(SysFrm *, void *KernelPrivate,
off_t Offset, int Whence)
{
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)",
KernelPrivate, Offset, Whence);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence);
debug("Seek %s %ld", KPObj->Name, ret);
return ret;
UNUSED(Frame);
}
static int sys_file_status(SyscallsFrame *Frame)
static int sys_file_status(SysFrm *)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
fixme("sys_file_status: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
static int sys_ipc(SysFrm *, enum IPCCommand Command,
enum IPCType Type, int ID, int Flags,
void *Buffer, size_t Size)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
UNUSED(Frame);
return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
InterProcessCommunication::IPC *ipc = TaskManager->GetCurrentProcess()->IPC;
return ipc->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
}
static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds)
static int sys_sleep(SysFrm *, uint64_t Milliseconds)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
UNUSED(Frame);
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
TaskManager->Sleep(Milliseconds);
TaskManager->Sleep(Milliseconds, true);
return 0;
}
static int sys_fork(SyscallsFrame *Frame)
static int sys_fork(SysFrm *Frame)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent;
Tasking::TCB *Thread = TaskManager->GetCurrentThread();
Tasking::PCB *NewProcess = TaskManager->CreateProcess(Parent,
Parent->Name,
Parent->Security.TrustLevel,
Parent->ELFSymbolTable ? Parent->ELFSymbolTable->GetImage() : nullptr);
void *ProcSymTable = nullptr;
if (Parent->ELFSymbolTable)
ProcSymTable = Parent->ELFSymbolTable->GetImage();
Tasking::PCB *NewProcess =
TaskManager->CreateProcess(Parent,
Parent->Name,
Parent->Security.TrustLevel,
ProcSymTable);
if (!NewProcess)
{
@ -419,14 +369,15 @@ static int sys_fork(SyscallsFrame *Frame)
strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name));
NewProcess->IPC->Fork(Parent->IPC);
Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess,
0,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
Thread->Info.Architecture,
Thread->Info.Compatibility,
true);
Tasking::TCB *NewThread =
TaskManager->CreateThread(NewProcess,
0,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
Thread->Info.Architecture,
Thread->Info.Compatibility,
true);
strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name));
@ -444,7 +395,9 @@ static int sys_fork(SyscallsFrame *Frame)
if (RetChild--)
{
/* We can't just return 0; because the CPUData->SystemCallStack is no longer valid */
/* We can't just return 0; because the
CPUData->SystemCallStack is no
longer valid */
asmv("movq %0, %%rcx\n"
:
: "r"(ReturnAddress));
@ -454,10 +407,10 @@ static int sys_fork(SyscallsFrame *Frame)
asmv("mov %0, %%rbp\n"
:
: "r"(ChildStackPointer));
asmv("movq $0, %rax\n"); // Return 0 to the child
asmv("swapgs\n"); // Swap GS back to the user GS
asmv("sti\n"); // Enable interrupts
asmv("sysretq\n"); // Return to rcx address in user mode
asmv("movq $0, %rax\n"); /* Return 0 to the child */
asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
}
RetChild = 1;
ReturnAddress = Frame->ReturnAddress;
@ -470,10 +423,12 @@ static int sys_fork(SyscallsFrame *Frame)
if (Thread->Security.IsCritical)
NewThread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(NewProcess->Security.UniqueToken,
(Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Parent->Security.UniqueToken));
TaskManager->GetSecurityManager()->TrustToken(NewThread->Security.UniqueToken,
(Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Thread->Security.UniqueToken));
Tasking::Security *Sec = TaskManager->GetSecurityManager();
Sec->TrustToken(NewProcess->Security.UniqueToken,
(TTL)Sec->GetTokenTrustLevel(Parent->Security.UniqueToken));
Sec->TrustToken(NewThread->Security.UniqueToken,
(TTL)Sec->GetTokenTrustLevel(Thread->Security.UniqueToken));
#ifdef a86
NewThread->ShadowGSBase = Thread->ShadowGSBase;
@ -482,180 +437,358 @@ static int sys_fork(SyscallsFrame *Frame)
#endif
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID);
NewThread->Status = Tasking::TaskStatus::Ready;
NewThread->Status = Ready;
return (int)NewThread->ID;
UNUSED(Frame);
}
static int sys_wait(SyscallsFrame *Frame)
static int sys_wait(SysFrm *)
{
fixme("sys_wait: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_kill(SyscallsFrame *Frame)
static int sys_kill(SysFrm *)
{
fixme("sys_kill: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_spawn(SyscallsFrame *Frame)
static int sys_spawn(SysFrm *)
{
fixme("sys_spawn: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_spawn_thread(SyscallsFrame *Frame, uint64_t InstructionPointer)
static int sys_spawn_thread(SysFrm *, uint64_t InstructionPointer)
{
Tasking::TCB *thread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)InstructionPointer);
Tasking::TCB *thread =
TaskManager->CreateThread(TaskManager->GetCurrentProcess(),
(Tasking::IP)InstructionPointer);
if (thread)
return (int)thread->ID;
return SYSCALL_ERROR;
}
static int sys_get_thread_list_of_process(SyscallsFrame *Frame)
static int sys_get_thread_list_of_process(SysFrm *)
{
fixme("sys_get_thread_list_of_process: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_get_current_process(SyscallsFrame *Frame)
static int sys_get_current_process(SysFrm *)
{
fixme("sys_get_current_process: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_get_current_thread(SyscallsFrame *Frame)
static int sys_get_current_thread(SysFrm *)
{
fixme("sys_get_current_thread: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_get_current_process_id(SyscallsFrame *Frame)
static int sys_get_current_process_id(SysFrm *)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
return (int)TaskManager->GetCurrentProcess()->ID;
}
static int sys_get_current_thread_id(SyscallsFrame *Frame)
static int sys_get_current_thread_id(SysFrm *)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
return (int)TaskManager->GetCurrentThread()->ID;
}
static int sys_get_process_by_pid(SyscallsFrame *Frame)
static int sys_get_process_by_pid(SysFrm *)
{
fixme("sys_get_process_by_pid: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_get_thread_by_tid(SyscallsFrame *Frame)
static int sys_get_thread_by_tid(SysFrm *)
{
fixme("sys_get_thread_by_tid: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_kill_process(SyscallsFrame *Frame)
static int sys_kill_process(SysFrm *)
{
fixme("sys_kill_process: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_kill_thread(SyscallsFrame *Frame)
static int sys_kill_thread(SysFrm *)
{
fixme("sys_kill_thread: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_sys_reserved_create_process(SyscallsFrame *Frame)
static int sys_sys_reserved_create_process(SysFrm *)
{
fixme("sys_sys_reserved_create_process: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static int sys_sys_reserved_create_thread(SyscallsFrame *Frame)
static int sys_sys_reserved_create_thread(SysFrm *)
{
fixme("sys_sys_reserved_create_thread: %#lx", Frame);
stub;
return SYSCALL_NOT_IMPLEMENTED;
}
static void *NativeSyscallsTable[_MaxSyscall] = {
[_Exit] = (void *)sys_exit,
[_Print] = (void *)sys_print,
[_RequestPages] = (void *)sys_request_pages,
[_FreePages] = (void *)sys_free_pages,
[_DetachAddress] = (void *)sys_detach_address,
[_MemoryMap] = (void *)sys_memory_map,
[_MemoryUnmap] = (void *)sys_memory_unmap,
[_KernelCTL] = (void *)sys_kernelctl,
[_FileOpen] = (void *)sys_file_open,
[_FileClose] = (void *)sys_file_close,
[_FileRead] = (void *)sys_file_read,
[_FileWrite] = (void *)sys_file_write,
[_FileSeek] = (void *)sys_file_seek,
[_FileStatus] = (void *)sys_file_status,
[_IPC] = (void *)sys_ipc,
[_Sleep] = (void *)sys_sleep,
[_Fork] = (void *)sys_fork,
[_Wait] = (void *)sys_wait,
[_Kill] = (void *)sys_kill,
[_Spawn] = (void *)sys_spawn,
[_SpawnThread] = (void *)sys_spawn_thread,
[_GetThreadListOfProcess] = (void *)sys_get_thread_list_of_process,
[_GetCurrentProcess] = (void *)sys_get_current_process,
[_GetCurrentThread] = (void *)sys_get_current_thread,
[_GetCurrentProcessID] = (void *)sys_get_current_process_id,
[_GetCurrentThreadID] = (void *)sys_get_current_thread_id,
[_GetProcessByPID] = (void *)sys_get_process_by_pid,
[_GetThreadByTID] = (void *)sys_get_thread_by_tid,
[_KillProcess] = (void *)sys_kill_process,
[_KillThread] = (void *)sys_kill_thread,
[_SysReservedCreateProcess] = (void *)sys_sys_reserved_create_process,
[_SysReservedCreateThread] = (void *)sys_sys_reserved_create_thread,
struct SyscallData
{
const char *Name;
void *Handler;
int TrustLevel;
};
uintptr_t HandleNativeSyscalls(SyscallsFrame *Frame)
static SyscallData NativeSyscallsTable[_MaxSyscall] = {
/**
*
* Basic syscalls
*
*/
[_Exit] = {
"Exit",
(void *)sys_exit,
TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel,
},
[_Print] = {
"Print",
(void *)sys_print,
TrustedByKernel | Trusted,
},
/**
*
* Memory syscalls
*
*/
[_RequestPages] = {
"RequestPages",
(void *)sys_request_pages,
TrustedByKernel | Trusted | Untrusted,
},
[_FreePages] = {
"FreePages",
(void *)sys_free_pages,
TrustedByKernel | Trusted | Untrusted,
},
[_DetachAddress] = {
"DetachAddress",
(void *)sys_detach_address,
TrustedByKernel | Trusted,
},
[_MemoryMap] = {
"MemoryMap",
(void *)sys_memory_map,
TrustedByKernel,
},
[_MemoryUnmap] = {
"MemoryUnmap",
(void *)sys_memory_unmap,
TrustedByKernel,
},
/**
*
* Kernel Control syscalls
*
*/
[_KernelCTL] = {
"KernelCTL",
(void *)sys_kernelctl,
TrustedByKernel | Trusted | Untrusted,
},
/**
*
* File syscalls
*
*/
[_FileOpen] = {
"FileOpen",
(void *)sys_file_open,
TrustedByKernel | Trusted | Untrusted,
},
[_FileClose] = {
"FileClose",
(void *)sys_file_close,
TrustedByKernel | Trusted | Untrusted,
},
[_FileRead] = {
"FileRead",
(void *)sys_file_read,
TrustedByKernel | Trusted | Untrusted,
},
[_FileWrite] = {
"FileWrite",
(void *)sys_file_write,
TrustedByKernel | Trusted | Untrusted,
},
[_FileSeek] = {
"FileSeek",
(void *)sys_file_seek,
TrustedByKernel | Trusted | Untrusted,
},
[_FileStatus] = {
"FileStatus",
(void *)sys_file_status,
TrustedByKernel | Trusted | Untrusted,
},
/**
*
* Process syscalls
*
*/
[_IPC] = {
"IPC",
(void *)sys_ipc,
TrustedByKernel | Trusted | Untrusted,
},
[_Sleep] = {
"Sleep",
(void *)sys_sleep,
TrustedByKernel | Trusted | Untrusted,
},
[_Fork] = {
"Fork",
(void *)sys_fork,
TrustedByKernel | Trusted | Untrusted,
},
[_Wait] = {
"Wait",
(void *)sys_wait,
0,
},
[_Kill] = {
"Kill",
(void *)sys_kill,
0,
},
[_Spawn] = {
"Spawn",
(void *)sys_spawn,
0,
},
[_SpawnThread] = {
"SpawnThread",
(void *)sys_spawn_thread,
0,
},
[_GetThreadListOfProcess] = {
"GetThreadListOfProcess",
(void *)sys_get_thread_list_of_process,
0,
},
[_GetCurrentProcess] = {
"GetCurrentProcess",
(void *)sys_get_current_process,
0,
},
[_GetCurrentThread] = {
"GetCurrentThread",
(void *)sys_get_current_thread,
0,
},
[_GetCurrentProcessID] = {
"GetCurrentProcessID",
(void *)sys_get_current_process_id,
TrustedByKernel | Trusted | Untrusted,
},
[_GetCurrentThreadID] = {
"GetCurrentThreadID",
(void *)sys_get_current_thread_id,
TrustedByKernel | Trusted | Untrusted,
},
[_GetProcessByPID] = {
"GetProcessByPID",
(void *)sys_get_process_by_pid,
0,
},
[_GetThreadByTID] = {
"GetThreadByTID",
(void *)sys_get_thread_by_tid,
0,
},
[_KillProcess] = {
"KillProcess",
(void *)sys_kill_process,
0,
},
[_KillThread] = {
"KillThread",
(void *)sys_kill_thread,
0,
},
[_SysReservedCreateProcess] = {
"SysReservedCreateProcess",
(void *)sys_sys_reserved_create_process,
0,
},
[_SysReservedCreateThread] = {
"SysReservedCreateThread",
(void *)sys_sys_reserved_create_thread,
0,
},
};
uintptr_t HandleNativeSyscalls(SysFrm *Frame)
{
#if defined(a64)
if (Frame->rax > sizeof(NativeSyscallsTable))
if (unlikely(Frame->rax > _MaxSyscall))
{
fixme("Syscall %ld not implemented", Frame->rax);
fixme("Syscall %ld not implemented.", Frame->rax);
return SYSCALL_NOT_IMPLEMENTED;
}
uintptr_t (*call)(uintptr_t, ...) = reinterpret_cast<uintptr_t (*)(uintptr_t, ...)>(NativeSyscallsTable[Frame->rax]);
if (!call)
SyscallData Syscall = NativeSyscallsTable[Frame->rax];
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
Syscall.Handler);
if (unlikely(!call))
{
error("Syscall %#lx failed.", Frame->rax);
return SYSCALL_INTERNAL_ERROR;
error("Syscall %#lx not implemented.", Frame->rax);
return SYSCALL_NOT_IMPLEMENTED;
}
debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
Frame->rax,
Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9);
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
Tasking::Security *Sec = TaskManager->GetSecurityManager();
if (unlikely(!Sec->IsTokenTrusted(token, Syscall.TrustLevel)))
{
warn("Thread %s(%d) tried to access a system call \"%s\" with insufficient trust level",
TaskManager->GetCurrentThread()->Name,
TaskManager->GetCurrentThread()->ID,
Syscall.Name);
uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9);
Frame->rax = ret;
return ret;
#ifdef DEBUG
int TknTl = Sec->GetTokenTrustLevel(token);
debug("token=%#lx, trust=%d%d%d%d",token,
TknTl & TrustedByKernel ? 1 : 0,
TknTl & Trusted ? 1 : 0,
TknTl & Untrusted ? 1 : 0,
TknTl & UnknownTrustLevel ? 1 : 0);
#endif
return SYSCALL_ACCESS_DENIED;
}
debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
Frame->rax, Syscall.Name,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
return call(Frame,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
#elif defined(a32)
if (Frame->eax > sizeof(NativeSyscallsTable))
{
fixme("Syscall %ld not implemented", Frame->eax);
return SYSCALL_NOT_IMPLEMENTED;
}
/* ... */
return SYSCALL_INTERNAL_ERROR;
return SYSCALL_NOT_IMPLEMENTED;
#elif defined(aa64)
return SYSCALL_INTERNAL_ERROR;
return SYSCALL_NOT_IMPLEMENTED;
#endif
}

View File

@ -21,12 +21,8 @@
#include "../kernel.h"
NewLock(SyscallsLock);
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
{
SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */
Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info;
Tasking::TaskInfo *Ttinfo = &TaskManager->GetCurrentThread()->Info;
uint64_t TempTimeCalc = TimeManager->GetCounter();

View File

@ -248,17 +248,24 @@ namespace Tasking
CPU::Pause();
}
void Task::Sleep(uint64_t Milliseconds)
void Task::Sleep(uint64_t Milliseconds, bool NoSwitch)
{
SmartLock(TaskingLock);
TCB *thread = this->GetCurrentThread();
PCB *process = this->GetCurrentProcess();
thread->Status = TaskStatus::Sleeping;
if (thread->Parent->Threads.size() == 1)
thread->Parent->Status = TaskStatus::Sleeping;
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds);
tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil);
TaskingLock.Unlock();
this->Schedule();
if (process->Threads.size() == 1)
process->Status = TaskStatus::Sleeping;
thread->Info.SleepUntil =
TimeManager->CalculateTarget(Milliseconds,
Time::Units::Milliseconds);
debug("Thread \"%s\"(%d) is going to sleep until %llu",
thread->Name, thread->ID, thread->Info.SleepUntil);
if (!NoSwitch)
this->Schedule();
}
void Task::SignalShutdown()
@ -410,6 +417,8 @@ namespace Tasking
{
Thread->Security.IsCritical = true;
Thread->Stack = new Memory::StackGuard(false, Parent->PageTable);
Thread->SyscallStack = __UINTPTR_MAX__;
Thread->TempStack = __UINTPTR_MAX__;
#if defined(a64)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::TrustedByKernel);
Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE);
@ -430,9 +439,11 @@ namespace Tasking
case TaskTrustLevel::User:
{
Thread->Stack = new Memory::StackGuard(true, Parent->PageTable);
Thread->SyscallStack = (uintptr_t)Thread->Memory->RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
Thread->TempStack = 0x0;
#if defined(a64)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted);
Thread->ShadowGSBase = (uint64_t)GetCurrentCPU();
Thread->ShadowGSBase = (uintptr_t)Thread;
Thread->GSBase = 0;
Thread->FSBase = 0;
Thread->Registers.cs = GDT_USER_CODE;
@ -742,7 +753,6 @@ namespace Tasking
Task::Task(const IP EntryPoint) : Interrupts::Handler(16) /* IRQ16 */
{
SmartLock(TaskingLock);
#if defined(a64)
// Map the IRQ16 to the first CPU.
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, CPU::x86::IRQ16 - CPU::x86::IRQ0, 1);
@ -750,7 +760,6 @@ namespace Tasking
#elif defined(aa64)
#endif
KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint));
TaskingLock.Unlock();
#if defined(a64)
TaskArchitecture Arch = TaskArchitecture::x64;
@ -765,7 +774,6 @@ namespace Tasking
TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector<AuxiliaryVector>(), Arch);
kthrd->Rename("Main Thread");
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
TaskingLock.Lock(__FUNCTION__);
bool MONITORSupported = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
@ -792,7 +800,6 @@ namespace Tasking
CPU::Interrupts(CPU::Enable);
}
TaskingLock.Unlock();
IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Kernel);
IdleProcess->ELFSymbolTable = KernelSymbolTable;
for (int i = 0; i < SMP::CPUCores; i++)

View File

@ -1076,6 +1076,7 @@ namespace Memory
~MemMgr();
private:
NewLock(MgrLock);
Bitmap PageBitmap;
PageTable *Table;
VirtualFileSystem::Node *Directory;

View File

@ -41,14 +41,8 @@ struct CPUArchData
struct CPUData
{
/** @brief Used by syscall handler */
uint8_t *SystemCallStack; /* gs+0x0 */
/** @brief Used by syscall handler */
uintptr_t TempStack; /* gs+0x8 */
/** @brief Used by CPU */
uintptr_t Stack; /* gs+0x10 */
uintptr_t Stack;
/** @brief CPU ID. */
int ID;

View File

@ -122,6 +122,12 @@ namespace Tasking
struct TCB
{
/** @brief Used by syscall handler */
uintptr_t SyscallStack; /* gs+0x0 */
/** @brief Used by syscall handler */
uintptr_t TempStack; /* gs+0x8 */
TID ID;
char Name[256];
struct PCB *Parent;
@ -132,12 +138,12 @@ namespace Tasking
TaskStatus Status;
#if defined(a64)
CPU::x64::TrapFrame Registers;
uint64_t ShadowGSBase, GSBase, FSBase;
uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(a32)
CPU::x32::TrapFrame Registers; // TODO
uint64_t ShadowGSBase, GSBase, FSBase;
uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(aa64)
uint64_t Registers; // TODO
uintptr_t Registers; // TODO
#endif
uintptr_t IPHistory[128];
TaskSecurity Security;
@ -244,7 +250,8 @@ namespace Tasking
Untrusted = 0b0010,
Trusted = 0b0100,
TrustedByKernel = 0b1000,
FullTrust = Trusted | TrustedByKernel
FullTrust = Trusted | TrustedByKernel,
AllFlags = 0b1111
};
class Security
@ -379,7 +386,7 @@ namespace Tasking
*
* @param Milliseconds Amount of milliseconds to sleep
*/
void Sleep(uint64_t Milliseconds);
void Sleep(uint64_t Milliseconds, bool NoSwitch = false);
PCB *CreateProcess(PCB *Parent,
const char *Name,

View File

@ -76,12 +76,12 @@ namespace std
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( <vector> )->Size: %lld", VectorSize);
#endif
if (VectorSize > 0)
{
VectorBuffer = new T[VectorSize];
for (size_t i = 0; i < VectorSize; i++)
VectorBuffer[i] = v.VectorBuffer[i];
}
if (!v.VectorBuffer || VectorSize <= 0)
return;
VectorBuffer = new T[VectorSize];
for (size_t i = 0; i < VectorSize; i++)
VectorBuffer[i] = v.VectorBuffer[i];
}
NIF ~vector()

View File

@ -8,15 +8,15 @@
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -49,47 +49,47 @@
enum MemoryMapFlags
{
MAP_PRESENT = 1 << 0,
MAP_WRITABLE = 1 << 1,
MAP_USER = 1 << 2,
MAP_PRESENT = 1 << 0,
MAP_WRITABLE = 1 << 1,
MAP_USER = 1 << 2,
};
enum KCtl
{
KCTL_NULL,
KCTL_NULL,
KCTL_GET_PID,
KCTL_GET_TID,
KCTL_GET_UID,
KCTL_GET_GID,
KCTL_GET_PID,
KCTL_GET_TID,
KCTL_GET_UID,
KCTL_GET_GID,
/**
* @brief Get the page size
*/
KCTL_GET_PAGE_SIZE,
/**
* @brief Get the page size
*/
KCTL_GET_PAGE_SIZE,
/**
* @brief Check whether the current thread is critical
*/
KCTL_IS_CRITICAL,
/**
* @brief Check whether the current thread is critical
*/
KCTL_IS_CRITICAL,
/**
* @brief Register an ELF library
* @fn int RegisterELFLib(char *Identifier, char *Path)
*/
KCTL_REGISTER_ELF_LIB,
/**
* @brief Register an ELF library
* @fn int RegisterELFLib(char *Identifier, char *Path)
*/
KCTL_REGISTER_ELF_LIB,
/**
* @brief Get an ELF library
* @fn uintptr_t GetELFLib(char *Identifier);
*/
KCTL_GET_ELF_LIB_MEMORY_IMAGE,
/**
* @brief Get an ELF library
* @fn uintptr_t GetELFLib(char *Identifier);
*/
KCTL_GET_ELF_LIB_MEMORY_IMAGE,
/**
* @brief Get the absolute path of a library file
* @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize)
*/
KCTL_GET_ABSOLUTE_PATH,
/**
* @brief Get the absolute path of a library file
* @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize)
*/
KCTL_GET_ABSOLUTE_PATH,
};
/**
@ -98,230 +98,230 @@ enum KCtl
*/
enum NativeSyscalls
{
/**
*
* Basic syscalls
*
*/
/**
*
* Basic syscalls
*
*/
/** @brief Exit the process.
* @fn int Exit(int Code)
* This syscall is used to exit the current process with the provided exit code.
*/
_Exit = 0,
/** @brief Exit the process.
* @fn int Exit(int Code)
* This syscall is used to exit the current process with the provided exit code.
*/
_Exit = 0,
/** @brief Print a message to the kernel console
* @fn int Print(char Char, int Index)
* This syscall is used to print a message to the kernel console.
*/
_Print,
/** @brief Print a message to the kernel console
* @fn int Print(char Char, int Index)
* This syscall is used to print a message to the kernel console.
*/
_Print,
/**
*
* Memory syscalls
*
*/
/**
*
* Memory syscalls
*
*/
/** @brief Request pages of memory
* @fn uintptr_t RequestPages(size_t Count)
* This syscall is used to request a specific number of pages of memory from the kernel.
*/
_RequestPages,
/** @brief Request pages of memory
* @fn uintptr_t RequestPages(size_t Count)
* This syscall is used to request a specific number of pages of memory from the kernel.
*/
_RequestPages,
/** @brief Free pages of memory
* @fn int FreePages(uintptr_t Address, size_t Count)
* This syscall is used to free a specific number of pages of memory that were previously requested.
*/
_FreePages,
/** @brief Free pages of memory
* @fn int FreePages(uintptr_t Address, size_t Count)
* This syscall is used to free a specific number of pages of memory that were previously requested.
*/
_FreePages,
/** @brief Detach memory address
* @fn int DetachAddress(uintptr_t Address)
* This syscall is used to detach a specific memory address from the current process.
*/
_DetachAddress,
/** @brief Detach memory address
* @fn int DetachAddress(uintptr_t Address)
* This syscall is used to detach a specific memory address from the current process.
*/
_DetachAddress,
/**
* @brief Map memory address
* @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
* This syscall is used to map a specific memory address to the current process.
*
* @param Size The size of the memory region to map. Not pages.
*/
_MemoryMap,
/**
* @brief Map memory address
* @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
* This syscall is used to map a specific memory address to the current process.
*
* @param Size The size of the memory region to map. Not pages.
*/
_MemoryMap,
/** @brief Unmap memory address
* @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size)
* This syscall is used to unmap a specific memory address from the current process.
*
* @param Size The size of the memory region to unmap. Not pages.
*/
_MemoryUnmap,
/** @brief Unmap memory address
* @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size)
* This syscall is used to unmap a specific memory address from the current process.
*
* @param Size The size of the memory region to unmap. Not pages.
*/
_MemoryUnmap,
/**
*
* Kernel Control syscalls
*
*/
/**
*
* Kernel Control syscalls
*
*/
/** @brief Kernel Control
* @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
* This syscall is used to control certain aspects of the kernel or get information about it.
*/
_KernelCTL,
/** @brief Kernel Control
* @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
* This syscall is used to control certain aspects of the kernel or get information about it.
*/
_KernelCTL,
/**
*
* File syscalls
*
*/
/**
*
* File syscalls
*
*/
/** @brief Open a file
* @fn void *FileOpen(const char *Path, uint64_t Flags)
* This syscall is used to open a file with the provided path and flags.
*/
_FileOpen,
/** @brief Open a file
* @fn void *FileOpen(const char *Path, uint64_t Flags)
* This syscall is used to open a file with the provided path and flags.
*/
_FileOpen,
/** @brief Close a file
* @fn int FileClose(void *KernelPrivate)
* This syscall is used to close a file that was previously opened.
*/
_FileClose,
/** @brief Close a file
* @fn int FileClose(void *KernelPrivate)
* This syscall is used to close a file that was previously opened.
*/
_FileClose,
/** @brief Read from a file
* @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to read a specific number of bytes from a file at a specific offset.
*/
_FileRead,
/** @brief Read from a file
* @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to read a specific number of bytes from a file at a specific offset.
*/
_FileRead,
/** @brief Write to a file
* @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to write a specific number of bytes to a file at a specific offset.
*/
_FileWrite,
/** @brief Write to a file
* @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to write a specific number of bytes to a file at a specific offset.
*/
_FileWrite,
/** @brief Seek in a file
* @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence)
* This syscall is used to change the current offset in a file.
*/
_FileSeek,
/** @brief Seek in a file
* @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence)
* This syscall is used to change the current offset in a file.
*/
_FileSeek,
/** @brief Get file status
* @fn
* This syscall is used to retrieve information about a file such as its size, permissions, etc.
*/
_FileStatus,
/** @brief Get file status
* @fn
* This syscall is used to retrieve information about a file such as its size, permissions, etc.
*/
_FileStatus,
/**
*
* Process syscalls
*
*/
/**
*
* Process syscalls
*
*/
/**
* @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc.
* @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
* This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc.
*/
_IPC,
/**
* @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc.
* @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
* This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc.
*/
_IPC,
/** @brief Sleep for a specific amount of time
* @fn int Sleep(uint64_t Milliseconds)
* This syscall is used to sleep the current thread for a specific amount of time.
*/
_Sleep,
/** @brief Sleep for a specific amount of time
* @fn int Sleep(uint64_t Milliseconds)
* This syscall is used to sleep the current thread for a specific amount of time.
*/
_Sleep,
/** @brief Fork the current process
* @fn int Fork()
* This syscall is used to create a new process that is a copy of the current process.
*/
_Fork,
/** @brief Fork the current process
* @fn int Fork()
* This syscall is used to create a new process that is a copy of the current process.
*/
_Fork,
/** @brief Wait for a process or a thread
* @fn
* This syscall is used to wait for a specific process or thread to terminate. It returns the exit code of the process or thread.
*/
_Wait,
/** @brief Wait for a process or a thread
* @fn
* This syscall is used to wait for a specific process or thread to terminate. It returns the exit code of the process or thread.
*/
_Wait,
/** @brief Kill a process or a thread
* @fn
* This syscall is used to send a termination signal to a specific process or thread
*/
_Kill,
/** @brief Kill a process or a thread
* @fn
* This syscall is used to send a termination signal to a specific process or thread
*/
_Kill,
/** @brief Spawn a new process
* @fn
* This syscall is used to create a new process with the provided path and arguments.
*/
_Spawn,
/** @brief Spawn a new process
* @fn
* This syscall is used to create a new process with the provided path and arguments.
*/
_Spawn,
/** @brief Spawn a new thread
* @fn int SpawnThread(uint64_t InstructionPointer)
* This syscall is used to create a new thread within the current process with the provided function and arguments.
*/
_SpawnThread,
/** @brief Spawn a new thread
* @fn int SpawnThread(uint64_t InstructionPointer)
* This syscall is used to create a new thread within the current process with the provided function and arguments.
*/
_SpawnThread,
/** @brief Get thread list of a process
* @fn
* This syscall is used to retrieve a list of all the threads within a specific process.
*/
_GetThreadListOfProcess,
/** @brief Get thread list of a process
* @fn
* This syscall is used to retrieve a list of all the threads within a specific process.
*/
_GetThreadListOfProcess,
/** @brief Get current process
* @fn
* This syscall is used to retrieve information about the current process.
*/
_GetCurrentProcess,
/** @brief Get current process
* @fn
* This syscall is used to retrieve information about the current process.
*/
_GetCurrentProcess,
/** @brief Get current thread
* @fn
* This syscall is used to retrieve information about the current thread.
*/
_GetCurrentThread,
/** @brief Get current thread
* @fn
* This syscall is used to retrieve information about the current thread.
*/
_GetCurrentThread,
/** @brief Get current process ID
* @fn int GetCurrentProcessID()
* This syscall is used to retrieve information about the current process.
*/
_GetCurrentProcessID,
/** @brief Get current process ID
* @fn int GetCurrentProcessID()
* This syscall is used to retrieve information about the current process.
*/
_GetCurrentProcessID,
/** @brief Get current thread ID
* @fn int GetCurrentThreadID()
* This syscall is used to retrieve information about the current thread.
*/
_GetCurrentThreadID,
/** @brief Get current thread ID
* @fn int GetCurrentThreadID()
* This syscall is used to retrieve information about the current thread.
*/
_GetCurrentThreadID,
/** @brief Get process by PID
* @fn
* This syscall is used to retrieve information about a specific process by its PID.
*/
_GetProcessByPID,
/** @brief Get process by PID
* @fn
* This syscall is used to retrieve information about a specific process by its PID.
*/
_GetProcessByPID,
/** @brief Get thread by TID
* @fn
* This syscall is used to retrieve information about a specific thread by its TID.
*/
_GetThreadByTID,
/** @brief Get thread by TID
* @fn
* This syscall is used to retrieve information about a specific thread by its TID.
*/
_GetThreadByTID,
/** @brief Kill a process
* @fn
* This syscall is used to send a termination signal to a specific process.
*/
_KillProcess,
/** @brief Kill a process
* @fn
* This syscall is used to send a termination signal to a specific process.
*/
_KillProcess,
/** @brief Kill a thread
* @fn
* This syscall is used to send a termination signal to a specific thread.
*/
_KillThread,
/** @brief Kill a thread
* @fn
* This syscall is used to send a termination signal to a specific thread.
*/
_KillThread,
/** @brief Reserved syscall */
_SysReservedCreateProcess,
/** @brief Reserved syscall */
_SysReservedCreateProcess,
/** @brief Reserved syscall */
_SysReservedCreateThread,
/** @brief Reserved syscall */
_SysReservedCreateThread,
/** @brief Not a real syscall */
_MaxSyscall
/** @brief Not a real syscall */
_MaxSyscall
};
/**
@ -330,122 +330,122 @@ enum NativeSyscalls
*/
enum SyscallsErrorCodes
{
/**
* @brief Access denied
* This error code is returned when the current thread does not have the required permissions to perform the requested operation.
*/
SYSCALL_ACCESS_DENIED = -0xDEADACC,
/**
* @brief Invalid argument
* This error code is returned when an invalid argument is passed to a syscall.
*/
SYSCALL_INVALID_ARGUMENT = -0xBADAEE,
/**
* @brief Invalid syscall
* This error code is returned when an invalid syscall number is passed to the syscall handler.
*/
SYSCALL_INVALID_SYSCALL = -0xBAD55CA,
/**
* @brief Internal error
* This error code is returned when an internal error occurs in the syscall handler.
*/
SYSCALL_INTERNAL_ERROR = -0xBADBAD5,
/**
* @brief Not implemented
* This error code is returned when a syscall is not implemented.
*/
SYSCALL_NOT_IMPLEMENTED = -0xBAD5EED,
/**
* @brief Generic error
* This error code is returned when a syscall fails for an unknown reason.
*/
SYSCALL_ERROR = -1,
/**
* @brief Success
* This error code is returned when a syscall succeeds.
*/
SYSCALL_OK = 0,
/**
* @brief Access denied
* This error code is returned when the current thread does not have the required permissions to perform the requested operation.
*/
SYSCALL_ACCESS_DENIED = -0xDEADACC,
/**
* @brief Invalid argument
* This error code is returned when an invalid argument is passed to a syscall.
*/
SYSCALL_INVALID_ARGUMENT = -0xBADAEE,
/**
* @brief Invalid syscall
* This error code is returned when an invalid syscall number is passed to the syscall handler.
*/
SYSCALL_INVALID_SYSCALL = -0xBAD55CA,
/**
* @brief Internal error
* This error code is returned when an internal error occurs in the syscall handler.
*/
SYSCALL_INTERNAL_ERROR = -0xBADBAD5,
/**
* @brief Not implemented
* This error code is returned when a syscall is not implemented.
*/
SYSCALL_NOT_IMPLEMENTED = -0xBAD5EED,
/**
* @brief Generic error
* This error code is returned when a syscall fails for an unknown reason.
*/
SYSCALL_ERROR = -1,
/**
* @brief Success
* This error code is returned when a syscall succeeds.
*/
SYSCALL_OK = 0,
};
static inline bool IsSyscallError(long ret)
{
return ret < 0;
return ret < 0;
}
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__