mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Fix sleep syscall
This commit is contained in:
parent
f552b8f6f0
commit
85c0de688d
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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++)
|
||||
|
@ -1076,6 +1076,7 @@ namespace Memory
|
||||
~MemMgr();
|
||||
|
||||
private:
|
||||
NewLock(MgrLock);
|
||||
Bitmap PageBitmap;
|
||||
PageTable *Table;
|
||||
VirtualFileSystem::Node *Directory;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
614
syscalls.h
614
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__
|
||||
|
Loading…
x
Reference in New Issue
Block a user