From 85c0de688d33db885fa6a599e4b0c6a3234f225f Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 11 Jun 2023 01:36:39 +0300 Subject: [PATCH] Fix sleep syscall --- Architecture/amd64/SystemCalls.cpp | 103 ++--- Core/Crash/Screens/Details.cpp | 1 - Core/InterruptsManager.cpp | 2 - Core/Memory/MemoryManager.cpp | 7 + Core/StackCheck.cpp | 18 +- KernelThread.cpp | 19 +- SystemCalls/Native.cpp | 663 +++++++++++++++++------------ SystemCalls/Syscalls.cpp | 4 - Tasking/Task.cpp | 33 +- include/memory.hpp | 1 + include/smp.hpp | 8 +- include/task.hpp | 17 +- include_std/std/vector.hpp | 12 +- syscalls.h | 614 +++++++++++++------------- 14 files changed, 829 insertions(+), 673 deletions(-) diff --git a/Architecture/amd64/SystemCalls.cpp b/Architecture/amd64/SystemCalls.cpp index 5c1833c..1014d93 100644 --- a/Architecture/amd64/SystemCalls.cpp +++ b/Architecture/amd64/SystemCalls.cpp @@ -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)); } diff --git a/Core/Crash/Screens/Details.cpp b/Core/Crash/Screens/Details.cpp index 464c2bd..97c2803 100644 --- a/Core/Crash/Screens/Details.cpp +++ b/Core/Crash/Screens/Details.cpp @@ -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); diff --git a/Core/InterruptsManager.cpp b/Core/InterruptsManager.cpp index 9fae563..b679a89 100644 --- a/Core/InterruptsManager.cpp +++ b/Core/InterruptsManager.cpp @@ -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) { diff --git a/Core/Memory/MemoryManager.cpp b/Core/Memory/MemoryManager.cpp index c0da0b8..bae4f26 100644 --- a/Core/Memory/MemoryManager.cpp +++ b/Core/Memory/MemoryManager.cpp @@ -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); diff --git a/Core/StackCheck.cpp b/Core/StackCheck.cpp index a08ba12..ee73d99 100644 --- a/Core/StackCheck.cpp +++ b/Core/StackCheck.cpp @@ -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(); } diff --git a/KernelThread.cpp b/KernelThread.cpp index 66084c5..79c30ce 100644 --- a/KernelThread.cpp +++ b/KernelThread.cpp @@ -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); } diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 4920f27..f60ec1e 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -16,105 +16,75 @@ */ #include + #include #include #include #include - #include #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(), - Thread->Info.Architecture, - Thread->Info.Compatibility, - true); + Tasking::TCB *NewThread = + TaskManager->CreateThread(NewProcess, + 0, + nullptr, + nullptr, + std::vector(), + 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(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 } diff --git a/SystemCalls/Syscalls.cpp b/SystemCalls/Syscalls.cpp index c27eea3..4901d81 100644 --- a/SystemCalls/Syscalls.cpp +++ b/SystemCalls/Syscalls.cpp @@ -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(); diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 27a1eee..17395d3 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -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(), 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++) diff --git a/include/memory.hpp b/include/memory.hpp index e4de1b0..4e5d00b 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -1076,6 +1076,7 @@ namespace Memory ~MemMgr(); private: + NewLock(MgrLock); Bitmap PageBitmap; PageTable *Table; VirtualFileSystem::Node *Directory; diff --git a/include/smp.hpp b/include/smp.hpp index f58d422..d346784 100644 --- a/include/smp.hpp +++ b/include/smp.hpp @@ -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; diff --git a/include/task.hpp b/include/task.hpp index 5fe36c4..6678060 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -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, diff --git a/include_std/std/vector.hpp b/include_std/std/vector.hpp index cc9f7e2..43e76fc 100644 --- a/include_std/std/vector.hpp +++ b/include_std/std/vector.hpp @@ -76,12 +76,12 @@ namespace std #ifdef DEBUG_MEM_ALLOCATION debug("VECTOR INIT: 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() diff --git a/syscalls.h b/syscalls.h index 179372f..d011183 100644 --- a/syscalls.h +++ b/syscalls.h @@ -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__