From b8c5c15a47597a6ec2cc41d462feca9564b171f7 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 16 Oct 2022 20:53:57 +0300 Subject: [PATCH] implemented interrupts handler & stub crash screen --- .../DifferentiatedSystemDescriptionTable.cpp | 24 +- Architecture/amd64/acpi.hpp | 12 +- .../amd64/cpu/InterruptDescriptorTable.cpp | 17 +- .../amd64/cpu/SymmetricMultiprocessing.cpp | 1 + Architecture/amd64/cpu/apic.hpp | 1 - Core/CPU.cpp | 57 +- Core/CrashHandler.cpp | 650 ++++++++++++++++++ Core/Interrupts/IntManager.cpp | 74 +- Core/PeripheralComponentInterconnect.cpp | 2 +- Core/Video/Display.cpp | 5 +- Core/crashhandler.hpp | 13 + Kernel.cpp | 10 +- include/cpu.hpp | 123 ++++ include/display.hpp | 40 +- include/interrupts.hpp | 29 + 15 files changed, 978 insertions(+), 80 deletions(-) create mode 100644 Core/CrashHandler.cpp create mode 100644 Core/crashhandler.hpp diff --git a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp index 1a2735a..a009a0e 100644 --- a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp +++ b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp @@ -4,9 +4,7 @@ #include #include -// #include "../timer.h" -// #include "apic.hpp" -// #include "smp.hpp" +#include "cpu/apic.hpp" #define ACPI_TIMER 0x0001 #define ACPI_BUSMASTER 0x0010 @@ -31,7 +29,7 @@ namespace ACPI #define ACPI_GAS_IO 1 #define ACPI_GAS_PCI 2 - void DSDT::SCIHandler(CPU::x64::TrapFrame *regs) + void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *Frame) { debug("SCI Handle Triggered"); uint16_t event = this->GetSCIevent(); @@ -58,7 +56,7 @@ namespace ACPI return; } } - UNUSED(regs); + UNUSED(Frame); } void DSDT::Shutdown() @@ -163,24 +161,12 @@ namespace ACPI GetSCIevent(); } - void DSDT::InitSCI() - { - // this should be done for all CPUs - if (ACPIShutdownSupported) - { - debug("Registering SCI Handler to vector IRQ%d", acpi->FADT->SCI_Interrupt); - this->RegisterSCIEvents(); - // RegisterInterrupt(this->SCIHandler, acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0, true, true); - } - } - - DSDT::DSDT(ACPI *acpi) + DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0) { uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt); uint8_t *S5Address = (uint8_t *)(Address) + 36; ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address; uint64_t Length = Header->Length; - Address *= 2; while (Length-- > 0) { if (!memcmp(S5Address, "_S5_", 4)) @@ -213,6 +199,8 @@ namespace ACPI SCI_EN = 1; trace("ACPI Shutdown is supported"); ACPIShutdownSupported = true; + this->RegisterSCIEvents(); + ((APIC::APIC *)Interrupts::apic)->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); return; } warn("Failed to parse _S5 in ACPI"); diff --git a/Architecture/amd64/acpi.hpp b/Architecture/amd64/acpi.hpp index f849dac..affd209 100644 --- a/Architecture/amd64/acpi.hpp +++ b/Architecture/amd64/acpi.hpp @@ -246,7 +246,7 @@ namespace ACPI ~MADT(); }; - class DSDT + class DSDT : public Interrupts::Handler { private: uint32_t SMI_CMD = 0; @@ -262,10 +262,17 @@ namespace ACPI ACPI *acpi; +#if defined(__amd64__) + void OnInterruptReceived(CPU::x64::TrapFrame *Frame); +#elif defined(__i386__) + void OnInterruptReceived(void *Frame); +#elif defined(__aarch64__) + void OnInterruptReceived(void *Frame); +#endif + public: bool ACPIShutdownSupported = false; - void SCIHandler(CPU::x64::TrapFrame *regs); void RegisterSCIEvents(); void SetSCIevent(uint16_t value); uint16_t GetSCIevent(); @@ -273,7 +280,6 @@ namespace ACPI void Reboot(); void Shutdown(); - void InitSCI(); DSDT(ACPI *acpi); ~DSDT(); }; diff --git a/Architecture/amd64/cpu/InterruptDescriptorTable.cpp b/Architecture/amd64/cpu/InterruptDescriptorTable.cpp index 2f44a03..7d48691 100644 --- a/Architecture/amd64/cpu/InterruptDescriptorTable.cpp +++ b/Architecture/amd64/cpu/InterruptDescriptorTable.cpp @@ -5,21 +5,8 @@ #include "gdt.hpp" -// TODO: IMPLEMENT "MainInterruptHandler" -extern "C" void MainInterruptHandler(void *Data) -{ - debug("Interrupt: %p", Data); - asmv("cli"); - asmv("hlt"); -} - -// TODO: IMPLEMENT "ExceptionHandler" -extern "C" void ExceptionHandler(void *Data) -{ - debug("Exception: %p", Data); - asmv("cli"); - asmv("hlt"); -} +extern "C" void MainInterruptHandler(void *Data); +extern "C" void ExceptionHandler(void *Data); namespace InterruptDescriptorTable { diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index 1725545..a6d922e 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -70,6 +70,7 @@ extern "C" void StartCPU() // Initialize GDT and IDT Interrupts::Initialize(CPU_ID); + ((APIC::APIC *)Interrupts::apic)->RedirectIRQs(CPU_ID); CPU::Interrupts(CPU::Enable); KPrint("CPU %d is online", CPU_ID); diff --git a/Architecture/amd64/cpu/apic.hpp b/Architecture/amd64/cpu/apic.hpp index 6681112..bfa7b34 100644 --- a/Architecture/amd64/cpu/apic.hpp +++ b/Architecture/amd64/cpu/apic.hpp @@ -52,7 +52,6 @@ namespace APIC void RedirectIRQs(int CPU = 0); void IPI(uint8_t CPU, uint32_t InterruptNumber); void OneShot(uint32_t Vector, uint64_t Miliseconds); - bool APICSupported(); uint32_t IOGetMaxRedirect(uint32_t APICID); void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RedirectIRQ(int CPU, uint8_t IRQ, int Status); diff --git a/Core/CPU.cpp b/Core/CPU.cpp index b49994f..d8edb7a 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -224,41 +224,48 @@ namespace CPU cr4.OSXMMEXCPT = 1; } + if (!BSP) + KPrint("Enabling CPU cache."); // Enable cpu cache but... how to use it? cr0.NW = 0; cr0.CD = 0; - if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) + CPU::x64::writecr0(cr0); + + debug("Enabling UMIP, SMEP & SMAP support..."); + CPU::x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx); + if (rdx & CPU::x64::CPUID_FEAT_RDX_UMIP) { - debug("Enabling UMIP, SMEP & SMAP support..."); - CPU::x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx); - if (rdx & CPU::x64::CPUID_FEAT_RDX_UMIP) - { - if (!BSP) - KPrint("UMIP is supported."); - fixme("Not going to enable UMIP."); - // cr4.UMIP = 1; - } - if (rdx & CPU::x64::CPUID_FEAT_RDX_SMEP) - { - if (!BSP) - KPrint("SMEP is supported."); - cr4.SMEP = 1; - } - if (rdx & CPU::x64::CPUID_FEAT_RDX_SMAP) - { - if (!BSP) - KPrint("SMAP is supported."); - cr4.SMAP = 1; - } - CPU::x64::writecr4(cr4); + if (!BSP) + KPrint("UMIP is supported."); + fixme("Not going to enable UMIP."); + // cr4.UMIP = 1; } + if (rdx & CPU::x64::CPUID_FEAT_RDX_SMEP) + { + if (!BSP) + KPrint("SMEP is supported."); + cr4.SMEP = 1; + } + if (rdx & CPU::x64::CPUID_FEAT_RDX_SMAP) + { + if (!BSP) + KPrint("SMAP is supported."); + cr4.SMAP = 1; + } + if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 && + strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0) + CPU::x64::writecr4(cr4); else { if (!BSP) - KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP"); + { + if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) + KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP"); + else if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0) + KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP"); + } } - CPU::x64::writecr0(cr0); debug("Enabling PAT support..."); CPU::x64::wrmsr(CPU::x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); if (!BSP++) diff --git a/Core/CrashHandler.cpp b/Core/CrashHandler.cpp new file mode 100644 index 0000000..64cb337 --- /dev/null +++ b/Core/CrashHandler.cpp @@ -0,0 +1,650 @@ +#include "crashhandler.hpp" + +#include +#include +#include +#include + +#if defined(__amd64__) +#include "../Architecture/amd64/cpu/gdt.hpp" +#elif defined(__i386__) +#elif defined(__aarch64__) +#endif + +#include "../kernel.h" + +#if defined(__amd64__) || defined(__i386__) +static const char *PagefaultDescriptions[] = { + "Supervisory process tried to read a non-present page entry", + "Supervisory process tried to read a page and caused a protection fault", + "Supervisory process tried to write to a non-present page entry", + "Supervisory process tried to write a page and caused a protection fault", + "User process tried to read a non-present page entry", + "User process tried to read a page and caused a protection fault", + "User process tried to write to a non-present page entry", + "User process tried to write a page and caused a protection fault"}; +#endif + +#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 + +#ifdef __debug_vscode__ +extern "C" int printf_(const char *format, ...); +extern "C" int vprintf_(const char *format, va_list arg); +extern "C" int sprintf_(char *s, const char *format, ...); +#endif + +namespace CrashHandler +{ + void printfWrapper(char c, void *unused) + { + Display->Print(c, 255, true); + UNUSED(unused); + } + + void EHPrint(const char *Format, ...) + { + va_list args; + va_start(args, Format); + vfctprintf(printfWrapper, NULL, Format, args); + va_end(args); + } + + void Handle(void *Data) + { + CPU::Interrupts(CPU::Disable); + +#if defined(__amd64__) + CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data; + error("Exception: %#lx", Frame->int_num); + + if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA) + { + debug("Exception in kernel mode"); + Display->CreateBuffer(0, 0, 255); + } + else + { + debug("Exception in user mode"); + UserModeExceptionHandler(Frame); + return; + } + + debug("Reading control registers..."); + CPU::x64::CR0 cr0 = CPU::x64::readcr0(); + CPU::x64::CR2 cr2 = CPU::x64::readcr2(); + CPU::x64::CR3 cr3 = CPU::x64::readcr3(); + CPU::x64::CR4 cr4 = CPU::x64::readcr4(); + CPU::x64::CR8 cr8 = CPU::x64::readcr8(); + CPU::x64::EFER efer; + efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); + + uint64_t dr0, dr1, dr2, dr3, dr6; + CPU::x64::DR7 dr7; + + // store debug registers + debug("Reading debug registers..."); + asm volatile("movq %%dr0, %0" + : "=r"(dr0)); + asm volatile("movq %%dr1, %0" + : "=r"(dr1)); + asm volatile("movq %%dr2, %0" + : "=r"(dr2)); + asm volatile("movq %%dr3, %0" + : "=r"(dr3)); + asm volatile("movq %%dr6, %0" + : "=r"(dr6)); + asm volatile("movq %%dr7, %0" + : "=r"(dr7)); + + switch (Frame->int_num) + { + case CPU::x64::DivideByZero: + { + DivideByZeroExceptionHandler(Frame); + break; + } + case CPU::x64::Debug: + { + DebugExceptionHandler(Frame); + break; + } + case CPU::x64::NonMaskableInterrupt: + { + NonMaskableInterruptExceptionHandler(Frame); + break; + } + case CPU::x64::Breakpoint: + { + BreakpointExceptionHandler(Frame); + break; + } + case CPU::x64::Overflow: + { + OverflowExceptionHandler(Frame); + break; + } + case CPU::x64::BoundRange: + { + BoundRangeExceptionHandler(Frame); + break; + } + case CPU::x64::InvalidOpcode: + { + InvalidOpcodeExceptionHandler(Frame); + break; + } + case CPU::x64::DeviceNotAvailable: + { + DeviceNotAvailableExceptionHandler(Frame); + break; + } + case CPU::x64::DoubleFault: + { + DoubleFaultExceptionHandler(Frame); + break; + } + case CPU::x64::CoprocessorSegmentOverrun: + { + CoprocessorSegmentOverrunExceptionHandler(Frame); + break; + } + case CPU::x64::InvalidTSS: + { + InvalidTSSExceptionHandler(Frame); + break; + } + case CPU::x64::SegmentNotPresent: + { + SegmentNotPresentExceptionHandler(Frame); + break; + } + case CPU::x64::StackSegmentFault: + { + StackFaultExceptionHandler(Frame); + break; + } + case CPU::x64::GeneralProtectionFault: + { + GeneralProtectionExceptionHandler(Frame); + break; + } + case CPU::x64::PageFault: + { + PageFaultExceptionHandler(Frame); + break; + } + case CPU::x64::x87FloatingPoint: + { + x87FloatingPointExceptionHandler(Frame); + break; + } + case CPU::x64::AlignmentCheck: + { + AlignmentCheckExceptionHandler(Frame); + break; + } + case CPU::x64::MachineCheck: + { + MachineCheckExceptionHandler(Frame); + break; + } + case CPU::x64::SIMDFloatingPoint: + { + SIMDFloatingPointExceptionHandler(Frame); + break; + } + case CPU::x64::Virtualization: + { + VirtualizationExceptionHandler(Frame); + break; + } + case CPU::x64::Security: + { + SecurityExceptionHandler(Frame); + break; + } + default: + { + UnknownExceptionHandler(Frame); + break; + } + } + + EHPrint("\e7981FCTechnical Informations on CPU %ld:\n", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE)); + EHPrint("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx\n", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, Frame->ds); + EHPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11); + EHPrint("R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", Frame->r12, Frame->r13, Frame->r14, Frame->r15); + EHPrint("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx\n", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + EHPrint("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx\n", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + EHPrint("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx\n", Frame->rip, Frame->rflags.raw, Frame->int_num, Frame->error_code, efer.raw); + EHPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); + EHPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", dr0, dr1, dr2, dr3, dr6, dr7.raw); + + EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n", + cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False", + cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False", + cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False", + cr0._reserved0, cr0._reserved1, cr0._reserved2); + + EHPrint("\eFCBD79CR2: PFLA: %#lx\n", + cr2.PFLA); + + EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#lx\n", + cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); + + EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n", + cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False", + cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False", + cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False", + cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False", + cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False", + cr4._reserved0, cr4._reserved1, cr4._reserved2); + + EHPrint("\e79FCF5CR8: TPL:%d\n", cr8.TPL); + + EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n", + Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False", + Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False", + Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False", + Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False", + Frame->rflags.ID ? "True " : "False", Frame->rflags.always_one, + Frame->rflags._reserved0, Frame->rflags._reserved1, Frame->rflags._reserved2, Frame->rflags._reserved3); + + EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n", + dr7.LocalDR0 ? "True " : "False", dr7.GlobalDR0 ? "True " : "False", dr7.LocalDR1 ? "True " : "False", dr7.GlobalDR1 ? "True " : "False", + dr7.LocalDR2 ? "True " : "False", dr7.GlobalDR2 ? "True " : "False", dr7.LocalDR3 ? "True " : "False", dr7.GlobalDR3 ? "True " : "False", + dr7.ConditionsDR0 ? "True " : "False", dr7.SizeDR0 ? "True " : "False", dr7.ConditionsDR1 ? "True " : "False", dr7.SizeDR1 ? "True " : "False", + dr7.ConditionsDR2 ? "True " : "False", dr7.SizeDR2 ? "True " : "False", dr7.ConditionsDR3 ? "True " : "False", dr7.SizeDR3 ? "True " : "False", + dr7.Reserved); + + EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n", + efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False", + efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False", + efer.Reserved0, efer.Reserved1, efer.Reserved2); + + // restore debug registers + debug("Restoring debug registers..."); + asm volatile("movq %0, %%dr0" + : + : "r"(dr0)); + asm volatile("movq %0, %%dr1" + : + : "r"(dr1)); + asm volatile("movq %0, %%dr2" + : + : "r"(dr2)); + asm volatile("movq %0, %%dr3" + : + : "r"(dr3)); + asm volatile("movq %0, %%dr6" + : + : "r"(dr6)); + asm volatile("movq %0, %%dr7" + : + : "r"(dr7)); + + struct StackFrame + { + struct StackFrame *rbp; + uint64_t rip; + }; + + 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("\eFF0000\n< No stack trace available. >\n"); + Display->SetBuffer(255); + while (1) + CPU::Stop(); + } + else + { + frames = (struct StackFrame *)Frame->rbp; + if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end) + debug("%p-%s <- Exception", (void *)Frame->rip, KernelSymbolTable->GetSymbolFromAddress(Frame->rip)); + else + debug("%p-OUTSIDE KERNEL <- Exception", (void *)Frame->rip); + for (uint64_t frame = 0; frame < 100; ++frame) + { + if (!frames->rip) + break; + if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end) + debug("%p-%s", (void *)frames->rip, KernelSymbolTable->GetSymbolFromAddress(frames->rip)); + else + debug("%p-OUTSIDE KERNEL", (void *)frames->rip); + frames = frames->rbp; + } + } + + if (!frames->rip || !frames->rbp) + { + EHPrint("\e2565CC%p", (void *)Frame->rip); + EHPrint("\e7925CC-"); + EHPrint("\eAA25C%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip)); + EHPrint("\e7981FC <- Exception"); + EHPrint("\eFF0000\n< No stack trace available. >\n"); + Display->SetBuffer(255); + while (1) + CPU::Stop(); + } + 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 (uint64_t frame = 0; frame < 20; ++frame) + { + if (!frames->rip) + break; + EHPrint("\n"); + EHPrint("\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"); + frames = frames->rbp; + } + } + +#elif defined(__i386__) + void *Frame = Data; +#elif defined(__aarch64__) + void *Frame = Data; +#endif + + Display->SetBuffer(255); + while (1) + CPU::Stop(); + } +} + +#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" + +void DivideByZeroExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + fixme("Divide by zero exception"); +} +void DebugExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + CrashHandler::EHPrint("\eDD2920System crashed!\n"); + CrashHandler::EHPrint("Kernel triggered debug exception."); +} +void NonMaskableInterruptExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("NMI exception"); } +void BreakpointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Breakpoint exception"); } +void OverflowExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Overflow exception"); } +void BoundRangeExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Bound range exception"); } +void InvalidOpcodeExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + CrashHandler::EHPrint("\eDD2920System crashed!\n"); + CrashHandler::EHPrint("Kernel tried to execute an invalid opcode."); +} +void DeviceNotAvailableExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Device not available exception"); } +void DoubleFaultExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Double fault exception"); } +void CoprocessorSegmentOverrunExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); } +void InvalidTSSExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Invalid TSS exception"); } +void SegmentNotPresentExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Segment not present exception"); } +void StackFaultExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + // staticbuffer(descbuf); + // staticbuffer(desc_ext); + // staticbuffer(desc_table); + // staticbuffer(desc_idx); + // staticbuffer(desc_tmp); + // CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->error_code}; + // 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("More info about the exception:\n"); +} +void GeneralProtectionExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + // staticbuffer(descbuf); + // staticbuffer(desc_ext); + // staticbuffer(desc_table); + // staticbuffer(desc_idx); + // staticbuffer(desc_tmp); + // SelectorErrorCode SelCode = {.raw = ERROR_CODE}; + // switch (SelCode.Table) + // { + // case CPU::x64::0b00: + // memcpy(desc_tmp, "GDT", 3); + // break; + // case CPU::x64::0b01: + // memcpy(desc_tmp, "IDT", 3); + // break; + // case CPU::x64::0b10: + // memcpy(desc_tmp, "LDT", 3); + // break; + // case CPU::x64::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); + // CurrentDisplay->SetPrintColor(0xDD2920); + // SET_PRINT_MID((char *)"System crashed!", FHeight(6)); + // CurrentDisplay->ResetPrintColor(); + // SET_PRINT_MID((char *)"More info about the exception:", FHeight(4)); + // sprintf_(descbuf, "Kernel performed an illegal operation at address %#lx", RIP); + // SET_PRINT_MID((char *)descbuf, FHeight(5)); + // sprintf_(desc_ext, "External: %d", SelCode.External); + // SET_PRINT_MID((char *)desc_ext, FHeight(3)); + // sprintf_(desc_table, "Table: %d (%s)", SelCode.Table, desc_tmp); + // SET_PRINT_MID((char *)desc_table, FHeight(2)); + // sprintf_(desc_idx, "%s Index: %#x", desc_tmp, SelCode.Idx); + // SET_PRINT_MID((char *)desc_idx, FHeight(1)); +} +void PageFaultExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + // err("Kernel Exception"); + // PageFaultErrorCode params = {.raw = (uint32_t)ERROR_CODE}; + + // // We can't use an allocator in exceptions (because that can cause another exception!) so, we'll just use a static buffer. + // staticbuffer(ret_err); + // staticbuffer(page_present); + // staticbuffer(page_write); + // staticbuffer(page_user); + // staticbuffer(page_reserved); + // staticbuffer(page_fetch); + // staticbuffer(page_protection); + // staticbuffer(page_shadow); + // staticbuffer(page_sgx); + + // CurrentDisplay->SetPrintColor(0xDD2920); + // SET_PRINT_MID((char *)"System crashed!", FHeight(12)); + // CurrentDisplay->ResetPrintColor(); + // sprintf_(ret_err, "An exception occurred at %#lx by %#lx", cr2.PFLA, RIP); + // SET_PRINT_MID((char *)ret_err, FHeight(11)); + // sprintf_(page_present, "Page: %s", params.P ? "Present" : "Not Present"); + // SET_PRINT_MID((char *)page_present, FHeight(10)); + // sprintf_(page_write, "Write Operation: %s", params.W ? "Read-Only" : "Read-Write"); + // SET_PRINT_MID((char *)page_write, FHeight(9)); + // sprintf_(page_user, "Processor Mode: %s", params.U ? "User-Mode" : "Kernel-Mode"); + // SET_PRINT_MID((char *)page_user, FHeight(8)); + // sprintf_(page_reserved, "CPU Reserved Bits: %s", params.R ? "Reserved" : "Unreserved"); + // SET_PRINT_MID((char *)page_reserved, FHeight(7)); + // sprintf_(page_fetch, "Caused By An Instruction Fetch: %s", params.I ? "Yes" : "No"); + // SET_PRINT_MID((char *)page_fetch, FHeight(6)); + // sprintf_(page_protection, "Caused By A Protection-Key Violation: %s", params.PK ? "Yes" : "No"); + // SET_PRINT_MID((char *)page_protection, FHeight(5)); + // sprintf_(page_shadow, "Caused By A Shadow Stack Access: %s", params.SS ? "Yes" : "No"); + // SET_PRINT_MID((char *)page_shadow, FHeight(4)); + // sprintf_(page_sgx, "Caused By An SGX Violation: %s", params.SGX ? "Yes" : "No"); + // SET_PRINT_MID((char *)page_sgx, FHeight(3)); + // if (ERROR_CODE & 0x00000008) + // { + // SET_PRINT_MID((char *)"One or more page directory entries contain reserved bits which are set to 1.", FHeight(2)); + // } + // else + // { + // SET_PRINT_MID((char *)pagefault_message[ERROR_CODE & 0b111], FHeight(2)); + // } + // err("\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", page_present, page_write, page_user, page_reserved, page_fetch, page_protection, page_shadow, page_sgx); +} +void x87FloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("x87 floating point exception"); } +void AlignmentCheckExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Alignment check exception"); } +void MachineCheckExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Machine check exception"); } +void SIMDFloatingPointExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("SIMD floating point exception"); } +void VirtualizationExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Virtualization exception"); } +void SecurityExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Security exception"); } +void UnknownExceptionHandler(CPU::x64::TrapFrame *Frame) { fixme("Unknown exception"); } + +void UserModeExceptionHandler(CPU::x64::TrapFrame *Frame) +{ + switch (Frame->int_num) + { + case CPU::x64::DivideByZero: + { + break; + } + case CPU::x64::Debug: + { + break; + } + case CPU::x64::NonMaskableInterrupt: + { + break; + } + case CPU::x64::Breakpoint: + { + break; + } + case CPU::x64::Overflow: + { + break; + } + case CPU::x64::BoundRange: + { + break; + } + case CPU::x64::InvalidOpcode: + { + break; + } + case CPU::x64::DeviceNotAvailable: + { + break; + } + case CPU::x64::DoubleFault: + { + break; + } + case CPU::x64::CoprocessorSegmentOverrun: + { + break; + } + case CPU::x64::InvalidTSS: + { + break; + } + case CPU::x64::SegmentNotPresent: + { + break; + } + case CPU::x64::StackSegmentFault: + { + break; + } + case CPU::x64::GeneralProtectionFault: + { + break; + } + case CPU::x64::PageFault: + { + break; + } + case CPU::x64::x87FloatingPoint: + { + break; + } + case CPU::x64::AlignmentCheck: + { + break; + } + case CPU::x64::MachineCheck: + { + break; + } + case CPU::x64::SIMDFloatingPoint: + { + break; + } + case CPU::x64::Virtualization: + { + break; + } + case CPU::x64::Security: + { + break; + } + default: + { + break; + } + } +} +#endif diff --git a/Core/Interrupts/IntManager.cpp b/Core/Interrupts/IntManager.cpp index cac18fb..50eb7af 100644 --- a/Core/Interrupts/IntManager.cpp +++ b/Core/Interrupts/IntManager.cpp @@ -13,13 +13,17 @@ #elif defined(__aarch64__) #endif +#include "../crashhandler.hpp" #include "../kernel.h" +extern "C" void ExceptionHandler(void *Data) { CrashHandler::Handle(Data); } + namespace Interrupts { #if defined(__amd64__) /* APIC::APIC */ void *apic = nullptr; #elif defined(__i386__) + /* APIC::APIC */ void *apic = nullptr; #elif defined(__aarch64__) #endif @@ -38,14 +42,82 @@ namespace Interrupts { #if defined(__amd64__) if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr) + { apic = new APIC::APIC; + ((APIC::APIC *)apic)->RedirectIRQs(0); + } else { error("LAPIC not found"); - // PIC + // TODO: PIC } #elif defined(__i386__) #elif defined(__aarch64__) +#endif + } + + void InitializeTimer() + { +#if defined(__amd64__) +#elif defined(__i386__) +#elif defined(__aarch64__) +#endif + } + + Vector RegisteredEvents; + + extern "C" void MainInterruptHandler(void *Data) + { +#if defined(__amd64__) + CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data; + if (RegisteredEvents[Frame->int_num]) + RegisteredEvents[Frame->int_num]->OnInterruptReceived(Frame); + + if (apic) + { + ((APIC::APIC *)Interrupts::apic)->EOI(); + return; + } + // TODO: PIC +#elif defined(__i386__) + void *Frame = Data; +#elif defined(__aarch64__) + void *Frame = Data; +#endif + while (1) + CPU::Stop(); + } + + Handler::Handler(int InterruptNumber) + { + debug("Handler::Handler(%d)", InterruptNumber); + this->InterruptNumber = InterruptNumber; + RegisteredEvents.push_back(this); + } + + Handler::~Handler() + { + for (uint64_t i = 0; i < RegisteredEvents.size(); i++) + if (RegisteredEvents[i] == this) + { + debug("Handler::~Handler(%d)", InterruptNumber); + RegisteredEvents.remove(i); + return; + } + } + +#if defined(__amd64__) + void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame) + { + warn("Unhandled interrupt received %#lx", Frame->int_num); +#elif defined(__i386__) + void Handler::OnInterruptReceived(void *Frame); + { + warn("Unhandled interrupt received"); +#elif defined(__aarch64__) + void Handler::OnInterruptReceived(void *Frame); + { + warn("Unhandled interrupt received"); #endif } } diff --git a/Core/PeripheralComponentInterconnect.cpp b/Core/PeripheralComponentInterconnect.cpp index 8fb445e..61e5bb7 100644 --- a/Core/PeripheralComponentInterconnect.cpp +++ b/Core/PeripheralComponentInterconnect.cpp @@ -850,7 +850,7 @@ namespace PCI { DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t)); Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW); - trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress, + trace("PCI Entry %d Address:%#lx BUS:%#lx-%#lx", t, NewDeviceConfig->BaseAddress, NewDeviceConfig->StartBus, NewDeviceConfig->EndBus); for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++) EnumerateBus(NewDeviceConfig->BaseAddress, Bus); diff --git a/Core/Video/Display.cpp b/Core/Video/Display.cpp index 06ecd9e..664c7b7 100644 --- a/Core/Video/Display.cpp +++ b/Core/Video/Display.cpp @@ -1,5 +1,6 @@ #include #include +#include #include extern uint64_t _binary_Files_ter_powerline_v12n_psf_start; @@ -10,9 +11,11 @@ NEWLOCK(PrintLock); namespace Video { - char Display::Print(char Char, int Index) + char Display::Print(char Char, int Index, bool WriteToUART) { SMARTLOCK(PrintLock); + if (WriteToUART) + UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write((char)Char); if (this->ColorIteration) { diff --git a/Core/crashhandler.hpp b/Core/crashhandler.hpp new file mode 100644 index 0000000..cb35514 --- /dev/null +++ b/Core/crashhandler.hpp @@ -0,0 +1,13 @@ +#ifndef __FENNIX_KERNEL_CRASH_HANDELR_H__ +#define __FENNIX_KERNEL_CRASH_HANDELR_H__ + +#include +#include + +namespace CrashHandler +{ + void EHPrint(const char *Format, ...); + void Handle(void *Data); +} + +#endif // !__FENNIX_KERNEL_CRASH_HANDELR_H__ diff --git a/Kernel.cpp b/Kernel.cpp index 3fe5f13..9b89a8d 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -28,14 +28,14 @@ extern "C" int printf_(const char *format, ...); extern "C" int vprintf_(const char *format, va_list arg); #endif -EXTERNC void KPrint(const char *format, ...) +EXTERNC void KPrint(const char *Format, ...) { SMARTLOCK(KernelLock); Time tm = ReadClock(); printf_("\eCCCCCC[\e00AEFF%02ld:%02ld:%02ld\eCCCCCC] ", tm.Hour, tm.Minute, tm.Second); va_list args; - va_start(args, format); - vprintf_(format, args); + va_start(args, Format); + vprintf_(Format, args); va_end(args); putchar('\n'); Display->SetBuffer(0); @@ -82,7 +82,11 @@ EXTERNC void Entry(BootInfo *Info) Interrupts::Enable(); KPrint("Initializing SMP"); SMP::Initialize(PowerManager->GetMADT()); + KPrint("Initializing timer"); + Interrupts::InitializeTimer(); KPrint("\e058C19######## \eE85230END \e058C19########"); + // CPU::Interrupts(CPU::Enable); + asmv("int $0x1"); while (1) CPU::Halt(); } diff --git a/include/cpu.hpp b/include/cpu.hpp index 1cf6c4b..305c111 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -1169,6 +1169,129 @@ namespace CPU uint64_t raw; } CR8; + typedef union EFER + { + struct + { + /** @brief Enable syscall & sysret instructions in 64-bit mode. */ + uint64_t SCE : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 7; + /** @brief Enable long mode. */ + uint64_t LME : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Indicates long. */ + uint64_t LMA : 1; + /** @brief Enable No-Execute Bit */ + uint64_t NXE : 1; + /** @brief Enable Secure Virtual Machine */ + uint64_t SVME : 1; + /** @brief Enable Long Mode Segment Limit */ + uint64_t LMSLE : 1; + /** @brief Enable Fast FXSAVE/FXRSTOR */ + uint64_t FFXSR : 1; + /** @brief Enable Translation Cache Extension */ + uint64_t TCE : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 32; + }; + uint64_t raw; + } __attribute__((packed)) EFER; + + // ! TODO: UNTESTED! + typedef union DR7 + { + struct + { + /** @brief Local DR0 Breakpoint (0) */ + uint64_t LocalDR0 : 1; + /** @brief Global DR0 Breakpoint (1) */ + uint64_t GlobalDR0 : 1; + /** @brief Local DR1 Breakpoint (2) */ + uint64_t LocalDR1 : 1; + /** @brief Global DR1 Breakpoint (3) */ + uint64_t GlobalDR1 : 1; + /** @brief Local DR2 Breakpoint (4) */ + uint64_t LocalDR2 : 1; + /** @brief Global DR2 Breakpoint (5) */ + uint64_t GlobalDR2 : 1; + /** @brief Local DR3 Breakpoint (6) */ + uint64_t LocalDR3 : 1; + /** @brief Global DR3 Breakpoint (7) */ + uint64_t GlobalDR3 : 1; + /** @brief Reserved [7 - (16-17)] */ + uint64_t Reserved : 9; + /** @brief Conditions for DR0 (16-17) */ + uint64_t ConditionsDR0 : 1; + /** @brief Size of DR0 Breakpoint (18-19) */ + uint64_t SizeDR0 : 1; + /** @brief Conditions for DR1 (20-21) */ + uint64_t ConditionsDR1 : 1; + /** @brief Size of DR1 Breakpoint (22-23) */ + uint64_t SizeDR1 : 1; + /** @brief Conditions for DR2 (24-25) */ + uint64_t ConditionsDR2 : 1; + /** @brief Size of DR2 Breakpoint (26-27) */ + uint64_t SizeDR2 : 1; + /** @brief Conditions for DR3 (28-29) */ + uint64_t ConditionsDR3 : 1; + /** @brief Size of DR3 Breakpoint (30-31) */ + uint64_t SizeDR3 : 1; + }; + uint64_t raw; + } DR7; + + typedef union PageFaultErrorCode + { + struct + { + /** @brief When set, the page fault was caused by a page-protection violation. When not set, it was caused by a non-present page. */ + uint64_t P : 1; + /** @brief When set, the page fault was caused by a write access. When not set, it was caused by a read access. */ + uint64_t W : 1; + /** @brief When set, the page fault was caused while CPL = 3. This does not necessarily mean that the page fault was a privilege violation. */ + uint64_t U : 1; + /** @brief When set, one or more page directory entries contain reserved bits which are set to 1. This only applies when the PSE or PAE flags in CR4 are set to 1. */ + uint64_t R : 1; + /** @brief When set, the page fault was caused by an instruction fetch. This only applies when the No-Execute bit is supported and enabled. */ + uint64_t I : 1; + /** @brief When set, the page fault was caused by a protection-key violation. The PKRU register (for user-mode accesses) or PKRS MSR (for supervisor-mode accesses) specifies the protection key rights. */ + uint64_t PK : 1; + /** @brief When set, the page fault was caused by a shadow stack access. */ + uint64_t SS : 1; + /** @brief Reserved */ + uint64_t _reserved0 : 8; + /** @brief When set, the fault was due to an SGX violation. The fault is unrelated to ordinary paging. */ + uint64_t SGX : 1; + /** @brief Reserved */ + uint64_t _reserved1 : 16; + }; + uint64_t raw; + } PageFaultErrorCode; + + // ! TODO: UNTESTED! + typedef union SelectorErrorCode + { + struct + { + /** @brief When set, the exception originated externally to the processor. */ + uint64_t External : 1; + /** @brief IDT/GDT/LDT Table + * @details 0b00 - The Selector Index references a descriptor in the GDT. + * @details 0b01 - The Selector Index references a descriptor in the IDT. + * @details 0b10 - The Selector Index references a descriptor in the LDT. + * @details 0b11 - The Selector Index references a descriptor in the IDT. + */ + uint64_t Table : 2; + /** @brief The index in the GDT, IDT or LDT. */ + uint64_t Idx : 13; + /** @brief Reserved */ + uint64_t Reserved : 16; + }; + uint64_t raw; + } SelectorErrorCode; + static inline void lgdt(void *gdt) { #if defined(__amd64__) diff --git a/include/display.hpp b/include/display.hpp index e3ad631..a4980a8 100644 --- a/include/display.hpp +++ b/include/display.hpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace Video @@ -82,6 +83,7 @@ namespace Video uint64_t Size; uint32_t Color; uint32_t CursorX, CursorY; + long Checksum; }; class Display @@ -89,7 +91,7 @@ namespace Video private: BootInfo::FramebufferInfo framebuffer; Font *CurrentFont; - ScreenBuffer *Buffers[16]; + ScreenBuffer *Buffers[256]; bool ColorIteration = false; int ColorPickerIteration = 0; @@ -98,17 +100,30 @@ namespace Video void SetCurrentFont(Font *Font) { CurrentFont = Font; } void CreateBuffer(uint32_t Width, uint32_t Height, int Index) { + if (Width == 0 && Height == 0) + { + Width = this->framebuffer.Width; + Height = this->framebuffer.Height; + debug("No width and height specified, using %ldx%ld", Width, Height); + } + uint64_t Size = this->framebuffer.Pitch * Height; - ScreenBuffer *buffer = new ScreenBuffer; - buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size)); - buffer->Width = Width; - buffer->Height = Height; - buffer->Size = Size; - buffer->Color = 0x000000; - buffer->CursorX = 0; - buffer->CursorY = 0; - this->Buffers[Index] = buffer; - memset(buffer->Buffer, 0, Size); + if (this->Buffers[Index]->Checksum != 0xDEAD5C9EE7) + { + ScreenBuffer *buffer = new ScreenBuffer; + buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size)); + buffer->Width = Width; + buffer->Height = Height; + buffer->Size = Size; + buffer->Color = 0xFFFFFF; + buffer->CursorX = 0; + buffer->CursorY = 0; + this->Buffers[Index] = buffer; + memset(this->Buffers[Index]->Buffer, 0, Size); + this->Buffers[Index]->Checksum = 0xDEAD5C9EE7; + } + else + warn("Buffer %d already exists, skipping creation", Index); } void SetBuffer(int Index) { memcpy(this->framebuffer.BaseAddress, this->Buffers[Index]->Buffer, this->Buffers[Index]->Size); } void ClearBuffer(int Index) { memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size); } @@ -117,6 +132,7 @@ namespace Video if (this->Buffers[Index] == nullptr) return; KernelAllocator.FreePages(this->Buffers[Index]->Buffer, TO_PAGES(this->Buffers[Index]->Size)); + this->Buffers[Index]->Checksum = 0; // Making sure that the buffer is not used anymore delete this->Buffers[Index]; } @@ -156,7 +172,7 @@ namespace Video } } - char Print(char Char, int Index); + char Print(char Char, int Index, bool WriteToUART = false); Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont = true); ~Display(); }; diff --git a/include/interrupts.hpp b/include/interrupts.hpp index 7b59ccd..0aa800f 100644 --- a/include/interrupts.hpp +++ b/include/interrupts.hpp @@ -2,12 +2,41 @@ #define __FENNIX_KERNEL_INTERRUPTS_H__ #include +#include namespace Interrupts { +#if defined(__amd64__) extern void *apic; +#elif defined(__i386__) + extern void *apic; +#elif defined(__aarch64__) +#endif void Initialize(int Core); void Enable(); + void InitializeTimer(); + + class Handler + { + private: + int InterruptNumber; + + protected: + void SetInterruptNumber(int InterruptNumber) { this->InterruptNumber = InterruptNumber; } + int GetInterruptNumber() { return InterruptNumber; } + Handler(int InterruptNumber); + ~Handler(); + + public: +#if defined(__amd64__) + virtual void OnInterruptReceived(CPU::x64::TrapFrame *Frame); +#elif defined(__i386__) + virtual void OnInterruptReceived(void *Frame); +#elif defined(__aarch64__) + virtual void OnInterruptReceived(void *Frame); +#endif + }; + } #endif // !__FENNIX_KERNEL_INTERRUPTS_H__