mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-30 00:07:59 +00:00
Stability fixes (i hope); attempt to implement argc, argv, envp, auxv; Syscalls
This commit is contained in:
parent
40b1da9dd1
commit
77081b4e1e
@ -7,7 +7,7 @@ extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandl
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint64_t SystemCallsHandler(SyscallsRegs *regs);
|
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
|
||||||
|
|
||||||
void InitializeSystemCalls()
|
void InitializeSystemCalls()
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
using namespace CPU::x64;
|
using namespace CPU::x64;
|
||||||
|
|
||||||
// "Core/SystemCalls.cpp"
|
// "Core/SystemCalls.cpp"
|
||||||
extern "C" uint64_t SystemCallsHandler(SyscallsRegs *regs);
|
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
|
||||||
|
|
||||||
extern "C" void SystemCallHandlerStub();
|
extern "C" void SystemCallHandlerStub();
|
||||||
|
|
||||||
|
@ -30,7 +30,9 @@ namespace APIC
|
|||||||
|
|
||||||
uint32_t APIC::Read(uint32_t Register)
|
uint32_t APIC::Read(uint32_t Register)
|
||||||
{
|
{
|
||||||
if (Register != APIC_ICRLO && Register != APIC_ICRHI)
|
if (Register != APIC_ICRLO &&
|
||||||
|
Register != APIC_ICRHI &&
|
||||||
|
Register != APIC_ID)
|
||||||
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
|
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
|
||||||
if (x2APICSupported)
|
if (x2APICSupported)
|
||||||
{
|
{
|
||||||
|
@ -2,15 +2,12 @@
|
|||||||
|
|
||||||
#include <interrupts.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
#include <assert.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
#if defined(__amd64__)
|
#include "../acpi.hpp"
|
||||||
#include "../Architecture/amd64/acpi.hpp"
|
#include "apic.hpp"
|
||||||
#include "../Architecture/amd64/cpu/apic.hpp"
|
|
||||||
#elif defined(__i386__)
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" uint64_t _trampoline_start, _trampoline_end;
|
extern "C" uint64_t _trampoline_start, _trampoline_end;
|
||||||
|
|
||||||
@ -31,7 +28,24 @@ volatile bool CPUEnabled = false;
|
|||||||
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
|
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
|
||||||
|
|
||||||
CPUData *GetCPU(long id) { return &CPUs[id]; }
|
CPUData *GetCPU(long id) { return &CPUs[id]; }
|
||||||
CPUData *GetCurrentCPU() { return (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); }
|
CPUData *GetCurrentCPU()
|
||||||
|
{
|
||||||
|
CPUData *data = (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
|
||||||
|
|
||||||
|
if (data == nullptr && Interrupts::apic[0])
|
||||||
|
data = &CPUs[((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24];
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
return nullptr; // The caller should handle this.
|
||||||
|
|
||||||
|
if (!data->IsActive)
|
||||||
|
{
|
||||||
|
error("CPU %d is not active!", data->ID);
|
||||||
|
return &CPUs[0];
|
||||||
|
}
|
||||||
|
assert(data->Checksum == CPU_DATA_CHECKSUM); // This should never happen.
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void StartCPU()
|
extern "C" void StartCPU()
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
using namespace CPU::x32;
|
using namespace CPU::x32;
|
||||||
|
|
||||||
extern "C" uint32_t SystemCallsHandler(SyscallsRegs *regs);
|
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
|
||||||
|
|
||||||
void InitializeSystemCalls()
|
void InitializeSystemCalls()
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <interrupts.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
#include <assert.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -16,18 +17,12 @@ CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
|
|||||||
CPUData *GetCurrentCPU()
|
CPUData *GetCurrentCPU()
|
||||||
{
|
{
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
|
if (!(&CPUs[ret])->IsActive)
|
||||||
if (!CPUs[ret].IsActive)
|
|
||||||
{
|
{
|
||||||
error("CPU %d is not active!", ret);
|
error("CPU %d is not active!", ret);
|
||||||
return &CPUs[0];
|
return &CPUs[0];
|
||||||
}
|
}
|
||||||
|
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
|
||||||
if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM)
|
|
||||||
{
|
|
||||||
error("CPU %d data is corrupted!", ret);
|
|
||||||
return &CPUs[0];
|
|
||||||
}
|
|
||||||
return &CPUs[ret];
|
return &CPUs[ret];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "crashhandler.hpp"
|
#include "../crashhandler.hpp"
|
||||||
|
#include "chfcts.hpp"
|
||||||
|
|
||||||
#include <display.hpp>
|
#include <display.hpp>
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
@ -7,87 +8,15 @@
|
|||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
#include "../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../../kernel.h"
|
||||||
|
|
||||||
#if defined(__amd64__)
|
|
||||||
void DivideByZeroExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void DebugExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void NonMaskableInterruptExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void BreakpointExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void OverflowExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void BoundRangeExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void InvalidOpcodeExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void DeviceNotAvailableExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void DoubleFaultExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void CoprocessorSegmentOverrunExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void InvalidTSSExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void SegmentNotPresentExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void StackFaultExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void GeneralProtectionExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void PageFaultExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void x87FloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void AlignmentCheckExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void MachineCheckExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void SIMDFloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void VirtualizationExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void SecurityExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void UnknownExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
void UserModeExceptionHandler(CPU::x64::TrapFrame *Frame);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace CrashHandler
|
namespace CrashHandler
|
||||||
{
|
{
|
||||||
struct StackFrame
|
|
||||||
{
|
|
||||||
struct StackFrame *rbp;
|
|
||||||
uint64_t rip;
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void TraceFrames(CPU::x64::TrapFrame *Frame, int Count)
|
|
||||||
{
|
|
||||||
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
|
|
||||||
debug("Stack tracing...");
|
|
||||||
EHPrint("\e7981FC\nStack Trace:\n");
|
|
||||||
if (!frames || !frames->rip || !frames->rbp)
|
|
||||||
{
|
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
|
||||||
EHPrint("\e7925CC-");
|
|
||||||
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
|
||||||
EHPrint("\e7981FC <- Exception");
|
|
||||||
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
|
||||||
EHPrint("\e7925CC-");
|
|
||||||
if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
|
|
||||||
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
|
||||||
else
|
|
||||||
EHPrint("Outside Kernel");
|
|
||||||
EHPrint("\e7981FC <- Exception");
|
|
||||||
for (int frame = 0; frame < Count; ++frame)
|
|
||||||
{
|
|
||||||
if (!frames->rip)
|
|
||||||
break;
|
|
||||||
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
|
||||||
EHPrint("\e7925CC-");
|
|
||||||
if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
|
|
||||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
|
|
||||||
else
|
|
||||||
EHPrint("\eFF4CA9Outside Kernel");
|
|
||||||
|
|
||||||
if (!Memory::Virtual().Check(frames->rbp))
|
|
||||||
return;
|
|
||||||
frames = frames->rbp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void printfWrapper(char c, void *unused)
|
__attribute__((no_stack_protector)) void printfWrapper(char c, void *unused)
|
||||||
{
|
{
|
||||||
Display->Print(c, 255, true);
|
Display->Print(c, 255, true);
|
||||||
@ -104,26 +33,44 @@ namespace CrashHandler
|
|||||||
|
|
||||||
__attribute__((no_stack_protector)) void Handle(void *Data)
|
__attribute__((no_stack_protector)) void Handle(void *Data)
|
||||||
{
|
{
|
||||||
|
CPU::Interrupts(CPU::Disable);
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
|
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
||||||
error("Exception: %#llx", Frame->InterruptNumber);
|
error("Exception: %#llx", Frame->InterruptNumber);
|
||||||
|
|
||||||
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
|
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
|
||||||
{
|
{
|
||||||
debug("Exception in kernel mode");
|
debug("Exception in kernel mode");
|
||||||
CPU::Interrupts(CPU::Disable);
|
|
||||||
Display->CreateBuffer(0, 0, 255);
|
Display->CreateBuffer(0, 0, 255);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("Exception in user mode");
|
debug("Exception in user mode");
|
||||||
if (!GetCurrentCPU()->CurrentThread->Security.IsCritical)
|
CPUData *data = GetCurrentCPU();
|
||||||
|
if (!data)
|
||||||
{
|
{
|
||||||
UserModeExceptionHandler(Frame);
|
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
|
||||||
return;
|
error("Cannot get CPU data! This results in a kernel crash!");
|
||||||
|
error("This should never happen!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EHPrint("\eFF0000Init process crashed!");
|
{
|
||||||
|
debug("CPU %ld data is valid", data->ID);
|
||||||
|
if (data->CurrentThread)
|
||||||
|
{
|
||||||
|
debug("Current thread is valid %#lx", data->CurrentThread);
|
||||||
|
if (!data->CurrentThread->Security.IsCritical)
|
||||||
|
{
|
||||||
|
debug("Current thread is not critical");
|
||||||
|
UserModeExceptionHandler(Frame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EHPrint("\eFF0000Init process crashed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("Reading control registers...");
|
debug("Reading control registers...");
|
||||||
@ -267,8 +214,39 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", GetCurrentCPU()->ID);
|
CPUData *cpudata = GetCurrentCPU();
|
||||||
EHPrint("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
|
||||||
|
if (cpudata == nullptr)
|
||||||
|
{
|
||||||
|
EHPrint("\eFFA500Invalid CPU data!\n");
|
||||||
|
for (long i = 0; i < MAX_CPU; i++)
|
||||||
|
{
|
||||||
|
cpudata = GetCPU(i);
|
||||||
|
if (cpudata != nullptr)
|
||||||
|
break;
|
||||||
|
if (i == MAX_CPU - 1)
|
||||||
|
{
|
||||||
|
EHPrint("\eFF0000No CPU data found!\n");
|
||||||
|
cpudata = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug("CPU ptr %#lx", cpudata);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpudata != nullptr)
|
||||||
|
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", cpudata->ID);
|
||||||
|
|
||||||
|
if (TaskManager && cpudata != nullptr)
|
||||||
|
{
|
||||||
|
EHPrint("\e7981FCCurrent Process: %s(%ld)\n",
|
||||||
|
cpudata->CurrentProcess->Name,
|
||||||
|
cpudata->CurrentProcess->ID);
|
||||||
|
EHPrint("\e7981FCCurrent Thread: %s(%ld)\n",
|
||||||
|
cpudata->CurrentThread->Name,
|
||||||
|
cpudata->CurrentThread->ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
||||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||||
Frame->ss, Frame->cs, Frame->ds);
|
Frame->ss, Frame->cs, Frame->ds);
|
||||||
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
||||||
@ -358,7 +336,7 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__amd64__) || defined(__i386__)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
static const char *PagefaultDescriptions[] = {
|
static const char *PagefaultDescriptions[8] = {
|
||||||
"Supervisory process tried to read a non-present page entry\n",
|
"Supervisory process tried to read a non-present page entry\n",
|
||||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||||
"Supervisory process tried to write to a non-present page entry\n",
|
"Supervisory process tried to write to a non-present page entry\n",
|
||||||
@ -370,70 +348,41 @@ static const char *PagefaultDescriptions[] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
#define staticbuffer(name) char name[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
__attribute__((no_stack_protector)) void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void DivideByZeroExceptionHandler(CPU::x64::TrapFrame *Frame)
|
|
||||||
{
|
{
|
||||||
fixme("Divide by zero exception\n");
|
fixme("Divide by zero exception\n");
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void DebugExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void DebugExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void NonMaskableInterruptExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("NMI exception"); }
|
__attribute__((no_stack_protector)) void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); }
|
||||||
__attribute__((no_stack_protector)) void BreakpointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Breakpoint exception"); }
|
__attribute__((no_stack_protector)) void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); }
|
||||||
__attribute__((no_stack_protector)) void OverflowExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Overflow exception"); }
|
__attribute__((no_stack_protector)) void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); }
|
||||||
__attribute__((no_stack_protector)) void BoundRangeExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Bound range exception"); }
|
__attribute__((no_stack_protector)) void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); }
|
||||||
__attribute__((no_stack_protector)) void InvalidOpcodeExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void DeviceNotAvailableExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Device not available exception"); }
|
__attribute__((no_stack_protector)) void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); }
|
||||||
__attribute__((no_stack_protector)) void DoubleFaultExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Double fault exception"); }
|
__attribute__((no_stack_protector)) void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); }
|
||||||
__attribute__((no_stack_protector)) void CoprocessorSegmentOverrunExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
|
__attribute__((no_stack_protector)) void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
|
||||||
__attribute__((no_stack_protector)) void InvalidTSSExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Invalid TSS exception"); }
|
__attribute__((no_stack_protector)) void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); }
|
||||||
__attribute__((no_stack_protector)) void SegmentNotPresentExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Segment not present exception"); }
|
__attribute__((no_stack_protector)) void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); }
|
||||||
__attribute__((no_stack_protector)) void StackFaultExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
staticbuffer(descbuf);
|
|
||||||
staticbuffer(desc_ext);
|
|
||||||
staticbuffer(desc_table);
|
|
||||||
staticbuffer(desc_idx);
|
|
||||||
staticbuffer(desc_tmp);
|
|
||||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||||
switch (SelCode.Table)
|
|
||||||
{
|
|
||||||
case 0b00:
|
|
||||||
memcpy(desc_tmp, "GDT", 3);
|
|
||||||
break;
|
|
||||||
case 0b01:
|
|
||||||
memcpy(desc_tmp, "IDT", 3);
|
|
||||||
break;
|
|
||||||
case 0b10:
|
|
||||||
memcpy(desc_tmp, "LDT", 3);
|
|
||||||
break;
|
|
||||||
case 0b11:
|
|
||||||
memcpy(desc_tmp, "IDT", 3);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
memcpy(desc_tmp, "Unknown", 7);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug("external:%d table:%d idx:%#x", SelCode.External, SelCode.Table, SelCode.Idx);
|
|
||||||
sprintf_(descbuf, "Stack segment fault at address %#lx", Frame->rip);
|
|
||||||
CrashHandler::EHPrint(descbuf);
|
|
||||||
sprintf_(desc_ext, "External: %d", SelCode.External);
|
|
||||||
CrashHandler::EHPrint(desc_ext);
|
|
||||||
sprintf_(desc_table, "Table: %d (%s)", SelCode.Table, desc_tmp);
|
|
||||||
CrashHandler::EHPrint(desc_table);
|
|
||||||
sprintf_(desc_idx, "%s Index: %#x", desc_tmp, SelCode.Idx);
|
|
||||||
CrashHandler::EHPrint(desc_idx);
|
|
||||||
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("More info about the exception:\n");
|
CrashHandler::EHPrint("More info about the exception:\n");
|
||||||
|
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
|
||||||
|
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||||
|
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||||
|
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||||
|
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void GeneralProtectionExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
// staticbuffer(descbuf);
|
// staticbuffer(descbuf);
|
||||||
// staticbuffer(desc_ext);
|
// staticbuffer(desc_ext);
|
||||||
@ -466,7 +415,7 @@ __attribute__((no_stack_protector)) void GeneralProtectionExceptionHandler(CPU::
|
|||||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void PageFaultExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||||
CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
|
CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
|
||||||
@ -484,15 +433,15 @@ __attribute__((no_stack_protector)) void PageFaultExceptionHandler(CPU::x64::Tra
|
|||||||
else
|
else
|
||||||
CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
|
CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||||
}
|
}
|
||||||
__attribute__((no_stack_protector)) void x87FloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("x87 floating point exception"); }
|
__attribute__((no_stack_protector)) void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("x87 floating point exception"); }
|
||||||
__attribute__((no_stack_protector)) void AlignmentCheckExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Alignment check exception"); }
|
__attribute__((no_stack_protector)) void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Alignment check exception"); }
|
||||||
__attribute__((no_stack_protector)) void MachineCheckExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Machine check exception"); }
|
__attribute__((no_stack_protector)) void MachineCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Machine check exception"); }
|
||||||
__attribute__((no_stack_protector)) void SIMDFloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("SIMD floating point exception"); }
|
__attribute__((no_stack_protector)) void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("SIMD floating point exception"); }
|
||||||
__attribute__((no_stack_protector)) void VirtualizationExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Virtualization exception"); }
|
__attribute__((no_stack_protector)) void VirtualizationExceptionHandler(CHArchTrapFrame *Frame) { fixme("Virtualization exception"); }
|
||||||
__attribute__((no_stack_protector)) void SecurityExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Security exception"); }
|
__attribute__((no_stack_protector)) void SecurityExceptionHandler(CHArchTrapFrame *Frame) { fixme("Security exception"); }
|
||||||
__attribute__((no_stack_protector)) void UnknownExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Unknown exception"); }
|
__attribute__((no_stack_protector)) void UnknownExceptionHandler(CHArchTrapFrame *Frame) { fixme("Unknown exception"); }
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void UserModeExceptionHandler(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No");
|
debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No");
|
||||||
@ -660,5 +609,9 @@ __attribute__((no_stack_protector)) void UserModeExceptionHandler(CPU::x64::Trap
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
error("End of report.");
|
||||||
|
CPU::Interrupts(CPU::Enable);
|
||||||
|
debug("Interrupts enabled back.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
65
Core/Crash/SFrame.cpp
Normal file
65
Core/Crash/SFrame.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "../crashhandler.hpp"
|
||||||
|
#include "chfcts.hpp"
|
||||||
|
|
||||||
|
#include <display.hpp>
|
||||||
|
#include <printf.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <smp.hpp>
|
||||||
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
#if defined(__amd64__)
|
||||||
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
|
||||||
|
namespace CrashHandler
|
||||||
|
{
|
||||||
|
struct StackFrame
|
||||||
|
{
|
||||||
|
struct StackFrame *rbp;
|
||||||
|
uint64_t rip;
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void TraceFrames(CHArchTrapFrame *Frame, int Count)
|
||||||
|
{
|
||||||
|
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
|
||||||
|
debug("Stack tracing...");
|
||||||
|
EHPrint("\e7981FC\nStack Trace:\n");
|
||||||
|
if (!frames || !frames->rip || !frames->rbp)
|
||||||
|
{
|
||||||
|
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
||||||
|
EHPrint("\e7925CC-");
|
||||||
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
||||||
|
EHPrint("\e7981FC <- Exception");
|
||||||
|
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
||||||
|
EHPrint("\e7925CC-");
|
||||||
|
if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
|
||||||
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
||||||
|
else
|
||||||
|
EHPrint("Outside Kernel");
|
||||||
|
EHPrint("\e7981FC <- Exception");
|
||||||
|
for (int frame = 0; frame < Count; ++frame)
|
||||||
|
{
|
||||||
|
if (!frames->rip)
|
||||||
|
break;
|
||||||
|
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
||||||
|
EHPrint("\e7925CC-");
|
||||||
|
if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
|
||||||
|
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
|
||||||
|
else
|
||||||
|
EHPrint("\eFF4CA9Outside Kernel");
|
||||||
|
|
||||||
|
if (!Memory::Virtual().Check(frames->rbp))
|
||||||
|
return;
|
||||||
|
frames = frames->rbp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
Core/Crash/UserHandler.cpp
Normal file
17
Core/Crash/UserHandler.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "../crashhandler.hpp"
|
||||||
|
#include "chfcts.hpp"
|
||||||
|
|
||||||
|
#include <display.hpp>
|
||||||
|
#include <printf.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <smp.hpp>
|
||||||
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
#if defined(__amd64__)
|
||||||
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
|
44
Core/Crash/chfcts.hpp
Normal file
44
Core/Crash/chfcts.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
|
||||||
|
#define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
#if defined(__amd64__)
|
||||||
|
typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
typedef struct CPU::x86::TrapFrame CHArchTrapFrame;
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace CrashHandler
|
||||||
|
{
|
||||||
|
void TraceFrames(CHArchTrapFrame *Frame, int Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void DebugExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void BreakpointExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void OverflowExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void BoundRangeExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void StackFaultExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void PageFaultExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void MachineCheckExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void VirtualizationExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void SecurityExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void UnknownExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
void UserModeExceptionHandler(CHArchTrapFrame *Frame);
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
|
@ -52,7 +52,7 @@ namespace Interrupts
|
|||||||
CoreData->Stack = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
CoreData->Stack = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
||||||
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
|
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
|
||||||
{
|
{
|
||||||
KPrint("CPU %d data it's corrupted!", Core);
|
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
||||||
|
@ -11,7 +11,7 @@ extern "C" void DeadLockHandler(LockClass *Lock)
|
|||||||
{
|
{
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
CPUData *CoreData = GetCurrentCPU();
|
||||||
long CCore = 0xdead;
|
long CCore = 0xdead;
|
||||||
if (CoreData)
|
if (CoreData != nullptr)
|
||||||
CCore = CoreData->ID;
|
CCore = CoreData->ID;
|
||||||
warn("Potential deadlock in lock '%s' held by '%s' (%ld) [%#lx-%ld] [%ld->%ld]",
|
warn("Potential deadlock in lock '%s' held by '%s' (%ld) [%#lx-%ld] [%ld->%ld]",
|
||||||
Lock->GetLockData()->AttemptingToGet,
|
Lock->GetLockData()->AttemptingToGet,
|
||||||
@ -35,7 +35,7 @@ int LockClass::Lock(const char *FunctionName)
|
|||||||
LockData.CurrentHolder = FunctionName;
|
LockData.CurrentHolder = FunctionName;
|
||||||
LockData.Count++;
|
LockData.Count++;
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
CPUData *CoreData = GetCurrentCPU();
|
||||||
if (CoreData)
|
if (CoreData != nullptr)
|
||||||
LockData.Core = CoreData->ID;
|
LockData.Core = CoreData->ID;
|
||||||
CPU::MemBar::Barrier();
|
CPU::MemBar::Barrier();
|
||||||
|
|
||||||
|
@ -265,9 +265,11 @@ namespace Memory
|
|||||||
|
|
||||||
trace("Reserving pages...");
|
trace("Reserving pages...");
|
||||||
this->ReservePages(0, MemorySize / PAGE_SIZE + 1);
|
this->ReservePages(0, MemorySize / PAGE_SIZE + 1);
|
||||||
|
trace("Unreserving usable pages...");
|
||||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||||
if (Info->Memory.Entry[i].Type == Usable)
|
if (Info->Memory.Entry[i].Type == Usable)
|
||||||
this->UnreservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
|
this->UnreservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
|
||||||
|
trace("Locking bitmap pages...");
|
||||||
this->ReservePages(0, 0x100); // Reserve between 0 and 0x100000.
|
this->ReservePages(0, 0x100); // Reserve between 0 and 0x100000.
|
||||||
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
|
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace Video
|
|||||||
{
|
{
|
||||||
char Display::Print(char Char, int Index, bool WriteToUART)
|
char Display::Print(char Char, int Index, bool WriteToUART)
|
||||||
{
|
{
|
||||||
SmartLock(PrintLock);
|
// SmartLock(PrintLock);
|
||||||
|
|
||||||
if (this->ColorIteration)
|
if (this->ColorIteration)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <msexec.h>
|
#include <msexec.h>
|
||||||
#include <cwalk.h>
|
#include <cwalk.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
#include <abi.h>
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
#include "../Fex.hpp"
|
#include "../Fex.hpp"
|
||||||
@ -13,7 +14,7 @@ using namespace Tasking;
|
|||||||
|
|
||||||
namespace Execute
|
namespace Execute
|
||||||
{
|
{
|
||||||
SpawnData Spawn(char *Path, uint64_t Arg0, uint64_t Arg1)
|
SpawnData Spawn(char *Path, Vector<const char *> &argv, Vector<const char *> &envp)
|
||||||
{
|
{
|
||||||
SpawnData ret = {.Status = ExStatus::Unknown,
|
SpawnData ret = {.Status = ExStatus::Unknown,
|
||||||
.Process = nullptr,
|
.Process = nullptr,
|
||||||
@ -42,9 +43,11 @@ namespace Execute
|
|||||||
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
||||||
pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
|
||||||
|
Vector<AuxiliaryVector> auxv; // TODO!
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
(IP)FexHdr->Pointer,
|
(IP)FexHdr->Pointer,
|
||||||
Arg0, Arg1,
|
argv, envp, auxv,
|
||||||
(IPOffset)BaseImage,
|
(IPOffset)BaseImage,
|
||||||
TaskArchitecture::x64,
|
TaskArchitecture::x64,
|
||||||
TaskCompatibility::Native);
|
TaskCompatibility::Native);
|
||||||
@ -130,9 +133,20 @@ namespace Execute
|
|||||||
memcpy(dst, ((char *)BaseImage) + pheader->p_offset, pheader->p_filesz);
|
memcpy(dst, ((char *)BaseImage) + pheader->p_offset, pheader->p_filesz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)Offset}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry + (uint64_t)Offset}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)Path}}});
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
(IP)ELFHeader->e_entry,
|
(IP)ELFHeader->e_entry,
|
||||||
Arg0, Arg1,
|
argv, envp, auxv,
|
||||||
(IPOffset)Offset,
|
(IPOffset)Offset,
|
||||||
Arch,
|
Arch,
|
||||||
Comp);
|
Comp);
|
||||||
@ -154,9 +168,13 @@ namespace Execute
|
|||||||
ret.Status = ExStatus::InvalidFileEntryPoint;
|
ret.Status = ExStatus::InvalidFileEntryPoint;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
fixme("auxv");
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
(IP)EP,
|
(IP)EP,
|
||||||
Arg0, Arg1,
|
argv, envp, auxv,
|
||||||
(IPOffset)BaseImage,
|
(IPOffset)BaseImage,
|
||||||
Arch,
|
Arch,
|
||||||
Comp);
|
Comp);
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
"assert.h": "c",
|
"assert.h": "c",
|
||||||
"cwalk.h": "c",
|
"cwalk.h": "c",
|
||||||
"md5.h": "c",
|
"md5.h": "c",
|
||||||
"stdint.h": "c"
|
"stdint.h": "c",
|
||||||
|
"debug.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
13
KConfig.cpp
13
KConfig.cpp
@ -49,6 +49,12 @@ static struct cag_option ConfigOptions[] = {
|
|||||||
.value_name = "PATH",
|
.value_name = "PATH",
|
||||||
.description = "Path to init program"},
|
.description = "Path to init program"},
|
||||||
|
|
||||||
|
{.identifier = 'o',
|
||||||
|
.access_letters = NULL,
|
||||||
|
.access_name = "ioc",
|
||||||
|
.value_name = "BOOL",
|
||||||
|
.description = "Enable Interrupts On Crash. If enabled, the navigation keys will be enabled on crash."},
|
||||||
|
|
||||||
{.identifier = 'h',
|
{.identifier = 'h',
|
||||||
.access_letters = "h",
|
.access_letters = "h",
|
||||||
.access_name = "help",
|
.access_name = "help",
|
||||||
@ -335,6 +341,13 @@ ParseSuccess:
|
|||||||
KPrint("\eAAFFAAUsing %s as init program", value);
|
KPrint("\eAAFFAAUsing %s as init program", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'o':
|
||||||
|
{
|
||||||
|
value = cag_option_get_value(&context);
|
||||||
|
strcmp(value, "true") ? config.InterruptsOnCrash = false : config.InterruptsOnCrash = true;
|
||||||
|
KPrint("\eAAFFAAInterrupts on crash: %s", value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'h':
|
case 'h':
|
||||||
{
|
{
|
||||||
KPrint("\n---------------------------------------------------------------------------\nUsage: kernel.fsys [OPTION]...\nKernel configuration.");
|
KPrint("\n---------------------------------------------------------------------------\nUsage: kernel.fsys [OPTION]...\nKernel configuration.");
|
||||||
|
45
KThread.cpp
45
KThread.cpp
@ -47,49 +47,66 @@ void FetchDisks()
|
|||||||
|
|
||||||
void KernelMainThread()
|
void KernelMainThread()
|
||||||
{
|
{
|
||||||
|
Vector<const char *> argv;
|
||||||
|
Vector<const char *> envp;
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
|
||||||
Tasking::TCB *CurrentWorker = nullptr;
|
Tasking::TCB *CurrentWorker = nullptr;
|
||||||
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
||||||
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
|
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
|
||||||
TaskManager->GetCurrentThread()->SetPriority(1);
|
TaskManager->GetCurrentThread()->SetPriority(1);
|
||||||
|
|
||||||
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)StartFilesystem);
|
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)StartFilesystem, argv, envp, auxv);
|
||||||
CurrentWorker->Rename("Disk");
|
CurrentWorker->Rename("Disk");
|
||||||
CurrentWorker->SetPriority(100);
|
CurrentWorker->SetPriority(100);
|
||||||
TaskManager->WaitForThread(CurrentWorker);
|
TaskManager->WaitForThread(CurrentWorker);
|
||||||
|
|
||||||
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)LoadDrivers);
|
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)LoadDrivers, argv, envp, auxv);
|
||||||
CurrentWorker->Rename("Drivers");
|
CurrentWorker->Rename("Drivers");
|
||||||
CurrentWorker->SetPriority(100);
|
CurrentWorker->SetPriority(100);
|
||||||
TaskManager->WaitForThread(CurrentWorker);
|
TaskManager->WaitForThread(CurrentWorker);
|
||||||
|
|
||||||
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)FetchDisks);
|
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)FetchDisks, argv, envp, auxv);
|
||||||
CurrentWorker->Rename("Fetch Disks");
|
CurrentWorker->Rename("Fetch Disks");
|
||||||
CurrentWorker->SetPriority(100);
|
CurrentWorker->SetPriority(100);
|
||||||
TaskManager->WaitForThread(CurrentWorker);
|
TaskManager->WaitForThread(CurrentWorker);
|
||||||
|
|
||||||
KPrint("Waiting for userspace process to start...");
|
KPrint("Setting up userspace...");
|
||||||
|
|
||||||
Vector<char *> argv;
|
envp.clear();
|
||||||
int argc = 0;
|
envp.push_back("PATH=/system:/system/bin");
|
||||||
|
envp.push_back("TERM=tty");
|
||||||
|
envp.push_back("HOME=/");
|
||||||
|
envp.push_back("USER=root");
|
||||||
|
envp.push_back("SHELL=/system/bin/sh");
|
||||||
|
envp.push_back("PWD=/");
|
||||||
|
envp.push_back("LANG=en_US.UTF-8");
|
||||||
|
envp.push_back("TZ=UTC");
|
||||||
|
|
||||||
/* ... */
|
argv.clear();
|
||||||
argv.push_back((char *)"--start");
|
argv.push_back("--init");
|
||||||
/* ... */
|
argv.push_back("--critical");
|
||||||
|
|
||||||
argv.push_back(nullptr);
|
|
||||||
argc = argv.size() - 1;
|
|
||||||
|
|
||||||
// TODO: Untested!
|
// TODO: Untested!
|
||||||
Execute::SpawnData ret = Execute::Spawn(Config.InitPath, argc, (uint64_t)argv.data());
|
bool ien = CPU::Interrupts(CPU::Check);
|
||||||
|
CPU::Interrupts(CPU::Disable);
|
||||||
|
Execute::SpawnData ret = Execute::Spawn(Config.InitPath, argv, envp);
|
||||||
if (ret.Status != Execute::ExStatus::OK)
|
if (ret.Status != Execute::ExStatus::OK)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
|
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
|
||||||
CPU::Halt(true);
|
if (ien)
|
||||||
|
CPU::Interrupts(CPU::Enable);
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
ret.Thread->SetCritical(true);
|
ret.Thread->SetCritical(true);
|
||||||
|
if (ien)
|
||||||
|
CPU::Interrupts(CPU::Enable);
|
||||||
|
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
|
||||||
TaskManager->WaitForThread(ret.Thread);
|
TaskManager->WaitForThread(ret.Thread);
|
||||||
KPrint("\eE85230Userspace process exited with code %d", ret.Thread->GetExitCode());
|
KPrint("\eE85230Userspace process exited with code %d", ret.Thread->GetExitCode());
|
||||||
error("Userspace process exited with code %d (%#x)", ret.Thread->GetExitCode(), ret.Thread->GetExitCode());
|
error("Userspace process exited with code %d (%#x)", ret.Thread->GetExitCode(), ret.Thread->GetExitCode());
|
||||||
|
Exit:
|
||||||
|
KPrint("Well, that's it. I'm going to sleep now.");
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ KernelConfig Config;
|
|||||||
Time::Clock BootClock;
|
Time::Clock BootClock;
|
||||||
|
|
||||||
// For the Display class. Printing on first buffer as default.
|
// For the Display class. Printing on first buffer as default.
|
||||||
extern "C" void putchar(char c) { Display->Print(c, 0); }
|
EXTERNC void putchar(char c) { Display->Print(c, 0); }
|
||||||
|
|
||||||
EXTERNC void KPrint(const char *Format, ...)
|
EXTERNC void KPrint(const char *Format, ...)
|
||||||
{
|
{
|
||||||
|
2409
SystemCalls/Linux.cpp
Normal file
2409
SystemCalls/Linux.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
SystemCalls/Native.cpp
Normal file
46
SystemCalls/Native.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <syscalls.hpp>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "../syscalls.h"
|
||||||
|
#include "../kernel.h"
|
||||||
|
|
||||||
|
static uint64_t sys_exit(SyscallsFrame *Frame, uint64_t code)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sys_print(SyscallsFrame *Frame, char Char, int Index)
|
||||||
|
{
|
||||||
|
debug("%c", Char);
|
||||||
|
return Display->Print(Char, Index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *NativeSyscallsTable[] = {
|
||||||
|
[_exit] = (void *)sys_exit,
|
||||||
|
[_print] = (void *)sys_print,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t HandleNativeSyscalls(SyscallsFrame *Frame)
|
||||||
|
{
|
||||||
|
debug("rax: %#llx, rbx: %#llx, rcx: %#llx, rdx: %#llx, rsi: %#llx, rdi: %#llx, rbp: %#llx, r8: %#llx, r9: %#llx, r10: %#llx, r11: %#llx, r12: %#llx, r13: %#llx, r14: %#llx, r15: %#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi, Frame->rbp, Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13, Frame->r14, Frame->r15);
|
||||||
|
if (Frame->rax > sizeof(NativeSyscallsTable))
|
||||||
|
{
|
||||||
|
fixme("Syscall %lld not implemented", Frame->rax);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t (*call)(uint64_t, ...) = reinterpret_cast<uint64_t (*)(uint64_t, ...)>(NativeSyscallsTable[Frame->rax]);
|
||||||
|
if (!call)
|
||||||
|
{
|
||||||
|
error("Syscall %#llx failed.", Frame->rax);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
debug("%#lx %#lx %#lx %#lx %#lx %#lx", Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9);
|
||||||
|
uint64_t ret = call((uint64_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9);
|
||||||
|
Frame->rax = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
@ -2,14 +2,33 @@
|
|||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
extern "C" uint64_t SystemCallsHandler(SyscallsRegs *regs)
|
#include "../kernel.h"
|
||||||
|
|
||||||
|
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *Frame)
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
fixme("System call %ld", regs->rax);
|
switch (TaskManager->GetCurrentThread()->Info.Compatibility)
|
||||||
|
{
|
||||||
|
case Tasking::TaskCompatibility::Native:
|
||||||
|
return HandleNativeSyscalls(Frame);
|
||||||
|
case Tasking::TaskCompatibility::Linux:
|
||||||
|
return HandleLinuxSyscalls(Frame);
|
||||||
|
case Tasking::TaskCompatibility::Windows:
|
||||||
|
{
|
||||||
|
error("Windows compatibility not implemented yet.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error("Unknown compatibility mode! Killing thread...");
|
||||||
|
TaskManager->KillThread(TaskManager->GetCurrentThread(), -0xCA11);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
fixme("System call %lld", regs->eax);
|
fixme("System call %lld", regs->eax);
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
fixme("System call");
|
fixme("System call");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,10 @@ namespace InterProcessCommunication
|
|||||||
IPC::IPC()
|
IPC::IPC()
|
||||||
{
|
{
|
||||||
trace("Starting IPC Service...");
|
trace("Starting IPC Service...");
|
||||||
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)IPCServiceStub);
|
Vector<const char *> argv;
|
||||||
|
Vector<const char *> envp;
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)IPCServiceStub, argv, envp, auxv);
|
||||||
TaskManager->GetCurrentThread()->Rename("IPC Service");
|
TaskManager->GetCurrentThread()->Rename("IPC Service");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
141
Tasking/Task.cpp
141
Tasking/Task.cpp
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <lock.hpp>
|
#include <lock.hpp>
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
|
#include <dumper.hpp>
|
||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
@ -379,6 +380,50 @@ namespace Tasking
|
|||||||
|
|
||||||
Success:
|
Success:
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_SCHEDULER
|
||||||
|
static int sanity;
|
||||||
|
const char *Statuses[] = {
|
||||||
|
"FF0000", // Unknown
|
||||||
|
"AAFF00", // Ready
|
||||||
|
"00AA00", // Running
|
||||||
|
"FFAA00", // Sleeping
|
||||||
|
"FFAA00", // Waiting
|
||||||
|
"FF0088", // Stopped
|
||||||
|
"FF0000", // Terminated
|
||||||
|
};
|
||||||
|
const char *StatusesSign[] = {
|
||||||
|
"U", // Unknown
|
||||||
|
"R", // Ready
|
||||||
|
"r", // Running
|
||||||
|
"S", // Sleeping
|
||||||
|
"W", // Waiting
|
||||||
|
"s", // Stopped
|
||||||
|
"T", // Terminated
|
||||||
|
};
|
||||||
|
for (int i = 0; i < 200; i++)
|
||||||
|
for (int j = 0; j < 200; j++)
|
||||||
|
Display->SetPixel(i, j, 0x222222, 0);
|
||||||
|
uint32_t tmpX, tmpY;
|
||||||
|
Display->GetBufferCursor(0, &tmpX, &tmpY);
|
||||||
|
Display->SetBufferCursor(0, 0, 0);
|
||||||
|
foreach (auto var in ListProcess)
|
||||||
|
{
|
||||||
|
int statuu = var->Status;
|
||||||
|
printf_("\e%s-> \eAABBCC%s\eCCCCCC[%d] \e00AAAA%s\n",
|
||||||
|
Statuses[statuu], var->Name, statuu, StatusesSign[statuu]);
|
||||||
|
foreach (auto var2 in var->Threads)
|
||||||
|
{
|
||||||
|
int statui = var2->Status;
|
||||||
|
printf_(" \e%s-> \eAABBCC%s\eCCCCCC[%d] \e00AAAA%s\n\eAABBCC",
|
||||||
|
Statuses[statui], var2->Name, statui, StatusesSign[statui]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf_("%d", sanity++);
|
||||||
|
if (sanity > 1000)
|
||||||
|
sanity = 0;
|
||||||
|
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||||
|
Display->SetBuffer(0);
|
||||||
|
#endif
|
||||||
schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d",
|
schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d",
|
||||||
CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID,
|
CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID,
|
||||||
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID);
|
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID);
|
||||||
@ -546,8 +591,9 @@ namespace Tasking
|
|||||||
|
|
||||||
TCB *Task::CreateThread(PCB *Parent,
|
TCB *Task::CreateThread(PCB *Parent,
|
||||||
IP EntryPoint,
|
IP EntryPoint,
|
||||||
Arg Argument0,
|
Vector<const char *> &argv,
|
||||||
Arg Argument1,
|
Vector<const char *> &envp,
|
||||||
|
Vector<AuxiliaryVector> &auxv,
|
||||||
IPOffset Offset,
|
IPOffset Offset,
|
||||||
TaskArchitecture Architecture,
|
TaskArchitecture Architecture,
|
||||||
TaskCompatibility Compatibility)
|
TaskCompatibility Compatibility)
|
||||||
@ -570,8 +616,6 @@ namespace Tasking
|
|||||||
strcpy(Thread->Name, Parent->Name);
|
strcpy(Thread->Name, Parent->Name);
|
||||||
Thread->EntryPoint = EntryPoint;
|
Thread->EntryPoint = EntryPoint;
|
||||||
Thread->Offset = Offset;
|
Thread->Offset = Offset;
|
||||||
Thread->Argument0 = Argument0;
|
|
||||||
Thread->Argument1 = Argument1;
|
|
||||||
Thread->ExitCode = 0xdead;
|
Thread->ExitCode = 0xdead;
|
||||||
Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)));
|
Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)));
|
||||||
Thread->Status = TaskStatus::Ready;
|
Thread->Status = TaskStatus::Ready;
|
||||||
@ -579,8 +623,6 @@ namespace Tasking
|
|||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
|
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
|
||||||
Thread->Registers.rip = (EntryPoint + Offset);
|
Thread->Registers.rip = (EntryPoint + Offset);
|
||||||
Thread->Registers.rdi = Argument0;
|
|
||||||
Thread->Registers.rsi = Argument1;
|
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
@ -622,6 +664,80 @@ namespace Tasking
|
|||||||
Thread->Registers.rflags.IF = 1;
|
Thread->Registers.rflags.IF = 1;
|
||||||
Thread->Registers.rflags.ID = 1;
|
Thread->Registers.rflags.ID = 1;
|
||||||
Thread->Registers.rsp = ((uint64_t)Thread->Stack + STACK_SIZE);
|
Thread->Registers.rsp = ((uint64_t)Thread->Stack + STACK_SIZE);
|
||||||
|
|
||||||
|
// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9
|
||||||
|
// What is a "eightbyte"? unsigned long? 1 eightbyte = 8 bytes? 2 eightbyte each = 16 bytes?
|
||||||
|
uint64_t TmpStack = Thread->Registers.rsp;
|
||||||
|
uint64_t TmpStack2 = TmpStack;
|
||||||
|
uint64_t *TmpStackPtr = (uint64_t *)TmpStack;
|
||||||
|
|
||||||
|
// TODO: argc, argv, envp, auxv not tested and probably not working
|
||||||
|
foreach (auto var in envp)
|
||||||
|
{
|
||||||
|
TmpStack -= strlen(var) + 1;
|
||||||
|
strcpy((char *)TmpStack, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (auto var in argv)
|
||||||
|
{
|
||||||
|
TmpStack -= strlen(var) + 1;
|
||||||
|
strcpy((char *)TmpStack, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* align by 16 */
|
||||||
|
TmpStack = (uint64_t)((uint64_t)TmpStack - ((uint64_t)TmpStack & 0x0F));
|
||||||
|
|
||||||
|
/* TODO: more aligment here? */
|
||||||
|
|
||||||
|
/* auxv null */
|
||||||
|
TmpStack -= sizeof(uint64_t);
|
||||||
|
POKE(uint64_t, TmpStack) = (uint64_t)0;
|
||||||
|
/* This should be included too? */
|
||||||
|
TmpStack -= sizeof(uint64_t);
|
||||||
|
POKE(uint64_t, TmpStack) = (uint64_t)0;
|
||||||
|
|
||||||
|
/* auxv */
|
||||||
|
foreach (auto var in auxv)
|
||||||
|
{
|
||||||
|
if (var.archaux.a_type == AT_ENTRY)
|
||||||
|
Thread->Registers.rdi = var.archaux.a_un.a_val;
|
||||||
|
|
||||||
|
TmpStack -= sizeof(uint64_t) * 2;
|
||||||
|
POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_type;
|
||||||
|
TmpStack -= sizeof(uint64_t) * 2;
|
||||||
|
POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_un.a_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* empty */
|
||||||
|
TmpStack -= sizeof(uint64_t);
|
||||||
|
POKE(uint64_t, TmpStack) = 0;
|
||||||
|
|
||||||
|
/* envp pointers */
|
||||||
|
for (uint64_t i = 0; i < envp.size(); i++)
|
||||||
|
{
|
||||||
|
/* Not sure if this works */
|
||||||
|
TmpStack2 -= strlen(envp[i]) + 1;
|
||||||
|
TmpStackPtr[i] = TmpStack2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* empty */
|
||||||
|
TmpStack -= sizeof(uint64_t);
|
||||||
|
POKE(uint64_t, TmpStack) = 0;
|
||||||
|
|
||||||
|
/* argv pointers */
|
||||||
|
for (uint64_t i = 0; i < argv.size(); i++)
|
||||||
|
{
|
||||||
|
/* Not sure if this works */
|
||||||
|
TmpStack2 -= strlen(argv[i]) + 1;
|
||||||
|
TmpStackPtr[i] = TmpStack2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* argc */
|
||||||
|
TmpStack -= sizeof(uint64_t);
|
||||||
|
POKE(uint64_t, TmpStack) = argv.size() - 1;
|
||||||
|
|
||||||
|
Thread->Registers.rsp -= (uint64_t)Thread->Stack + STACK_SIZE - TmpStack;
|
||||||
|
|
||||||
/* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */
|
/* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */
|
||||||
|
|
||||||
Memory::Virtual uva = Memory::Virtual(Parent->PageTable);
|
Memory::Virtual uva = Memory::Virtual(Parent->PageTable);
|
||||||
@ -635,6 +751,9 @@ namespace Tasking
|
|||||||
}
|
}
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_SCHEDULER
|
||||||
|
DumpData(Thread->Name, Thread->Stack, STACK_SIZE);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -786,7 +905,10 @@ namespace Tasking
|
|||||||
TaskArchitecture Arch = TaskArchitecture::ARM64;
|
TaskArchitecture Arch = TaskArchitecture::ARM64;
|
||||||
#endif
|
#endif
|
||||||
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
|
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
|
||||||
TCB *kthrd = CreateThread(kproc, EntryPoint, 0, 0, 0, Arch);
|
Vector<const char *> argv;
|
||||||
|
Vector<const char *> envp;
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
TCB *kthrd = CreateThread(kproc, EntryPoint, argv, envp, auxv, 0, Arch);
|
||||||
kthrd->Rename("Main Thread");
|
kthrd->Rename("Main Thread");
|
||||||
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
|
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
|
||||||
TaskingLock.Lock(__FUNCTION__);
|
TaskingLock.Lock(__FUNCTION__);
|
||||||
@ -810,7 +932,10 @@ namespace Tasking
|
|||||||
IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Idle);
|
IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Idle);
|
||||||
for (int i = 0; i < SMP::CPUCores; i++)
|
for (int i = 0; i < SMP::CPUCores; i++)
|
||||||
{
|
{
|
||||||
IdleThread = CreateThread(IdleProcess, reinterpret_cast<uint64_t>(IdleProcessLoop));
|
Vector<const char *> argv;
|
||||||
|
Vector<const char *> envp;
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
IdleThread = CreateThread(IdleProcess, reinterpret_cast<uint64_t>(IdleProcessLoop), argv, envp, auxv);
|
||||||
char IdleName[16];
|
char IdleName[16];
|
||||||
sprintf_(IdleName, "Idle Thread %d", i);
|
sprintf_(IdleName, "Idle Thread %d", i);
|
||||||
IdleThread->Rename(IdleName);
|
IdleThread->Rename(IdleName);
|
||||||
|
72
include/abi.h
Normal file
72
include/abi.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef __FENNIX_KERNEL_ABI_H__
|
||||||
|
#define __FENNIX_KERNEL_ABI_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define AT_NULL 0
|
||||||
|
#define AT_IGNORE 1
|
||||||
|
#define AT_EXECFD 2
|
||||||
|
#define AT_PHDR 3
|
||||||
|
#define AT_PHENT 4
|
||||||
|
#define AT_PHNUM 5
|
||||||
|
#define AT_PAGESZ 6
|
||||||
|
#define AT_BASE 7
|
||||||
|
#define AT_FLAGS 8
|
||||||
|
#define AT_ENTRY 9
|
||||||
|
#define AT_NOTELF 10
|
||||||
|
#define AT_UID 11
|
||||||
|
#define AT_EUID 12
|
||||||
|
#define AT_GID 13
|
||||||
|
#define AT_EGID 14
|
||||||
|
#define AT_PLATFORM 15
|
||||||
|
#define AT_HWCAP 16
|
||||||
|
#define AT_CLKTCK 17
|
||||||
|
#define AT_SECURE 23
|
||||||
|
#define AT_BASE_PLATFORM 24
|
||||||
|
#define AT_RANDOM 25
|
||||||
|
#define AT_HWCAP2 26
|
||||||
|
#define AT_EXECFN 31
|
||||||
|
#define AT_SYSINFO 32
|
||||||
|
#define AT_SYSINFO_EHDR 33
|
||||||
|
#define AT_L1I_CACHESHAPE 34
|
||||||
|
#define AT_L1D_CACHESHAPE 35
|
||||||
|
#define AT_L2_CACHESHAPE 36
|
||||||
|
#define AT_L3_CACHESHAPE 37
|
||||||
|
#define AT_L1I_CACHESIZE 40
|
||||||
|
#define AT_L1I_CACHEGEOMETRY 41
|
||||||
|
#define AT_L1D_CACHESIZE 42
|
||||||
|
#define AT_L1D_CACHEGEOMETRY 43
|
||||||
|
#define AT_L2_CACHESIZE 44
|
||||||
|
#define AT_L2_CACHEGEOMETRY 45
|
||||||
|
#define AT_L3_CACHESIZE 46
|
||||||
|
#define AT_L3_CACHEGEOMETRY 47
|
||||||
|
#define AT_MINSIGSTKSZ 51
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t a_type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t a_val;
|
||||||
|
} a_un;
|
||||||
|
} Elf32_auxv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint64_t a_type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint64_t a_val;
|
||||||
|
} a_un;
|
||||||
|
} Elf64_auxv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#if defined(__amd64__)
|
||||||
|
Elf64_auxv_t archaux;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#endif
|
||||||
|
} AuxiliaryVector;
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_ABI_H__
|
@ -3,12 +3,28 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#define assert(x) \
|
#include <debug.h>
|
||||||
do \
|
|
||||||
{ \
|
#define assert(x) \
|
||||||
if (!(x)) \
|
do \
|
||||||
while (1) \
|
{ \
|
||||||
; \
|
if (!(x)) \
|
||||||
|
{ \
|
||||||
|
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
|
||||||
|
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
|
||||||
|
while (1) \
|
||||||
|
; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_allow_continue(x) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!(x)) \
|
||||||
|
{ \
|
||||||
|
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
|
||||||
|
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define static_assert(x) \
|
#define static_assert(x) \
|
||||||
|
@ -1585,6 +1585,9 @@ namespace CPU
|
|||||||
__attribute__((no_stack_protector)) static inline void fxsave(char *FXSaveArea)
|
__attribute__((no_stack_protector)) static inline void fxsave(char *FXSaveArea)
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
|
if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000)
|
||||||
|
return;
|
||||||
|
|
||||||
_amd64_fxsave(FXSaveArea);
|
_amd64_fxsave(FXSaveArea);
|
||||||
// asmv("fxsaveq (%0)"
|
// asmv("fxsaveq (%0)"
|
||||||
// :
|
// :
|
||||||
@ -1596,6 +1599,9 @@ namespace CPU
|
|||||||
__attribute__((no_stack_protector)) static inline void fxrstor(char *FXRstorArea)
|
__attribute__((no_stack_protector)) static inline void fxrstor(char *FXRstorArea)
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
|
if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000)
|
||||||
|
return;
|
||||||
|
|
||||||
_amd64_fxrstor(FXRstorArea);
|
_amd64_fxrstor(FXRstorArea);
|
||||||
// asmv("fxrstorq (%0)"
|
// asmv("fxrstorq (%0)"
|
||||||
// :
|
// :
|
||||||
|
@ -40,7 +40,7 @@ namespace Execute
|
|||||||
};
|
};
|
||||||
|
|
||||||
BinaryType GetBinaryType(char *Path);
|
BinaryType GetBinaryType(char *Path);
|
||||||
SpawnData Spawn(char *Path, uint64_t Arg0, uint64_t Arg1);
|
SpawnData Spawn(char *Path, Vector<const char *> &argv, Vector<const char *> &envp);
|
||||||
|
|
||||||
void *ELFLoadRel(Elf64_Ehdr *Header);
|
void *ELFLoadRel(Elf64_Ehdr *Header);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ struct KernelConfig
|
|||||||
bool SchedulerType;
|
bool SchedulerType;
|
||||||
char DriverDirectory[256];
|
char DriverDirectory[256];
|
||||||
char InitPath[256];
|
char InitPath[256];
|
||||||
|
bool InterruptsOnCrash;
|
||||||
int Cores;
|
int Cores;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ struct CPUData
|
|||||||
/** @brief Current running thread */
|
/** @brief Current running thread */
|
||||||
Tasking::TCB *CurrentThread;
|
Tasking::TCB *CurrentThread;
|
||||||
|
|
||||||
/** @brief Architecture-specific CPU data. */
|
/** @brief Architecture-specific data. */
|
||||||
CPUArchData *Data;
|
CPUArchData *Data;
|
||||||
/** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
|
/** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
|
||||||
int Checksum;
|
int Checksum;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
typedef struct SyscallsRegs
|
typedef struct SyscallsFrame
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||||
@ -15,7 +15,10 @@ typedef struct SyscallsRegs
|
|||||||
uint64_t InterruptNumber, ErrorCode, eip, cs, eflags, esp, ss;
|
uint64_t InterruptNumber, ErrorCode, eip, cs, eflags, esp, ss;
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
} SyscallsRegs;
|
} SyscallsFrame;
|
||||||
|
|
||||||
|
uint64_t HandleNativeSyscalls(SyscallsFrame *Frame);
|
||||||
|
uint64_t HandleLinuxSyscalls(SyscallsFrame *Frame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize syscalls for the current CPU. (Function is available on x32, x64 & aarch64)
|
* @brief Initialize syscalls for the current CPU. (Function is available on x32, x64 & aarch64)
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#include <hashmap.hpp>
|
#include <hashmap.hpp>
|
||||||
#include <ipc.hpp>
|
#include <ipc.hpp>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <abi.h>
|
||||||
|
|
||||||
namespace Tasking
|
namespace Tasking
|
||||||
{
|
{
|
||||||
typedef unsigned long IP;
|
typedef unsigned long IP;
|
||||||
typedef unsigned long Arg;
|
|
||||||
typedef unsigned long IPOffset;
|
typedef unsigned long IPOffset;
|
||||||
typedef unsigned long UPID;
|
typedef unsigned long UPID;
|
||||||
typedef unsigned long UTID;
|
typedef unsigned long UTID;
|
||||||
@ -84,8 +84,6 @@ namespace Tasking
|
|||||||
struct PCB *Parent;
|
struct PCB *Parent;
|
||||||
IP EntryPoint;
|
IP EntryPoint;
|
||||||
IPOffset Offset;
|
IPOffset Offset;
|
||||||
Arg Argument0;
|
|
||||||
Arg Argument1;
|
|
||||||
int ExitCode;
|
int ExitCode;
|
||||||
void *Stack;
|
void *Stack;
|
||||||
TaskStatus Status;
|
TaskStatus Status;
|
||||||
@ -217,6 +215,17 @@ namespace Tasking
|
|||||||
public:
|
public:
|
||||||
void Schedule();
|
void Schedule();
|
||||||
long GetUsage(int Core) { return 100 - IdleProcess->Info.Usage[Core]; }
|
long GetUsage(int Core) { return 100 - IdleProcess->Info.Usage[Core]; }
|
||||||
|
void KillThread(TCB *tcb, int Code)
|
||||||
|
{
|
||||||
|
tcb->Status = TaskStatus::Terminated;
|
||||||
|
tcb->ExitCode = Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KillProcess(PCB *pcb, int Code)
|
||||||
|
{
|
||||||
|
pcb->Status = TaskStatus::Terminated;
|
||||||
|
pcb->ExitCode = Code;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Current Process object
|
* @brief Get the Current Process object
|
||||||
@ -242,8 +251,9 @@ namespace Tasking
|
|||||||
|
|
||||||
TCB *CreateThread(PCB *Parent,
|
TCB *CreateThread(PCB *Parent,
|
||||||
IP EntryPoint,
|
IP EntryPoint,
|
||||||
Arg Argument0 = 0,
|
Vector<const char *> &argv,
|
||||||
Arg Argument1 = 0,
|
Vector<const char *> &envp,
|
||||||
|
Vector<AuxiliaryVector> &auxv,
|
||||||
IPOffset Offset = 0,
|
IPOffset Offset = 0,
|
||||||
TaskArchitecture Architecture = TaskArchitecture::x64,
|
TaskArchitecture Architecture = TaskArchitecture::x64,
|
||||||
TaskCompatibility Compatibility = TaskCompatibility::Native);
|
TaskCompatibility Compatibility = TaskCompatibility::Native);
|
||||||
|
@ -200,4 +200,45 @@ typedef __SIZE_TYPE__ size_t;
|
|||||||
#define WINT_MAX __WINT_MAX__
|
#define WINT_MAX __WINT_MAX__
|
||||||
#define WINT_MIN __WINT_MIN__
|
#define WINT_MIN __WINT_MIN__
|
||||||
|
|
||||||
|
#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4)
|
||||||
|
#define b8(x) ((x)&0xFF)
|
||||||
|
#define b16(x) __builtin_bswap16(x)
|
||||||
|
#define b32(x) __builtin_bswap32(x)
|
||||||
|
#define b48(x) (((((x)&0x0000000000ff) << 40) | (((x)&0x00000000ff00) << 24) | (((x)&0x000000ff0000) << 8) | (((x)&0x0000ff000000) >> 8) | (((x)&0x00ff00000000) >> 24) | (((x)&0xff0000000000) >> 40)))
|
||||||
|
#define b64(x) __builtin_bswap64(x)
|
||||||
|
|
||||||
|
|
||||||
|
#define O0 __attribute__((optimize("O0")))
|
||||||
|
#define O1 __attribute__((optimize("O1")))
|
||||||
|
#define O2 __attribute__((optimize("O2")))
|
||||||
|
#define O3 __attribute__((optimize("O3")))
|
||||||
|
#define Os __attribute__((optimize("Os")))
|
||||||
|
#define Ofast __attribute__((optimize("Ofast")))
|
||||||
|
|
||||||
|
/** @brief dbg */
|
||||||
|
#define OPTMZ O0
|
||||||
|
|
||||||
|
#define __unused __attribute__((unused))
|
||||||
|
#define __packed __attribute__((packed))
|
||||||
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
|
#define __section(x) __attribute__((section(x)))
|
||||||
|
#define __noreturn __attribute__((noreturn))
|
||||||
|
#define __weak __attribute__((weak))
|
||||||
|
#define __alias(x) __attribute__((alias(x)))
|
||||||
|
#define __always_inline __attribute__((always_inline))
|
||||||
|
#define __noinline __attribute__((noinline))
|
||||||
|
#define __pure __attribute__((pure))
|
||||||
|
#define __const __attribute__((const))
|
||||||
|
#define __malloc __attribute__((malloc))
|
||||||
|
#define __returns_twice __attribute__((returns_twice))
|
||||||
|
#define __used __attribute__((used))
|
||||||
|
#define __deprecated __attribute__((deprecated))
|
||||||
|
#define __deprecated_msg(x) __attribute__((deprecated(x)))
|
||||||
|
#define __weakref(x) __attribute__((weakref(x)))
|
||||||
|
#define __weakrefalias(x) __attribute__((weakref(#x)))
|
||||||
|
#define __visibility(x) __attribute__((visibility(x)))
|
||||||
|
#define __constructor __attribute__((constructor))
|
||||||
|
#define __destructor __attribute__((destructor))
|
||||||
|
#define __cleanup(x) __attribute__((cleanup(x)))
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_TYPES_H__
|
#endif // !__FENNIX_KERNEL_TYPES_H__
|
||||||
|
1
kernel.h
1
kernel.h
@ -35,6 +35,7 @@ extern Disk::Manager *DiskManager;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EXTERNC void putchar(char c);
|
||||||
EXTERNC void KPrint(const char *format, ...);
|
EXTERNC void KPrint(const char *format, ...);
|
||||||
EXTERNC void Entry(struct BootInfo *Info);
|
EXTERNC void Entry(struct BootInfo *Info);
|
||||||
|
|
||||||
|
12
syscalls.h
Normal file
12
syscalls.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __FENNIX_KERNEL_SYSCALLS_LIST_H__
|
||||||
|
#define __FENNIX_KERNEL_SYSCALLS_LIST_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
enum NativeSyscalls
|
||||||
|
{
|
||||||
|
_exit = 0,
|
||||||
|
_print,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__
|
Loading…
x
Reference in New Issue
Block a user