From 5fd8d3b3a5c8d691d26ec1db39ef65449a8a8d14 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Wed, 28 Feb 2024 06:31:02 +0200 Subject: [PATCH] Revamped kernel panic functions with significant improvements --- core/crash/crash_details.cpp | 348 ---- core/crash/crash_handler.cpp | 1453 ----------------- core/crash/kb_drv.cpp | 291 ---- core/crash/screens/console.cpp | 42 - core/crash/screens/details.cpp | 265 --- core/crash/screens/main.cpp | 390 ----- core/crash/screens/stack_frame.cpp | 78 - core/crash/screens/tasks.cpp | 99 -- core/crash/stack_frame.cpp | 175 -- core/crash/user_handler.cpp | 225 --- core/crashhandler.hpp | 35 - core/driver/api.cpp | 5 +- core/dsdt.cpp | 8 + core/interrupts_manager.cpp | 13 - core/panic/diag.cpp | 145 ++ core/panic/handler.cpp | 336 ++++ core/panic/keyboard.cpp | 388 +++++ core/{crash/chfcts.hpp => panic/keyboard.hpp} | 123 +- core/panic/ui.cpp | 920 +++++++++++ core/panic/user.cpp | 225 +++ core/stack_check.cpp | 44 +- include/ints.hpp | 1 - include_std/assert.h | 21 +- 23 files changed, 2057 insertions(+), 3573 deletions(-) delete mode 100644 core/crash/crash_details.cpp delete mode 100644 core/crash/crash_handler.cpp delete mode 100644 core/crash/kb_drv.cpp delete mode 100644 core/crash/screens/console.cpp delete mode 100644 core/crash/screens/details.cpp delete mode 100644 core/crash/screens/main.cpp delete mode 100644 core/crash/screens/stack_frame.cpp delete mode 100644 core/crash/screens/tasks.cpp delete mode 100644 core/crash/stack_frame.cpp delete mode 100644 core/crash/user_handler.cpp delete mode 100644 core/crashhandler.hpp create mode 100644 core/panic/diag.cpp create mode 100644 core/panic/handler.cpp create mode 100644 core/panic/keyboard.cpp rename core/{crash/chfcts.hpp => panic/keyboard.hpp} (58%) create mode 100644 core/panic/ui.cpp create mode 100644 core/panic/user.cpp diff --git a/core/crash/crash_details.cpp b/core/crash/crash_details.cpp deleted file mode 100644 index 97de443..0000000 --- a/core/crash/crash_details.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../crashhandler.hpp" -#include "chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../kernel.h" - -static const char *PageFaultDescriptions[8] = { - "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 write to a non-present page entry\n", - "Supervisory process tried to write a page and caused a protection fault\n", - "User process tried to read a non-present page entry\n", - "User process tried to read a page and caused a protection fault\n", - "User process tried to write to a non-present page entry\n", - "User process tried to write a page and caused a protection fault\n"}; - -nsa void DivideByZeroExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Divide by zero exception\n"); - UNUSED(Frame); -} - -nsa void DebugExceptionHandler(CPU::TrapFrame *Frame) -{ - CrashHandler::EHPrint("Kernel triggered debug exception.\n"); - UNUSED(Frame); -} - -nsa void NonMaskableInterruptExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("NMI exception"); - UNUSED(Frame); -} - -nsa void BreakpointExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Breakpoint exception"); - UNUSED(Frame); -} - -nsa void OverflowExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Overflow exception"); - UNUSED(Frame); -} - -nsa void BoundRangeExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Bound range exception"); - UNUSED(Frame); -} - -nsa void InvalidOpcodeExceptionHandler(CPU::TrapFrame *Frame) -{ - CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n"); - UNUSED(Frame); -} - -nsa void DeviceNotAvailableExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Device not available exception"); - UNUSED(Frame); -} - -nsa void DoubleFaultExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Double fault exception"); - UNUSED(Frame); -} - -nsa void CoprocessorSegmentOverrunExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Coprocessor segment overrun exception"); - UNUSED(Frame); -} - -nsa void InvalidTSSExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Invalid TSS exception"); - UNUSED(Frame); -} - -nsa void SegmentNotPresentExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Segment not present exception"); - UNUSED(Frame); -} - -nsa void StackFaultExceptionHandler(CPU::TrapFrame *Frame) -{ - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; -#if defined(a64) - CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip); -#elif defined(a32) - CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip); -#elif defined(aa64) -#endif - 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); -} - -nsa void GeneralProtectionExceptionHandler(CPU::TrapFrame *Frame) -{ - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - // 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; - // } - CrashHandler::EHPrint("Kernel performed an illegal operation.\n"); - CrashHandler::EHPrint("External: %d\n", SelCode.External); - CrashHandler::EHPrint("Table: %d\n", SelCode.Table); - CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx); -} - -nsa void PageFaultExceptionHandler(CPU::TrapFrame *Frame) -{ - CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; -#if defined(a64) - CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip); -#elif defined(a32) - CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip); -#elif defined(aa64) -#endif - CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present"); - CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write"); - CrashHandler::EHPrint("Processor Mode: %s\n", params.U ? "User-Mode" : "Kernel-Mode"); - CrashHandler::EHPrint("CPU Reserved Bits: %s\n", params.R ? "Reserved" : "Unreserved"); - CrashHandler::EHPrint("Caused By An Instruction Fetch: %s\n", params.I ? "Yes" : "No"); - CrashHandler::EHPrint("Caused By A Protection-Key Violation: %s\n", params.PK ? "Yes" : "No"); - CrashHandler::EHPrint("Caused By A Shadow Stack Access: %s\n", params.SS ? "Yes" : "No"); - CrashHandler::EHPrint("Caused By An SGX Violation: %s\n", params.SGX ? "Yes" : "No"); - if (Frame->ErrorCode & 0x00000008) - CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n"); - else - CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]); - -#ifdef DEBUG - uintptr_t CheckPageFaultAddress = 0; - CheckPageFaultAddress = CrashHandler::PageFaultAddress; - if (CheckPageFaultAddress == 0) -#ifdef a64 - CheckPageFaultAddress = Frame->rip; -#elif defined(a32) - CheckPageFaultAddress = Frame->eip; -#elif defined(aa64) - CheckPageFaultAddress = 0; -#endif - -#if defined(a64) - Memory::Virtual vmm(((Memory::PageTable *)CPU::x64::readcr3().raw)); -#elif defined(a32) - Memory::Virtual vmm(((Memory::PageTable *)CPU::x32::readcr3().raw)); -#elif defined(aa64) - Memory::Virtual vmm(); -#warning "TODO: aa64" -#endif - - bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress); - debug("Page available (Check(...)): %s. %s", - PageAvailable ? "Yes" : "No", - (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); - - if (PageAvailable) - { - bool Present = vmm.Check((void *)CheckPageFaultAddress); - bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); - bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); - bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); - bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); - bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); - bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); - bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); - /* ... */ - - debug("Page available: %s", Present ? "Yes" : "No"); - debug("Page read/write: %s", ReadWrite ? "Yes" : "No"); - debug("Page user/kernel: %s", User ? "User" : "Kernel"); - debug("Page write-through: %s", WriteThrough ? "Yes" : "No"); - debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No"); - debug("Page accessed: %s", Accessed ? "Yes" : "No"); - debug("Page dirty: %s", Dirty ? "Yes" : "No"); - debug("Page global: %s", Global ? "Yes" : "No"); - - if (Present) - { -#if defined(a64) - uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress; - CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000; - debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress); - - Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress); - debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d", - CheckPageFaultLinearAddress, - Index.PMLIndex, - Index.PDPTEIndex, - Index.PDEIndex, - Index.PTEIndex); -#if defined(a64) - Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x64::readcr3().raw)->Entries[Index.PMLIndex]; -#elif defined(a32) - Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex]; -#elif defined(aa64) - Memory::PageMapLevel4 PML4 = {.raw = 0}; -#warning "TODO: aa64" -#endif - - Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); - Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); - - debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", - Index.PMLIndex, 0, 0, 0, - PML4.Present ? "1" : "0", - PML4.ReadWrite ? "1" : "0", - PML4.UserSupervisor ? "1" : "0", - PML4.WriteThrough ? "1" : "0", - PML4.CacheDisable ? "1" : "0", - PML4.Accessed ? "1" : "0", - PML4.ExecuteDisable ? "1" : "0", - PML4.GetAddress() << 12); - - debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", - Index.PMLIndex, Index.PDPTEIndex, 0, 0, - PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0", - PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - - debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", - Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0, - PDE->Entries[Index.PDEIndex].Present ? "1" : "0", - PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0", - PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0", - PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0", - PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0", - PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0", - PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0", - PDE->Entries[Index.PDEIndex].GetAddress() << 12); - - debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx", - Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex, - PTE->Entries[Index.PTEIndex].Present ? "1" : "0", - PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0", - PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0", - PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0", - PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0", - PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0", - PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0", - PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0", - PTE->Entries[Index.PTEIndex].Global ? "1" : "0", - PTE->Entries[Index.PTEIndex].ProtectionKey, - PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0", - PTE->Entries[Index.PTEIndex].GetAddress() << 12); -#endif - } - } -#endif -} - -nsa void x87FloatingPointExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("x87 floating point exception"); - UNUSED(Frame); -} - -nsa void AlignmentCheckExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Alignment check exception"); - UNUSED(Frame); -} - -nsa void MachineCheckExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Machine check exception"); - UNUSED(Frame); -} - -nsa void SIMDFloatingPointExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("SIMD floating point exception"); - UNUSED(Frame); -} - -nsa void VirtualizationExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Virtualization exception"); - UNUSED(Frame); -} - -nsa void SecurityExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Security exception"); - UNUSED(Frame); -} - -nsa void UnknownExceptionHandler(CPU::TrapFrame *Frame) -{ - fixme("Unknown exception"); - UNUSED(Frame); -} diff --git a/core/crash/crash_handler.cpp b/core/crash/crash_handler.cpp deleted file mode 100644 index 655a308..0000000 --- a/core/crash/crash_handler.cpp +++ /dev/null @@ -1,1453 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../crashhandler.hpp" -#include "chfcts.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../arch/amd64/cpu/gdt.hpp" -#include "../arch/amd64/cpu/apic.hpp" -#elif defined(a32) -#include "../../arch/i386/cpu/gdt.hpp" -#include "../arch/i386/cpu/apic.hpp" -#elif defined(aa64) -#endif - -#include "../../kernel.h" - -NewLock(UserInputLock); - -namespace CrashHandler -{ - uintptr_t PageFaultAddress = 0; - void *EHIntFrames[INT_FRAMES_MAX]; - static bool ExceptionOccurred = false; - int SBIdx = 255; - CrashKeyboardDriver *kbd; - Video::Font *CrashFont = nullptr; - - nsa void printfWrapper(char c, void *unused) - { - Display->Print(c, CrashFont, true); - UNUSED(unused); - } - - nsa void EHPrint(const char *Format, ...) - { - va_list args; - va_start(args, Format); - vfctprintf(printfWrapper, NULL, Format, args); - va_end(args); - } - - nsa void EHDumpData(void *Address, unsigned long Length) - { - EHPrint("-------------------------------------------------------------------------\n"); - Display->UpdateBuffer(); - unsigned char *AddressChar = (unsigned char *)Address; - unsigned char Buffer[17]; - unsigned long Iterate; - for (Iterate = 0; Iterate < Length; Iterate++) - { - if ((Iterate % 16) == 0) - { - if (Iterate != 0) - EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); - EHPrint(" \e9E9E9E%04x\eAABBCC ", Iterate); - Display->UpdateBuffer(); - } - EHPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]); - if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e)) - Buffer[Iterate % 16] = '.'; - else - Buffer[Iterate % 16] = AddressChar[Iterate]; - Buffer[(Iterate % 16) + 1] = '\0'; - } - - while ((Iterate % 16) != 0) - { - EHPrint(" "); - Display->UpdateBuffer(); - Iterate++; - } - - EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); - EHPrint("-------------------------------------------------------------------------\n\n."); - Display->UpdateBuffer(); - } - - nsa char *TrimWhiteSpace(char *str) - { - char *end; - while (*str == ' ') - str++; - if (*str == 0) - return str; - end = str + strlen(str) - 1; - while (end > str && *end == ' ') - end--; - *(end + 1) = 0; - return str; - } - - CRData crashdata{}; - - nsa void DisplayTopOverlay() - { - Video::Font *f = Display->GetCurrentFont(); - Video::FontInfo fi = f->GetInfo(); - - // for (uint32_t i = 0; i < Display->GetWidth; i++) - // { - // for (uint32_t j = 0; j < fi.Height + 8; j++) - // { - // uint32_t grayValue = (j < 0x505050 / 0x040404) ? 0x505050 - (j * 0x040404) : 0; - // Display->SetPixel(i, j, grayValue, SBIdx); - // } - // } - - for (uint32_t i = 0; i < Display->GetWidth; i++) - { - for (uint32_t j = 0; j < fi.Height + 8; j++) - { - uint32_t grayValue = 0x505050 - (j * 0x020202); - Display->SetPixel(i, j, grayValue); - } - } - - for (uint32_t i = 0; i < Display->GetWidth; i++) - Display->SetPixel(i, fi.Height + 8, 0x404040); - - Display->SetBufferCursor(8, (fi.Height + 8) / 6); - switch (SBIdx) - { - case 255: - { - EHPrint("\eAAAAAAMAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 254: - { - EHPrint("\e606060MAIN \eAAAAAADETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 253: - { - EHPrint("\e606060MAIN \e606060DETAILS \eAAAAAAFRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 252: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \eAAAAAATASKS \e606060CONSOLE"); - break; - } - case 251: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \eAAAAAACONSOLE"); - break; - } - default: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - } - EHPrint(" \e00AAFF%ld MiB / %ld MiB (%ld MiB Reserved)", - TO_MiB(KernelAllocator.GetUsedMemory()), - TO_MiB(KernelAllocator.GetTotalMemory()), - TO_MiB(KernelAllocator.GetReservedMemory())); - EHPrint(" \eAA0F0F%s", CPU::Hypervisor()); - EHPrint(" \eAAF00F%s", CPU::Vendor()); - EHPrint(" \eAA00FF%s", CPU::Name()); - Display->SetBufferCursor(0, fi.Height + 10); - - /* https://imgflip.com/i/77slbl */ - if ((Random::rand32() % 100) >= 98) - { - debug("Easter egg activated!"); - int BaseXOffset = Display->GetWidth - 14; - int BaseYOffset = 8; - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E); - - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E); - Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E); - - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000); - Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E); - - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E); - - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832); - - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E); - - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF); - - Display->UpdateBuffer(); - } - } - - nsa void DisplayBottomOverlay() - { - Video::Font *f = Display->GetCurrentFont(); - Video::FontInfo fi = f->GetInfo(); - - for (uint32_t i = 0; i < Display->GetWidth; i++) - for (uint32_t j = Display->GetHeight - fi.Height - 8; j < Display->GetHeight; j++) - Display->SetPixel(i, j, 0x282828); - - Display->SetBufferCursor(8, Display->GetHeight - fi.Height - 4); - EHPrint("\eAAAAAA> \eFAFAFA"); - } - - nsa void ArrowInput(uint8_t key) - { - switch (key) - { - case KEY_D_UP: - if (SBIdx < 255) - SBIdx++; - else - return; - break; - case KEY_D_LEFT: - if (SBIdx < 255) - SBIdx++; - else - return; - break; - case KEY_D_RIGHT: - if (SBIdx > 251) - SBIdx--; - else - return; - break; - case KEY_D_DOWN: - if (SBIdx > 251) - SBIdx--; - else - return; - break; - default: - break; - } - Display->ClearBuffer(); - DisplayTopOverlay(); - EHPrint("\eFAFAFA"); - - switch (SBIdx) - { - case 255: - { - DisplayMainScreen(crashdata); - break; - } - case 254: - { - DisplayDetailsScreen(crashdata); - break; - } - case 253: - { - DisplayStackFrameScreen(crashdata); - break; - } - case 252: - { - DisplayTasksScreen(crashdata); - break; - } - case 251: - { - DisplayConsoleScreen(crashdata); - break; - } - default: - { - break; - } - } - DisplayBottomOverlay(); - Display->UpdateBuffer(); - } - - nsa void UserInput(char *Input) - { - SmartCriticalSection(UserInputLock); - Display->ClearBuffer(); - DisplayTopOverlay(); - EHPrint("\eFAFAFA"); - - if (strcmp(Input, "help") == 0) - { - EHPrint("Available commands are:\n"); - EHPrint("exit - Shutdown the OS.\n"); - EHPrint("reboot - Reboot the OS.\n"); - EHPrint("help - Display this help message.\n"); - EHPrint("showbuf,sb - Display the contents of a screen buffer.\n"); - EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n"); - EHPrint("ifr - Show interrupt frames.\n"); - EHPrint("tlb
- Print the page table entries\n"); - EHPrint("bitmap - Print the memory bitmap\n"); - EHPrint("mem - Print the memory allocation\n"); - EHPrint("cr - Print the CPU control register\n"); - EHPrint("tss - Print the CPU task state segment\n"); - EHPrint("dump
- Dump memory\n"); - EHPrint("uartmemdmp - Dump the memory of a UART.\n"); - EHPrint("main - Show the main screen.\n"); - EHPrint("details - Show the details screen.\n"); - EHPrint("frames - Show the stack frame screen.\n"); - EHPrint("tasks - Show the tasks screen.\n"); - EHPrint("console - Show the console screen.\n"); - EHPrint("Also, you can use the arrow keys to navigate between the screens.\n"); - EHPrint("=========================================================================\n"); - EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); - EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus); - } - else if (strcmp(Input, "exit") == 0) - { - PowerManager->Shutdown(); - EHPrint("\eFFFFFFNow it's safe to turn off your computer."); - Display->UpdateBuffer(); - CPU::Stop(); - } - else if (strcmp(Input, "reboot") == 0) - { - PowerManager->Reboot(); - EHPrint("\eFFFFFFNow it's safe to reboot your computer."); - Display->UpdateBuffer(); - CPU::Stop(); - } - else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0) - { - char *arg = TrimWhiteSpace(Input + 7); - int tmpidx = SBIdx; - SBIdx = atoi(arg); - Display->UpdateBuffer(); -#if defined(a86) - for (int i = 0; i < 5000000; i++) - inb(0x80); -#endif // a64 || a32 - SBIdx = tmpidx; - Display->UpdateBuffer(); - } - else if (strncmp(Input, "ifr", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - int CountI = atoi(arg); - int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]); - - debug("Printing %ld interrupt frames.", CountI); - - if (CountI > TotalCount) - { - EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount); - Display->UpdateBuffer(); - } - else - { - for (int i = 0; i < CountI; i++) - { - if (EHIntFrames[i]) - { - if (!Memory::Virtual().Check(EHIntFrames[i])) - continue; - EHPrint("\n\e2565CC%p", EHIntFrames[i]); - EHPrint("\e7925CC-"); -#if defined(a64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#elif defined(a32) - if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#elif defined(aa64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#endif - EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbol((uintptr_t)EHIntFrames[i])); - else - EHPrint("\eFF4CA9Outside Kernel"); -#if defined(a86) - for (int i = 0; i < 20000; i++) - inb(0x80); -#endif // a64 || a32 - Display->UpdateBuffer(); - } - } - } - } - else if (strncmp(Input, "tlb", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - uintptr_t Address = NULL; - Address = strtol(arg, NULL, 16); - debug("Converted %s to %#lx", arg, Address); - Memory::PageTable *BasePageTable = (Memory::PageTable *)Address; - if (!Memory::Virtual().Check(BasePageTable)) - { - EHPrint("\eFF4400Address %#lx is not valid!\eFAFAFA\n", Address); - goto DrawBottom; - } - - for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++) - { -#if defined(a64) - Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex]; - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, 0, 0, 0, - PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.GetAddress() << 12); - Display->UpdateBuffer(); - if (!PML4.Present) - continue; - - Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); - if (!PDPTE) - continue; - - for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, 0, 0, - PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].GetAddress() << 12); - Display->UpdateBuffer(); - if (!PDPTE->Entries[PDPTEIndex].Present) - continue; - - Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12); - if (!PDE) - continue; - - for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, PDEIndex, 0, - PDE->Entries[PDEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].GetAddress() << 12); - Display->UpdateBuffer(); - if (!PDE->Entries[PDEIndex].Present) - continue; - - Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[PDEIndex].GetAddress() << 12); - if (!PTE) - continue; - - for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, PDEIndex, PTEIndex, - PTE->Entries[PTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Dirty ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].PageAttributeTable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Global ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].ProtectionKey, - PTE->Entries[PTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].GetAddress() << 12); - Display->UpdateBuffer(); - } - } - } -#endif - } - } - else if (strncmp(Input, "bitmap", 6) == 0) - { - Bitmap bm = KernelAllocator.GetPageBitmap(); - - EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0); - for (size_t i = 0; i < bm.Size; i++) - { - if (bm.Get(i)) - EHPrint("\eFF00001"); - else - EHPrint("\e00FF000"); - if (i % 128 == 127) - { - short Percentage = s_cst(short, (i * 100) / bm.Size); - EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i); - Display->UpdateBuffer(); - } - } - EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size); - Display->UpdateBuffer(); - } - else if (strcmp(Input, "mem") == 0) - { - uint64_t Total = KernelAllocator.GetTotalMemory(); - uint64_t Used = KernelAllocator.GetUsedMemory(); - uint64_t Free = KernelAllocator.GetFreeMemory(); - uint64_t Reserved = KernelAllocator.GetReservedMemory(); - - EHPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved); - int Progress = s_cst(int, (Used * 100) / Total); - int ReservedProgress = s_cst(int, (Reserved * 100) / Total); - EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress); - for (int i = 0; i < Progress; i++) - EHPrint("\eFF0000|"); - for (int i = 0; i < 100 - Progress; i++) - EHPrint("\e00FF00|"); - for (int i = 0; i < ReservedProgress; i++) - EHPrint("\eFF00FF|"); - EHPrint("\eCCCCCC]\n"); - - Display->UpdateBuffer(); - } - else if (strncmp(Input, "cr", 2) == 0) - { - char *cr = TrimWhiteSpace(Input + 2); - switch (cr[0]) - { - case '0': - { -#if defined(a64) - EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0()); -#elif defined(a32) - EHPrint("\e44AA000: %#lx\n", CPU::x32::readcr0()); -#endif - break; - } - case '2': - { -#if defined(a64) - EHPrint("\e44AA002: %#lx\n", PageFaultAddress); -#elif defined(a32) - EHPrint("\e44AA002: %#lx\n", CPU::x32::readcr2()); -#endif - break; - } - case '3': - { -#if defined(a64) - EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3()); -#elif defined(a32) - EHPrint("\e44AA003: %#lx\n", CPU::x32::readcr3()); -#endif - break; - } - case '4': - { -#if defined(a64) - EHPrint("\e44AA004: %#lx\n", CPU::x64::readcr4()); -#elif defined(a32) - EHPrint("\e44AA004: %#lx\n", CPU::x32::readcr4()); -#endif - break; - } - case '8': - { -#if defined(a64) - EHPrint("\e44AA008: %#lx\n", CPU::x64::readcr8()); -#elif defined(a32) - EHPrint("\e44AA008: %#lx\n", CPU::x32::readcr8()); -#endif - break; - } - default: - EHPrint("\eFF0000Invalid CR\n"); - break; - } - } - else if (strncmp(Input, "tss", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - int TSSIndex = atoi(arg); - if (TSSIndex > SMP::CPUCores) - { - EHPrint("\eFF0000Invalid TSS index\n"); - } - else - { -#if defined(a86) - GlobalDescriptorTable::TaskStateSegment tss = GlobalDescriptorTable::tss[TSSIndex]; - EHPrint("\eFAFAFAStack Pointer 0: \eAABB22%#lx\n", tss.StackPointer[0]); - EHPrint("\eFAFAFAStack Pointer 1: \eAABB22%#lx\n", tss.StackPointer[1]); - EHPrint("\eFAFAFAStack Pointer 2: \eAABB22%#lx\n", tss.StackPointer[2]); - - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[0]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[1]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[2]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[3]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[4]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[5]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[6]); - - EHPrint("\eFAFAFAI/O Map Base Address Offset: \eAABB22%#lx\n", tss.IOMapBaseAddressOffset); - - EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0); - EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1); - EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2); -#elif defined(aa64) - EHPrint("\eFF0000AArch64 does not have TSS\n"); -#endif - } - } - else if (strncmp(Input, "dump", 4) == 0) - { - char *arg = TrimWhiteSpace(Input + 4); - char *addr = strtok(arg, " "); - char *len = strtok(NULL, " "); - if (addr == NULL || len == NULL) - { - EHPrint("\eFF0000Invalid arguments\n"); - } - else - { - uintptr_t Address = strtoul(addr, NULL, 16); - size_t Length = strtoul(len, NULL, 10); - - size_t ActualLength = Length; - uintptr_t AlignedAddress = ROUND_DOWN(Address, PAGE_SIZE); - { - Memory::Virtual vmm; - for (uintptr_t adr = AlignedAddress; - adr < Address + Length; - adr += PAGE_SIZE) - { - if (!vmm.Check((void *)adr)) - { - EHPrint("\eFFA500Address %#lx is not mapped\n", adr); - Display->UpdateBuffer(); - ActualLength -= PAGE_SIZE; - } - } - } - - debug("Dumping %ld bytes from %#lx\n", ActualLength, AlignedAddress); - EHDumpData((void *)AlignedAddress, (unsigned long)ActualLength); - } - } - else if (strncmp(Input, "uartmemdmp", 10) == 0) - { - char *arg = TrimWhiteSpace(Input + 10); - char *cPort = strtok(arg, " "); - char *cBoolSkip = strtok(NULL, " "); - UniversalAsynchronousReceiverTransmitter::SerialPorts port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; - switch (cPort[0]) - { - case '1': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; - break; - case '2': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM2; - break; - case '3': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM3; - break; - case '4': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM4; - break; - case '5': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM5; - break; - case '6': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM6; - break; - case '7': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM7; - break; - case '8': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM8; - break; - default: - EHPrint("\eFF0000Invalid port! Defaulting to 1.\n"); - break; - } - EHPrint("\eF8F8F8Dumping memory to UART port %c (%#lx) and %s inaccessible pages.\n", cPort[0], port, cBoolSkip[0] == '1' ? "skipping" : "zeroing"); - Display->UpdateBuffer(); - uint64_t TotalMemLength = KernelAllocator.GetTotalMemory(); - uint64_t ProgressLength = TotalMemLength; - UniversalAsynchronousReceiverTransmitter::UART uart(port); - Memory::Virtual vmm; - uint8_t *Address = 0x0; - int Progress = 0; - for (size_t i = 0; i < TotalMemLength; i++) - { - if (vmm.Check(Address)) - uart.Write(*Address); - else if (cBoolSkip[0] == '0') - uart.Write((uint8_t)0); - else - ProgressLength--; - Address++; - - if (unlikely(i % 0x1000 == 0)) - { - int NewProgress = (int)((i * 100) / ProgressLength); - if (unlikely(NewProgress != Progress)) - { - Progress = NewProgress; - EHPrint("\n%d%%\n", Progress); - Display->UpdateBuffer(); - } - Display->Print('.'); - if (unlikely(i % 0x500 == 0)) - Display->UpdateBuffer(); - } - } - EHPrint("\nDone.\n"); - } - else if (strcmp(Input, "main") == 0) - { - SBIdx = 255; - DisplayTopOverlay(); - DisplayMainScreen(crashdata); - Display->UpdateBuffer(); - } - else if (strcmp(Input, "details") == 0) - { - SBIdx = 254; - DisplayTopOverlay(); - DisplayDetailsScreen(crashdata); - Display->UpdateBuffer(); - } - else if (strcmp(Input, "frames") == 0) - { - SBIdx = 253; - DisplayTopOverlay(); - DisplayStackFrameScreen(crashdata); - Display->UpdateBuffer(); - } - else if (strcmp(Input, "tasks") == 0) - { - SBIdx = 252; - DisplayTopOverlay(); - DisplayTasksScreen(crashdata); - Display->UpdateBuffer(); - } - else if (strcmp(Input, "console") == 0) - { - SBIdx = 251; - DisplayTopOverlay(); - DisplayConsoleScreen(crashdata); - Display->UpdateBuffer(); - } - else if (strlen(Input) > 0) - EHPrint("Unknown command: %s", Input); - - DrawBottom: - DisplayBottomOverlay(); - Display->UpdateBuffer(); - } - - nsa void StopAllCores() - { -#if defined(a86) - /* FIXME: Can't send IPIs to other cores - * because it causes another exception on - * the other cores. - * - * Also it makes every core to stay at 100% usage for some reason. - */ - - return; - if (SMP::CPUCores > 1) - { - APIC::InterruptCommandRegister icr{}; - bool x2APIC = ((APIC::APIC *)Interrupts::apic[0])->x2APIC; - - if (likely(x2APIC)) - { - icr.x2.VEC = s_cst(uint8_t, CPU::x86::IRQ31); - icr.x2.MT = APIC::Fixed; - icr.x2.L = APIC::Assert; - - for (int i = 1; i < SMP::CPUCores; i++) - { - icr.x2.DES = uint8_t(i); - ((APIC::APIC *)Interrupts::apic[i])->ICR(icr); - } - } - else - { - icr.VEC = s_cst(uint8_t, CPU::x86::IRQ31); - icr.MT = APIC::Fixed; - icr.L = APIC::Assert; - - for (int i = 1; i < SMP::CPUCores; i++) - { - icr.DES = uint8_t(i); - ((APIC::APIC *)Interrupts::apic[i])->ICR(icr); - } - } - CPU::Interrupts(CPU::Disable); - } -#elif defined(aa64) -#endif - } - - nsa inline bool Handle_x86_64(CPU::TrapFrame *Frame) - { -#ifdef a64 - trace("Exception at %#lx(%s)", Frame->rip, - KernelSymbolTable - ? KernelSymbolTable->GetSymbol(Frame->rip) - : "No symbol"); - - for (size_t i = 0; i < INT_FRAMES_MAX; i++) - EHIntFrames[i] = Interrupts::InterruptFrames[i]; - PageFaultAddress = CPU::x64::readcr2().PFLA; - - if (unlikely(Frame->cs != GDT_USER_CODE && - Frame->cs != GDT_USER_DATA)) - { - if (PageFaultAddress) - { - debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))", - Frame->rip, PageFaultAddress, - KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->rip) - : "No symbol"); - } - else - { - debug("Exception in kernel mode (ip: %#lx (%s))", - Frame->rip, - KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->rip) - : "No symbol"); - } - - CPUData *data = GetCurrentCPU(); - if (data) - { - if (data->CurrentThread) - { - if (!data->CurrentThread->Security.IsCritical) - { - fixme("Exception in non-critical thread (kernel mode)"); - } - } - } - - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - StopAllCores(); - } - else - { - CPUData *data = GetCurrentCPU(); - if (PageFaultAddress) - { - debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))", - Frame->rip, PageFaultAddress, - data->CurrentProcess->ELFSymbolTable - ? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->rip) - : "No symbol"); - } - else - { - debug("Exception in user mode (ip: %#lx (%s))", - Frame->rip, - data->CurrentProcess->ELFSymbolTable - ? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->rip) - : "No symbol"); - } - - if (UserModeExceptionHandler(Frame)) - return true; - else if (DebuggerIsAttached) - asmv("int $0x8"); - - if (unlikely(data->CurrentThread->Security.IsCritical)) - { - error("Critical thread \"%s\"(%d) died", - data->CurrentThread->Name, - data->CurrentThread->ID); - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - StopAllCores(); - return false; - } - - Tasking::TCB *tcb = data->CurrentThread; - CPU::Interrupts(CPU::Enable); - while (true) - { - tcb->GetContext()->Yield(); - CPU::Halt(TaskManager->IsPanic()); - } - } -#endif - return false; - } - - nsa inline bool Handle_x86_32(CPU::TrapFrame *Frame) - { -#ifdef a32 - trace("Exception at %#lx(%s)", Frame->eip, - KernelSymbolTable - ? KernelSymbolTable->GetSymbol(Frame->eip) - : "No symbol"); - - for (size_t i = 0; i < INT_FRAMES_MAX; i++) - EHIntFrames[i] = Interrupts::InterruptFrames[i]; - PageFaultAddress = CPU::x32::readcr2().PFLA; - - if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA) - { - CPUData *data = GetCurrentCPU(); - if (PageFaultAddress) - { - debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))", - Frame->eip, PageFaultAddress, - data->CurrentProcess->ELFSymbolTable - ? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->eip) - : "No symbol"); - } - else - { - debug("Exception in kernel mode (ip: %#lx (%s))", - Frame->eip, - data->CurrentProcess->ELFSymbolTable - ? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->eip) - : "No symbol"); - } - - if (UserModeExceptionHandler(Frame)) - return true; - else if (DebuggerIsAttached) - asmv("int $0x8"); - - if (data->CurrentThread) - { - if (!data->CurrentThread->Security.IsCritical) - { - fixme("Exception in non-critical thread (kernel mode)"); - } - } - - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - StopAllCores(); - } - else - { - CPUData *data = GetCurrentCPU(); - if (PageFaultAddress) - { - debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))", - Frame->eip, PageFaultAddress, - KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->eip) - : "No symbol"); - } - else - { - debug("Exception in user mode (ip: %#lx (%s))", - Frame->eip, - KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->eip) - : "No symbol"); - } - - if (UserModeExceptionHandler(Frame)) - return true; - else if (DebuggerIsAttached) - asmv("int $0x8"); - - if (unlikely(data->CurrentThread->Security.IsCritical)) - { - error("Critical thread \"%s\"(%d) died", - data->CurrentThread->Name, - data->CurrentThread->ID); - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - StopAllCores(); - return false; - } - - Tasking::TCB *tcb = data->CurrentThread; - CPU::Interrupts(CPU::Enable); - while (true) - { - tcb->GetContext()->Yield(); - CPU::Halt(TaskManager->IsPanic()); - } - } -#endif - return false; - } - - nsa inline void Print_x86_64(CPU::TrapFrame *Frame) - { -#ifdef a64 - CPU::x64::CR0 cr0 = CPU::x64::readcr0(); - CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; - 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); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); - - EHPrint("\eFF2525FS=%#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, 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->InterruptNumber, Frame->ErrorCode, 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("CR0: 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("CR2: PFLA: %#lx\n", - cr2.PFLA); - - EHPrint("CR3: PWT:%s PCD:%s PDBR:%#lx\n", - cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); - EHPrint("CR4: 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("CR8: TPL:%d\n", cr8.TPL); - - EHPrint("RFL: 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.AlwaysOne, - Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); - - EHPrint("EFER: 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); -#endif - } - - nsa inline void Print_x86_32(CPU::TrapFrame *Frame) - { -#ifdef a32 - CPU::x32::CR0 cr0 = CPU::x32::readcr0(); - CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = PageFaultAddress}; - CPU::x32::CR3 cr3 = CPU::x32::readcr3(); - CPU::x32::CR4 cr4 = CPU::x32::readcr4(); - CPU::x32::CR8 cr8 = CPU::x32::readcr8(); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); - - EHPrint("\eFF2525FS=%#x GS=%#x CS=%#x DS=%#x\n", - CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), - CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE), - Frame->cs, ds); - - EHPrint("EAX=%#x EBX=%#x ECX=%#x EDX=%#x\n", - Frame->eax, Frame->ebx, Frame->ecx, Frame->edx); - - EHPrint("ESI=%#x EDI=%#x EBP=%#x ESP=%#x\n", - Frame->esi, Frame->edi, Frame->ebp, Frame->esp); - - EHPrint("EIP=%#x EFL=%#x INT=%#x ERR=%#x\n", - Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode); - - EHPrint("CR0=%#x CR2=%#x CR3=%#x CR4=%#x CR8=%#x\n", - cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); - - EHPrint("CR0: 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("CR2: PFLA: %#x\n", - cr2.PFLA); - - EHPrint("CR3: PWT:%s PCD:%s PDBR:%#x\n", - cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); - EHPrint("CR4: 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\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); - - EHPrint("CR8: TPL:%d\n", cr8.TPL); - - EHPrint("RFL: 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\n", - Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False", - Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False", - Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False", - Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False", - Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne, - Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2); -#endif - } - - nsa void Handle(void *Data) - { - // TODO: SUPPORT SMP - CPU::Interrupts(CPU::Disable); - CPU::TrapFrame *Frame = (CPU::TrapFrame *)Data; - SBIdx = 255; - debug("-----------------------------------------------------------------------------------"); - debug("%ld MiB / %ld MiB (%ld MiB Reserved)", - TO_MiB(KernelAllocator.GetUsedMemory()), - TO_MiB(KernelAllocator.GetTotalMemory()), - TO_MiB(KernelAllocator.GetReservedMemory())); - error("Exception: %#x", Frame->InterruptNumber); -#if defined(a64) - if (Handle_x86_64(Frame)) -#elif defined(a32) - if (Handle_x86_32(Frame)) -#endif - return; - - if (ExceptionOccurred) - { - SBIdx = 255; - Display->ClearBuffer(); - Display->SetBufferCursor(0, 0); -#if defined(a64) - Print_x86_64(Frame); -#elif defined(a32) - Print_x86_32(Frame); -#endif - EHPrint("\nException occurred while handling exception! HALTED!"); - Display->UpdateBuffer(); - Interrupts::RemoveAll(); - CPU::Stop(); - } - - ExceptionOccurred = true; - - if (DriverManager) - DriverManager->Panic(); - - debug("Reading control registers..."); - crashdata.Frame = Frame; -#if defined(a64) - crashdata.cr0 = CPU::x64::readcr0(); - crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; - crashdata.cr3 = CPU::x64::readcr3(); - crashdata.cr4 = CPU::x64::readcr4(); - crashdata.cr8 = CPU::x64::readcr8(); - crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); -#elif defined(a32) - crashdata.cr0 = CPU::x32::readcr0(); - crashdata.cr2 = CPU::x32::CR2{.PFLA = PageFaultAddress}; - crashdata.cr3 = CPU::x32::readcr3(); - crashdata.cr4 = CPU::x32::readcr4(); - crashdata.cr8 = CPU::x32::readcr8(); -#endif - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); - -// Get debug registers -#ifdef a64 - asmv("movq %%dr0, %0" - : "=r"(crashdata.dr0)); - asmv("movq %%dr1, %0" - : "=r"(crashdata.dr1)); - asmv("movq %%dr2, %0" - : "=r"(crashdata.dr2)); - asmv("movq %%dr3, %0" - : "=r"(crashdata.dr3)); - asmv("movq %%dr6, %0" - : "=r"(crashdata.dr6.raw)); - asmv("movq %%dr7, %0" - : "=r"(crashdata.dr7.raw)); -#endif - - CPUData *cpudata = GetCurrentCPU(); - - 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) - { - crashdata.ID = cpudata->ID; - crashdata.CPUData = cpudata; - error("Technical Informations on CPU %d:", cpudata->ID); - } - - if (TaskManager && cpudata != nullptr) - { - crashdata.Process = cpudata->CurrentProcess.load(); - crashdata.Thread = cpudata->CurrentThread.load(); - - error("Current Process: %s(%ld)", - cpudata->CurrentProcess->Name, - cpudata->CurrentProcess->ID); - error("Current Thread: %s(%ld)", - cpudata->CurrentThread->Name, - cpudata->CurrentThread->ID); - } - - { -#if defined(a64) - error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - - error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11); - error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15); - error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw); - error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw); - error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6.raw, crashdata.dr7.raw); - - error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", - crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False", - crashdata.cr0.ET ? "True " : "False", crashdata.cr0.NE ? "True " : "False", crashdata.cr0.WP ? "True " : "False", crashdata.cr0.AM ? "True " : "False", - crashdata.cr0.NW ? "True " : "False", crashdata.cr0.CD ? "True " : "False", crashdata.cr0.PG ? "True " : "False", - crashdata.cr0.Reserved0, crashdata.cr0.Reserved1, crashdata.cr0.Reserved2); - - error("CR2: PFLA: %#llx", - crashdata.cr2.PFLA); - - error("CR3: PWT:%s PCD:%s PDBR:%#llx", - crashdata.cr3.PWT ? "True " : "False", crashdata.cr3.PCD ? "True " : "False", crashdata.cr3.PDBR); - - error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x", - crashdata.cr4.VME ? "True " : "False", crashdata.cr4.PVI ? "True " : "False", crashdata.cr4.TSD ? "True " : "False", crashdata.cr4.DE ? "True " : "False", - crashdata.cr4.PSE ? "True " : "False", crashdata.cr4.PAE ? "True " : "False", crashdata.cr4.MCE ? "True " : "False", crashdata.cr4.PGE ? "True " : "False", - crashdata.cr4.PCE ? "True " : "False", crashdata.cr4.UMIP ? "True " : "False", crashdata.cr4.OSFXSR ? "True " : "False", crashdata.cr4.OSXMMEXCPT ? "True " : "False", - crashdata.cr4.LA57 ? "True " : "False", crashdata.cr4.VMXE ? "True " : "False", crashdata.cr4.SMXE ? "True " : "False", crashdata.cr4.PCIDE ? "True " : "False", - crashdata.cr4.OSXSAVE ? "True " : "False", crashdata.cr4.SMEP ? "True " : "False", crashdata.cr4.SMAP ? "True " : "False", crashdata.cr4.PKE ? "True " : "False", - crashdata.cr4.Reserved0, crashdata.cr4.Reserved1, crashdata.cr4.Reserved2); - - error("CR8: TPL:%d", crashdata.cr8.TPL); - - error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x", - 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.AlwaysOne, - Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); - - error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s", - crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False", - crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", crashdata.dr6.BT ? "True " : "False"); - - error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s", - crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False", - crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False", - crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False", - crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False", - crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False"); - - error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", - crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False", - crashdata.efer.SVME ? "True " : "False", crashdata.efer.LMSLE ? "True " : "False", crashdata.efer.FFXSR ? "True " : "False", crashdata.efer.TCE ? "True " : "False", - crashdata.efer.Reserved0, crashdata.efer.Reserved1, crashdata.efer.Reserved2); -#elif defined(a32) - error("FS=%#x GS=%#x CS=%#x DS=%#x", - CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE), - Frame->cs, ds); - - error("EAX=%#x EBX=%#x ECX=%#x EDX=%#x", - Frame->eax, Frame->ebx, Frame->ecx, Frame->edx); - - error("ESI=%#x EDI=%#x EBP=%#x ESP=%#x", - Frame->esi, Frame->edi, Frame->ebp, Frame->esp); - - error("EIP=%#x EFL=%#x INT=%#x ERR=%#x", - Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, - Frame->ErrorCode); - - error("CR0=%#x CR2=%#x CR3=%#x CR4=%#x CR8=%#x", - crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, - crashdata.cr4.raw, crashdata.cr8.raw); - - error("DR0=%#x DR1=%#x DR2=%#x DR3=%#x DR6=%#x DR7=%#x", - crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, - crashdata.dr6.raw, crashdata.dr7.raw); - - error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", - crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False", - crashdata.cr0.ET ? "True " : "False", crashdata.cr0.NE ? "True " : "False", crashdata.cr0.WP ? "True " : "False", crashdata.cr0.AM ? "True " : "False", - crashdata.cr0.NW ? "True " : "False", crashdata.cr0.CD ? "True " : "False", crashdata.cr0.PG ? "True " : "False", - crashdata.cr0.Reserved0, crashdata.cr0.Reserved1, crashdata.cr0.Reserved2); - - error("CR2: PFLA: %#x", - crashdata.cr2.PFLA); - - error("CR3: PWT:%s PCD:%s PDBR:%#x", - crashdata.cr3.PWT ? "True " : "False", crashdata.cr3.PCD ? "True " : "False", crashdata.cr3.PDBR); - - error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x", - crashdata.cr4.VME ? "True " : "False", crashdata.cr4.PVI ? "True " : "False", crashdata.cr4.TSD ? "True " : "False", crashdata.cr4.DE ? "True " : "False", - crashdata.cr4.PSE ? "True " : "False", crashdata.cr4.PAE ? "True " : "False", crashdata.cr4.MCE ? "True " : "False", crashdata.cr4.PGE ? "True " : "False", - crashdata.cr4.PCE ? "True " : "False", crashdata.cr4.UMIP ? "True " : "False", crashdata.cr4.OSFXSR ? "True " : "False", crashdata.cr4.OSXMMEXCPT ? "True " : "False", - crashdata.cr4.LA57 ? "True " : "False", crashdata.cr4.VMXE ? "True " : "False", crashdata.cr4.SMXE ? "True " : "False", crashdata.cr4.PCIDE ? "True " : "False", - crashdata.cr4.OSXSAVE ? "True " : "False", crashdata.cr4.SMEP ? "True " : "False", crashdata.cr4.SMAP ? "True " : "False", crashdata.cr4.PKE ? "True " : "False", - crashdata.cr4.Reserved0, crashdata.cr4.Reserved1); - - error("CR8: TPL:%d", crashdata.cr8.TPL); - - error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x", - Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False", - Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False", - Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False", - Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False", - Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne, - Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2); - - error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s", - crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", - crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False", - crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", - crashdata.dr6.BT ? "True " : "False"); - - error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s", - crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False", - crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False", - crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False", - crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False", - crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False"); -#endif - } - - if (Config.InterruptsOnCrash) - { - CrashFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x15b_psf_start, &_binary_files_tamsyn_font_1_11_Tamsyn8x15b_psf_end, Video::FontType::PCScreenFont2); - DisplayTopOverlay(); - DisplayMainScreen(crashdata); - Display->UpdateBuffer(); - Interrupts::RemoveAll(); - kbd = new CrashKeyboardDriver; - DisplayBottomOverlay(); - Display->UpdateBuffer(); - } - else - { - /* - TODO: Stuff that should be done when IOC is disabled. - */ - Display->UpdateBuffer(); - } - - CPU::Halt(true); - } -} diff --git a/core/crash/kb_drv.cpp b/core/crash/kb_drv.cpp deleted file mode 100644 index 8431b63..0000000 --- a/core/crash/kb_drv.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../crashhandler.hpp" -#include "chfcts.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../kernel.h" - -const char sc_ascii_low[] = {'?', '?', '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y', - 'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g', - 'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '}; - -const char sc_ascii_high[] = {'?', '?', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y', - 'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G', - 'H', 'J', 'K', 'L', ';', '\"', '~', '?', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '}; - -static int LowerCase = true; - -static inline int GetLetterFromScanCode(uint8_t ScanCode) -{ - if (ScanCode & 0x80) - { - switch (ScanCode) - { - case KEY_U_LSHIFT: - LowerCase = true; - return KEY_INVALID; - case KEY_U_RSHIFT: - LowerCase = true; - return KEY_INVALID; - default: - return KEY_INVALID; - } - } - else - { - switch (ScanCode) - { - case KEY_D_RETURN: - return '\n'; - case KEY_D_LSHIFT: - LowerCase = false; - return KEY_INVALID; - case KEY_D_RSHIFT: - LowerCase = false; - return KEY_INVALID; - case KEY_D_BACKSPACE: - return ScanCode; - default: - { - if (ScanCode > 0x39) - break; - if (LowerCase) - return sc_ascii_low[ScanCode]; - else - return sc_ascii_high[ScanCode]; - } - } - } - return KEY_INVALID; -} - -namespace CrashHandler -{ - void CrashKeyboardDriver::PS2Wait(bool Read) - { - int Timeout = 100000; - uint8_t Status = 0; - while (Timeout--) - { - Status = inb(0x64); - if (Read) - { - if ((Status & 1) == 1) - return; - } - else - { - if ((Status & 2) == 0) - return; - } - } - } - - CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */ - { -#define WaitRead PS2Wait(true) -#define WaitWrite PS2Wait(false) - CPU::Interrupts(CPU::Disable); -#if defined(a86) - - /* Disable Port 1 */ - WaitWrite; - outb(0x64, 0xAD); - - /* Disable Port 2 */ - WaitWrite; - outb(0x64, 0xA7); - - /* Flush */ - WaitRead; - inb(0x60); - - /* Test PS/2 controller */ - WaitWrite; - outb(0x64, 0xAA); - WaitRead; - uint8_t test = inb(0x60); - if (test != 0x55) - { - if (test == 0xFA) - warn("PS/2 controller acknowledged? (expected TEST_PASSED = 0x55)"); - else - { - error("PS/2 controller self test failed (%#x)", test); - // CPU::Stop(); - } - } - - /* Enable Port 1 */ - WaitWrite; - outb(0x64, 0xAE); - - /* Reset Port 1 */ - WaitWrite; - outb(0x64, 0xFF); /* This may break some keyboards? */ - - /* Test Port 1 */ - WaitWrite; - outb(0x64, 0xAB); - WaitRead; - test = inb(0x60); - - if (test != 0x00) - { - if (test == 0xFA) - warn("PS/2 keyboard acknowledged? (expected TEST_PASSED = 0x00)"); - else - { - error("PS/2 keyboard self test failed (%#x)", test); - // CPU::Stop(); - } - } - - /* Disable Port 1 */ - WaitWrite; - outb(0x64, 0xAD); - - /* Disable Port 2 */ - WaitWrite; - outb(0x64, 0xA7); - - /* Flush Port 1 */ - WaitRead; - inb(0x60); - - /* Read Controller Configuration */ - WaitWrite; - outb(0x64, 0x20); - WaitRead; - uint8_t cfg = inb(0x60); - - /* Enable Port 1 & Port 1 translation */ - cfg |= 0b01000001; - - /* Write Controller Configuration */ - WaitWrite; - outb(0x64, 0x60); - WaitWrite; - outb(0x60, cfg); - - /* Enable Port 1 */ - outb(0x64, 0xAE); - - /* Set scan code set 1 */ - WaitWrite; - outb(0x60, 0xF0); - WaitWrite; - outb(0x60, 0x02); - - /* Check if we have scan code set 1 */ - WaitWrite; - outb(0x60, 0xF0); - WaitWrite; - outb(0x60, 0x00); - - /* Read scan code set */ - WaitRead; - uint8_t scs = inb(0x60); - if (scs != 0x41) - { - warn("PS/2 keyboard scan code set 1 not supported (%#x)", scs); - } -#endif // defined(a86) - - CPU::Interrupts(CPU::Enable); - } - - CrashKeyboardDriver::~CrashKeyboardDriver() - { - error("CrashKeyboardDriver::~CrashKeyboardDriver() called"); - } - - int BackSpaceLimit = 0; - static char UserInputBuffer[1024]; - - nsa void CrashKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame) - { -#if defined(a86) - UNUSED(Frame); - uint8_t scanCode = inb(0x60); - if (scanCode == KEY_D_TAB || - scanCode == KEY_D_LCTRL || - scanCode == KEY_D_LALT || - scanCode == KEY_U_LCTRL || - scanCode == KEY_U_LALT) - return; - - switch (scanCode) - { - case KEY_D_UP: - case KEY_D_LEFT: - case KEY_D_RIGHT: - case KEY_D_DOWN: - ArrowInput(scanCode); - break; - default: - break; - } - - int key = GetLetterFromScanCode(scanCode); - if (key != KEY_INVALID) - { - if (key == KEY_D_BACKSPACE) - { - if (BackSpaceLimit > 0) - { - Display->Print('\b'); - backspace(UserInputBuffer); - BackSpaceLimit--; - } - } - else if (key == '\n') - { - UserInput(UserInputBuffer); - BackSpaceLimit = 0; - UserInputBuffer[0] = '\0'; - } - else - { - append(UserInputBuffer, s_cst(char, key)); - Display->Print((char)key); - BackSpaceLimit++; - } - Display->UpdateBuffer(); /* Update as we type. */ - } -#endif // a64 || a32 - } -} diff --git a/core/crash/screens/console.cpp b/core/crash/screens/console.cpp deleted file mode 100644 index 5bc3272..0000000 --- a/core/crash/screens/console.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../../crashhandler.hpp" -#include "../chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../../kernel.h" - -namespace CrashHandler -{ - nsa void DisplayConsoleScreen(CRData data) - { - EHPrint("TODO"); - UNUSED(data); - } -} \ No newline at end of file diff --git a/core/crash/screens/details.cpp b/core/crash/screens/details.cpp deleted file mode 100644 index 0a0cc88..0000000 --- a/core/crash/screens/details.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../../crashhandler.hpp" -#include "../chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../../kernel.h" - -namespace CrashHandler -{ - nsa void DisplayDetailsScreen(CRData data) - { - if (data.Process) - EHPrint("\e7981FCCurrent Process: %s(%ld)\n", - data.Process->Name, - data.Process->ID); - if (data.Thread) - EHPrint("\e7981FCCurrent Thread: %s(%ld)\n", - data.Thread->Name, - data.Thread->ID); - EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID); - uintptr_t ds; -#if defined(a64) - - CPUData *cpu = (CPUData *)data.CPUData; - if (cpu) - { - EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu); - EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", - cpu->Stack, cpu->ID, cpu->ErrorCode); - EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false"); - EHPrint("Current Process: %#lx, Current Thread: %#lx\n", - cpu->CurrentProcess.load(), cpu->CurrentThread.load()); - EHPrint("Arch Specific Data: %#lx\n", cpu->Data); - EHPrint("Checksum: 0x%X\n", cpu->Checksum); - } - - asmv("mov %%ds, %0" - : "=r"(ds)); -#elif defined(a32) - asmv("mov %%ds, %0" - : "=r"(ds)); -#elif defined(aa64) -#endif - -#if defined(a64) - EHPrint("\e7981FCFS=%#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), - data.Frame->ss, data.Frame->cs, ds); - EHPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11); - EHPrint("R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15); - EHPrint("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx); - EHPrint("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp); - EHPrint("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw); -#elif defined(a32) - EHPrint("\e7981FCFS=%#x GS=%#x CS=%#x DS=%#x\n", - CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE), - data.Frame->cs, ds); - EHPrint("EAX=%#x EBX=%#x ECX=%#x EDX=%#x\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx); - EHPrint("ESI=%#x EDI=%#x EBP=%#x ESP=%#x\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp); - EHPrint("EIP=%#x EFL=%#x INT=%#x ERR=%#x\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode); -#elif defined(aa64) -#endif - -#if defined(a86) - EHPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw); - EHPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.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", - data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False", - data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False", - data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False"); - - EHPrint("\eFCBD79CR2: PFLA: %#lx\n", - data.cr2.PFLA); - - EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#lx\n", - data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.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", - data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False", - data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False", - data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False", - data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False", - data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False"); - EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL); -#endif // a64 || a32 - -#if defined(a64) - 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", - data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False", - data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False", - data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False", - data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False", - data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne); -#elif defined(a32) - EHPrint("\eFCFC02EFL: 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", - data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False", - data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False", - data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False", - data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False", - data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne); -#elif defined(aa64) -#endif - -#if defined(a86) - EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s\n BD:%s BS:%s BT:%s\n", - data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False", - data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False"); - - EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n", - data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False", - data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False", - data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False", - data.dr7.LEN0 ? "True " : "False", data.dr7.RW1 ? "True " : "False", data.dr7.LEN1 ? "True " : "False", data.dr7.RW2 ? "True " : "False", - data.dr7.LEN2 ? "True " : "False", data.dr7.RW3 ? "True " : "False", data.dr7.LEN3 ? "True " : "False"); - -#ifdef a64 - EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n\n", - data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False", - data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False"); -#endif // a64 -#endif - - switch (data.Frame->InterruptNumber) - { - case CPU::x86::DivideByZero: - { - DivideByZeroExceptionHandler(data.Frame); - break; - } - case CPU::x86::Debug: - { - DebugExceptionHandler(data.Frame); - break; - } - case CPU::x86::NonMaskableInterrupt: - { - NonMaskableInterruptExceptionHandler(data.Frame); - break; - } - case CPU::x86::Breakpoint: - { - BreakpointExceptionHandler(data.Frame); - break; - } - case CPU::x86::Overflow: - { - OverflowExceptionHandler(data.Frame); - break; - } - case CPU::x86::BoundRange: - { - BoundRangeExceptionHandler(data.Frame); - break; - } - case CPU::x86::InvalidOpcode: - { - InvalidOpcodeExceptionHandler(data.Frame); - break; - } - case CPU::x86::DeviceNotAvailable: - { - DeviceNotAvailableExceptionHandler(data.Frame); - break; - } - case CPU::x86::DoubleFault: - { - DoubleFaultExceptionHandler(data.Frame); - break; - } - case CPU::x86::CoprocessorSegmentOverrun: - { - CoprocessorSegmentOverrunExceptionHandler(data.Frame); - break; - } - case CPU::x86::InvalidTSS: - { - InvalidTSSExceptionHandler(data.Frame); - break; - } - case CPU::x86::SegmentNotPresent: - { - SegmentNotPresentExceptionHandler(data.Frame); - break; - } - case CPU::x86::StackSegmentFault: - { - StackFaultExceptionHandler(data.Frame); - break; - } - case CPU::x86::GeneralProtectionFault: - { - GeneralProtectionExceptionHandler(data.Frame); - break; - } - case CPU::x86::PageFault: - { - PageFaultExceptionHandler(data.Frame); - break; - } - case CPU::x86::x87FloatingPoint: - { - x87FloatingPointExceptionHandler(data.Frame); - break; - } - case CPU::x86::AlignmentCheck: - { - AlignmentCheckExceptionHandler(data.Frame); - break; - } - case CPU::x86::MachineCheck: - { - MachineCheckExceptionHandler(data.Frame); - break; - } - case CPU::x86::SIMDFloatingPoint: - { - SIMDFloatingPointExceptionHandler(data.Frame); - break; - } - case CPU::x86::Virtualization: - { - VirtualizationExceptionHandler(data.Frame); - break; - } - case CPU::x86::Security: - { - SecurityExceptionHandler(data.Frame); - break; - } - default: - { - UnknownExceptionHandler(data.Frame); - break; - } - } - } -} diff --git a/core/crash/screens/main.cpp b/core/crash/screens/main.cpp deleted file mode 100644 index fe5b488..0000000 --- a/core/crash/screens/main.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../../crashhandler.hpp" -#include "../chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../../kernel.h" - -static const char *PagefaultDescriptions[8] = { - "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 write to a non-present page entry\n", - "Supervisory process tried to write a page and caused a protection fault\n", - "User process tried to read a non-present page entry\n", - "User process tried to read a page and caused a protection fault\n", - "User process tried to write to a non-present page entry\n", - "User process tried to write a page and caused a protection fault\n"}; - -namespace CrashHandler -{ - nsa void DisplayMainScreen(CRData data) - { - CPU::TrapFrame *Frame = data.Frame; - - /* - _______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____ -| __| | | __|_ _| ___| | | | | __ \ _ | __| | | ___| \ -|__ |\ /|__ | | | | ___| | | ---| < |__ | | ___| -- | -|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/ - */ - EHPrint("\eFF5500 _______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____ \n"); - EHPrint("| __| | | __|_ _| ___| | | | | __ \\ _ | __| | | ___| \\ \n"); - EHPrint("|__ |\\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |\n"); - EHPrint("|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/ \n\eFAFAFA"); - - switch (Frame->InterruptNumber) - { - case CPU::x86::DivideByZero: - { - EHPrint("Exception: Divide By Zero\n"); - EHPrint("The processor attempted to divide a number by zero.\n"); - break; - } - case CPU::x86::Debug: - { - EHPrint("Exception: Debug\n"); - EHPrint("A debug exception has occurred.\n"); - break; - } - case CPU::x86::NonMaskableInterrupt: - { - EHPrint("Exception: Non-Maskable Interrupt\n"); - EHPrint("A non-maskable interrupt was received.\n"); - break; - } - case CPU::x86::Breakpoint: - { - EHPrint("Exception: Breakpoint\n"); - EHPrint("The processor encountered a breakpoint.\n"); - break; - } - case CPU::x86::Overflow: - { - EHPrint("Exception: Overflow\n"); - EHPrint("The processor attempted to add a number to a number that was too large.\n"); - break; - } - case CPU::x86::BoundRange: - { - EHPrint("Exception: Bound Range\n"); - EHPrint("The processor attempted to access an array element that is out of bounds.\n"); - break; - } - case CPU::x86::InvalidOpcode: - { - EHPrint("Exception: Invalid Opcode\n"); - EHPrint("The processor attempted to execute an invalid opcode.\n"); - break; - } - case CPU::x86::DeviceNotAvailable: - { - EHPrint("Exception: Device Not Available\n"); - EHPrint("The processor attempted to use a device that is not available.\n"); - break; - } - case CPU::x86::DoubleFault: - { - EHPrint("Exception: Double Fault\n"); - EHPrint("The processor encountered a double fault.\n"); - break; - } - case CPU::x86::CoprocessorSegmentOverrun: - { - EHPrint("Exception: Coprocessor Segment Overrun\n"); - EHPrint("The processor attempted to access a segment that is not available.\n"); - break; - } - case CPU::x86::InvalidTSS: - { - EHPrint("Exception: Invalid TSS\n"); - EHPrint("The processor attempted to access a task state segment that is not available or valid.\n"); - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - EHPrint("External? %s\n", SelCode.External ? "Yes" : "No"); - EHPrint("GDT IDT LDT IDT\n"); - switch (SelCode.Table) - { - case 0b00: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b01: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b10: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b11: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - default: - { - EHPrint(" ? \n"); - EHPrint(" ? \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - } - break; - } - case CPU::x86::SegmentNotPresent: - { - EHPrint("Exception: Segment Not Present\n"); - EHPrint("The processor attempted to access a segment that is not present.\n"); - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - EHPrint("External? %s\n", SelCode.External ? "Yes" : "No"); - EHPrint("GDT IDT LDT IDT\n"); - switch (SelCode.Table) - { - case 0b00: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b01: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b10: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b11: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - default: - { - EHPrint(" ? \n"); - EHPrint(" ? \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - } - break; - } - case CPU::x86::StackSegmentFault: - { - EHPrint("Exception: Stack Segment Fault\n"); - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - EHPrint("External? %s\n", SelCode.External ? "Yes" : "No"); - EHPrint("GDT IDT LDT IDT\n"); - switch (SelCode.Table) - { - case 0b00: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b01: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b10: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b11: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - default: - { - EHPrint(" ? \n"); - EHPrint(" ? \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - } - break; - } - case CPU::x86::GeneralProtectionFault: - { - EHPrint("Exception: General Protection Fault\n"); - EHPrint("Kernel performed an illegal operation.\n"); - CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - EHPrint("External? %s\n", SelCode.External ? "Yes" : "No"); - EHPrint("GDT IDT LDT IDT\n"); - switch (SelCode.Table) - { - case 0b00: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b01: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b10: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - case 0b11: - { - EHPrint(" ^ \n"); - EHPrint(" | \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - default: - { - EHPrint(" ? \n"); - EHPrint(" ? \n"); - EHPrint(" %ld\n", SelCode.Idx); - break; - } - } - break; - } - case CPU::x86::PageFault: - { - EHPrint("Exception: Page Fault\n"); - EHPrint("The processor attempted to access a page that is not present/accessible.\n"); - - CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; -#if defined(a64) - EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip); -#elif defined(a32) - EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip); -#elif defined(aa64) -#endif - EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present"); - EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write"); - EHPrint("Processor Mode: \e8888FF%s\eFAFAFA\n", params.U ? "User-Mode" : "Kernel-Mode"); - EHPrint("CPU Reserved Bits: %s\eFAFAFA\n", params.R ? "\eE85230Reserved" : "\e058C19Unreserved"); - EHPrint("Caused By An Instruction Fetch: %s\eFAFAFA\n", params.I ? "\eE85230Yes" : "\e058C19No"); - EHPrint("Caused By A Protection-Key Violation: %s\eFAFAFA\n", params.PK ? "\eE85230Yes" : "\e058C19No"); - EHPrint("Caused By A Shadow Stack Access: %s\eFAFAFA\n", params.SS ? "\eE85230Yes" : "\e058C19No"); - EHPrint("Caused By An SGX Violation: %s\eFAFAFA\n", params.SGX ? "\eE85230Yes" : "\e058C19No"); - EHPrint("More Info: \e8888FF"); - if (Frame->ErrorCode & 0x00000008) - EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n"); - else - EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]); - EHPrint("\eFAFAFA"); - break; - } - case CPU::x86::x87FloatingPoint: - { - EHPrint("Exception: x87 Floating Point\n"); - EHPrint("The x87 FPU generated an error.\n"); - break; - } - case CPU::x86::AlignmentCheck: - { - EHPrint("Exception: Alignment Check\n"); - EHPrint("The CPU detected an unaligned memory access.\n"); - break; - } - case CPU::x86::MachineCheck: - { - EHPrint("Exception: Machine Check\n"); - EHPrint("The CPU detected a hardware error.\n"); - break; - } - case CPU::x86::SIMDFloatingPoint: - { - EHPrint("Exception: SIMD Floating Point\n"); - EHPrint("The CPU detected an error in the SIMD unit.\n"); - break; - } - case CPU::x86::Virtualization: - { - EHPrint("Exception: Virtualization\n"); - EHPrint("The CPU detected a virtualization error.\n"); - break; - } - case CPU::x86::Security: - { - EHPrint("Exception: Security\n"); - EHPrint("The CPU detected a security violation.\n"); - break; - } - default: - { - EHPrint("Exception: Unknown\n"); - EHPrint("The CPU generated an unknown exception.\n"); - break; - } - } - -#if defined(a64) - EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip); -#elif defined(a32) - EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip); -#elif defined(aa64) -#endif - } -} diff --git a/core/crash/screens/stack_frame.cpp b/core/crash/screens/stack_frame.cpp deleted file mode 100644 index 529a0e5..0000000 --- a/core/crash/screens/stack_frame.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../../crashhandler.hpp" -#include "../chfcts.hpp" - -#include -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../../kernel.h" - -namespace CrashHandler -{ - nsa void DisplayStackFrameScreen(CRData data) - { - EHPrint("\eFAFAFATracing 10 frames..."); - TraceFrames(data, 10, KernelSymbolTable, true); - if (data.Process) - { - EHPrint("\n\eFAFAFATracing 10 process frames..."); - SymbolResolver::Symbols *pSt = data.Process->ELFSymbolTable; - debug("pSt = %#lx", pSt); - if (!pSt || !pSt->SymTableExists) - EHPrint("\n\eFF0000< No symbol table available. >\n"); - else - TraceFrames(data, 10, pSt, false); - } - EHPrint("\n\eFAFAFATracing interrupt frames..."); - for (short i = 0; i < 8; i++) - { - if (EHIntFrames[i]) - { - if (!Memory::Virtual().Check(EHIntFrames[i])) - continue; - EHPrint("\n\e2565CC%p", EHIntFrames[i]); - EHPrint("\e7925CC-"); -#if defined(a64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && - (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#elif defined(a32) - if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && - (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#elif defined(aa64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && - (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) -#endif - EHPrint("\e25CCC9%s", - KernelSymbolTable->GetSymbol((uintptr_t)EHIntFrames[i])); - else - EHPrint("\eFF4CA9Outside Kernel"); - } - } - } -} diff --git a/core/crash/screens/tasks.cpp b/core/crash/screens/tasks.cpp deleted file mode 100644 index 28a55b2..0000000 --- a/core/crash/screens/tasks.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../../crashhandler.hpp" -#include "../chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../../kernel.h" - -namespace CrashHandler -{ - nsa void DisplayTasksScreen(CRData data) - { - const char *StatusColor[] = { - "FF0000", // Unknown - "AAFF00", // Ready - "00AA00", // Running - "FFAA00", // Sleeping - "FFAA00", // Blocked - "FFAA00", // Stopped - "FFAA00", // Waiting - - "FF00FF", // Core dump - "FF0088", // Zombie - "FF0000", // Terminated - }; - - const char *StatusString[] = { - "Unknown", // Unknown - "Ready", // Ready - "Running", // Running - "Sleeping", // Sleeping - "Blocked", // Blocked - "Stopped", // Stopped - "Waiting", // Waiting - - "CoreDump", // Core dump - "Zombie", // Zombie - "Terminated", // Terminated - }; - - if (TaskManager) - { - std::list Plist = TaskManager->GetProcessList(); - - if (data.Thread) -#if defined(a64) - EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", - data.Thread->Name, data.Thread->ID, data.Frame->rip); -#elif defined(a32) - EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", - data.Thread->Name, data.Thread->ID, data.Frame->eip); -#elif defined(aa64) -#endif - - EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size()); - foreach (auto Process in Plist) - { - EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n", - StatusColor[Process->State.load()], Process->Name, - Process->ID, StatusString[Process->State.load()], - Process->PageTable); - - foreach (auto Thread in Process->Threads) - EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n", - StatusColor[Thread->State.load()], Thread->Name, - Thread->ID, StatusString[Thread->State.load()], - Thread->Stack); - } - } - else - EHPrint("\eFAFAFATaskManager is not initialized!\n"); - } -} diff --git a/core/crash/stack_frame.cpp b/core/crash/stack_frame.cpp deleted file mode 100644 index a579466..0000000 --- a/core/crash/stack_frame.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../crashhandler.hpp" -#include "chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../kernel.h" - -#define AddrToStr(addr) SymHandle->GetSymbol(addr) - -namespace CrashHandler -{ - struct StackFrame - { - struct StackFrame *rbp; - uintptr_t rip; - }; - - nsa void TraceFrames(CRData data, int Count, - SymbolResolver::Symbols *SymHandle, - bool Kernel) - { - Memory::Virtual vmm; - - if (!vmm.Check(data.Frame)) - { - EHPrint("Invalid frame pointer: %p\n", data.Frame); - return; - } - - if (!vmm.Check(SymHandle)) - { - EHPrint("Invalid symbol handle: %p\n", SymHandle); - return; - } - - bool TriedRetryBP = false; - struct StackFrame *frames = nullptr; - RetryBP: -#if defined(a64) - if (TriedRetryBP == false) - frames = (struct StackFrame *)data.Frame->rbp; -#elif defined(a32) - if (TriedRetryBP == false) - frames = (struct StackFrame *)data.Frame->ebp; -#elif defined(aa64) -#endif - if (!vmm.Check((void *)frames)) - { - if (TriedRetryBP == false) - { - Memory::Virtual vma(data.Process->PageTable); - debug("Invalid frame pointer: %p", frames); - frames = (struct StackFrame *)data.Process->PageTable->Get((void *)frames); - debug("Physical frame pointer: %p", frames); - TriedRetryBP = true; - goto RetryBP; - } -#if defined(a64) - EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp); -#elif defined(a32) - EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp); -#elif defined(aa64) -#endif - return; - } - - debug("Stack tracing... %p %d %p %d", - data.Frame, Count, frames, Kernel); - EHPrint("\e7981FC\nStack Trace:\n"); - if (!frames || !frames->rip || !frames->rbp) - { -#if defined(a64) - EHPrint("\e2565CC%p", (void *)data.Frame->rip); -#elif defined(a32) - EHPrint("\e2565CC%p", (void *)data.Frame->eip); -#elif defined(aa64) -#endif - EHPrint("\e7925CC-"); -#if defined(a64) - EHPrint("\eAA25CC%s", AddrToStr(data.Frame->rip)); -#elif defined(a32) - EHPrint("\eAA25CC%s", AddrToStr(data.Frame->eip)); -#elif defined(aa64) -#endif - EHPrint("\e7981FC <- Exception"); - EHPrint("\eFF0000\n< No stack trace available. >\n"); - } - else - { -#if defined(a64) - debug("Exception in function %s(%p)", - AddrToStr(data.Frame->rip), - data.Frame->rip); - EHPrint("\e2565CC%p", (void *)data.Frame->rip); - EHPrint("\e7925CC-"); - if ((data.Frame->rip >= 0xFFFFFFFF80000000 && - data.Frame->rip <= (uintptr_t)&_kernel_end) || - Kernel == false) - { - EHPrint("\eAA25CC%s", AddrToStr(data.Frame->rip)); - } - else - EHPrint("Outside Kernel"); -#elif defined(a32) - EHPrint("\e2565CC%p", (void *)data.Frame->eip); - EHPrint("\e7925CC-"); - if ((data.Frame->eip >= 0xC0000000 && - data.Frame->eip <= (uintptr_t)&_kernel_end) || - Kernel == false) - { - EHPrint("\eAA25CC%s", AddrToStr(data.Frame->eip)); - } - else - EHPrint("Outside Kernel"); -#elif defined(aa64) -#endif - EHPrint("\e7981FC <- Exception"); - for (int frame = 0; frame < Count; ++frame) - { - if (!frames->rip) - break; - EHPrint("\n\e2565CC%p", (void *)frames->rip); - EHPrint("\e7925CC-"); -#if defined(a64) - if ((frames->rip >= 0xFFFFFFFF80000000 && - frames->rip <= (uintptr_t)&_kernel_end) || - Kernel == false) -#elif defined(a32) - if ((frames->rip >= 0xC0000000 && - frames->rip <= (uintptr_t)&_kernel_end) || - Kernel == false) -#elif defined(aa64) - if ((frames->rip >= 0xFFFFFFFF80000000 && - frames->rip <= (uintptr_t)&_kernel_end) || - Kernel == false) -#endif - EHPrint("\e25CCC9%s", AddrToStr(frames->rip)); - else - EHPrint("\eFF4CA9Outside Kernel"); - - if (!vmm.Check(frames->rbp)) - return; - frames = frames->rbp; - } - } - EHPrint("\n"); - } -} diff --git a/core/crash/user_handler.cpp b/core/crash/user_handler.cpp deleted file mode 100644 index 4814545..0000000 --- a/core/crash/user_handler.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "../crashhandler.hpp" -#include "chfcts.hpp" - -#include -#include -#include -#include -#include - -#if defined(a64) -#include "../../arch/amd64/cpu/gdt.hpp" -#elif defined(a32) -#elif defined(aa64) -#endif - -#include "../../kernel.h" - -nsa bool UserModeExceptionHandler(CPU::TrapFrame *Frame) -{ - CPUData *CurCPU = GetCurrentCPU(); - Tasking::PCB *CurProc = CurCPU->CurrentProcess; - Tasking::TCB *CurThread = CurCPU->CurrentThread; - debug("Current process %s(%d) and thread %s(%d)", - CurProc->Name, CurProc->ID, CurThread->Name, CurThread->ID); - CurThread->SetState(Tasking::Waiting); - -#ifdef DEBUG - { -#if defined(a64) - CPU::x64::CR0 cr0 = CPU::x64::readcr0(); - CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = CrashHandler::PageFaultAddress}; - 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); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); -#elif defined(a32) - CPU::x32::CR0 cr0 = CPU::x32::readcr0(); - CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = CrashHandler::PageFaultAddress}; - CPU::x32::CR3 cr3 = CPU::x32::readcr3(); - CPU::x32::CR4 cr4 = CPU::x32::readcr4(); - CPU::x32::CR8 cr8 = CPU::x32::readcr8(); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); -#elif defined(aa64) -#endif - -#if defined(a64) - debug("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - debug("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", Frame->r8, Frame->r9, Frame->r10, Frame->r11); - debug("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", Frame->r12, Frame->r13, Frame->r14, Frame->r15); - debug("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - debug("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - debug("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw); -#elif defined(a32) - debug("FS=%#x GS=%#x CS=%#x DS=%#x", - CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE), - Frame->cs, ds); - debug("EAX=%#x EBX=%#x ECX=%#x EDX=%#x", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx); - debug("ESI=%#x EDI=%#x EBP=%#x ESP=%#x", Frame->esi, Frame->edi, Frame->ebp, Frame->esp); - debug("EIP=%#x EFL=%#x INT=%#x ERR=%#x", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode); -#elif defined(aa64) -#endif - -#if defined(a86) - debug("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); - - debug("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", - 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); - - debug("CR2: PFLA: %#lx", - cr2.PFLA); - - debug("CR3: PWT:%s PCD:%s PDBR:%#llx", - cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); -#endif // defined(a86) - -#if defined(a64) - debug("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x", - 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); -#elif defined(a32) - debug("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x", - 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); -#endif - -#if defined(a86) - debug("CR8: TPL:%d", cr8.TPL); -#endif // defined(a86) - -#if defined(a64) - debug("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x", - 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.AlwaysOne, - Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); -#elif defined(a32) - debug("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x", - Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False", - Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False", - Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False", - Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False", - Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne, - Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2); -#elif defined(aa64) -#endif - -#if defined(a64) - debug("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", - 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); -#endif - } -#endif - - switch (Frame->InterruptNumber) - { - case CPU::x86::PageFault: - { - bool Handled = false; - - Handled = CurProc->vma->HandleCoW(CrashHandler::PageFaultAddress); - if (!Handled) - Handled = CurThread->Stack->Expand(CrashHandler::PageFaultAddress); - - if (Handled) - { - debug("Page fault handled"); - CurThread->SetState(Tasking::Ready); - return true; - } - - CurProc->Signals->SendSignal(SIGSEGV, - {Tasking::KILL_CRASH}); - break; - } - case CPU::x86::Debug: - case CPU::x86::Breakpoint: - { - CurProc->Signals->SendSignal(SIGTRAP, - {Tasking::KILL_CRASH}); - break; - } - case CPU::x86::DivideByZero: - case CPU::x86::Overflow: - case CPU::x86::BoundRange: - case CPU::x86::x87FloatingPoint: - case CPU::x86::SIMDFloatingPoint: - { - CurProc->Signals->SendSignal(SIGFPE, - {Tasking::KILL_CRASH}); - break; - } - case CPU::x86::InvalidOpcode: - case CPU::x86::GeneralProtectionFault: - { - CurProc->Signals->SendSignal(SIGILL, - {Tasking::KILL_CRASH}); - break; - } - case CPU::x86::DeviceNotAvailable: - { - CurProc->Signals->SendSignal(SIGBUS, - {Tasking::KILL_CRASH}); - break; - } - case CPU::x86::NonMaskableInterrupt: - case CPU::x86::DoubleFault: - case CPU::x86::CoprocessorSegmentOverrun: - case CPU::x86::InvalidTSS: - case CPU::x86::SegmentNotPresent: - case CPU::x86::StackSegmentFault: - case CPU::x86::AlignmentCheck: - case CPU::x86::MachineCheck: - case CPU::x86::Virtualization: - case CPU::x86::Security: - default: - { - error("Unhandled exception %d on CPU %d", - Frame->InterruptNumber, CurCPU->ID); - break; - } - } - - error("User mode exception handler failed"); - return false; -} diff --git a/core/crashhandler.hpp b/core/crashhandler.hpp deleted file mode 100644 index 60456cb..0000000 --- a/core/crashhandler.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_CRASH_HANDLER_H__ -#define __FENNIX_KERNEL_CRASH_HANDLER_H__ - -#include - -#include -#include - -namespace CrashHandler -{ - extern uintptr_t PageFaultAddress; - extern void *EHIntFrames[INT_FRAMES_MAX]; - - void EHPrint(const char *Format, ...); - void Handle(void *Data); -} - -#endif // !__FENNIX_KERNEL_CRASH_HANDLER_H__ diff --git a/core/driver/api.cpp b/core/driver/api.cpp index 787a119..13fb760 100644 --- a/core/driver/api.cpp +++ b/core/driver/api.cpp @@ -479,9 +479,8 @@ namespace Driver { dbg_api("%d, %s", MajorID, Name); - Tasking::PCB *pcb = TaskManager->CreateProcess(nullptr, - Name, Tasking::System, - nullptr, true, 0, 0); + Tasking::PCB *pcb = TaskManager->CreateProcess(nullptr, Name, Tasking::System, + true, 0, 0); return pcb->ID; } diff --git a/core/dsdt.cpp b/core/dsdt.cpp index eddaf7a..0cb5c34 100644 --- a/core/dsdt.cpp +++ b/core/dsdt.cpp @@ -38,6 +38,8 @@ #define ACPI_PCIE_WAKE 0x4000 #define ACPI_WAKE 0x8000 +extern std::atomic ExceptionLock; + namespace ACPI { __always_inline inline bool IsCanonical(uint64_t Address) @@ -104,6 +106,12 @@ namespace ACPI } else if (Event & ACPI_POWER_BUTTON) { + if (ExceptionLock.load()) + { + this->Shutdown(); + CPU::Stop(); + } + Tasking::PCB *pcb = thisProcess; if (pcb && !pcb->GetContext()->IsPanic()) { diff --git a/core/interrupts_manager.cpp b/core/interrupts_manager.cpp index 76ab596..cbb1d14 100644 --- a/core/interrupts_manager.cpp +++ b/core/interrupts_manager.cpp @@ -34,7 +34,6 @@ #elif defined(aa64) #endif -#include "crashhandler.hpp" #include "../kernel.h" void HandleException(CPU::ExceptionFrame *Frame); @@ -112,7 +111,6 @@ namespace Interrupts /* APIC::Timer */ void *apicTimer[MAX_CPU] = {nullptr}; #elif defined(aa64) #endif - void *InterruptFrames[INT_FRAMES_MAX]; void Initialize(int Core) { @@ -293,17 +291,6 @@ namespace Interrupts #endif // debug("IRQ%ld", Frame->InterruptNumber - 32); - memmove(InterruptFrames + 1, - InterruptFrames, - sizeof(InterruptFrames) - sizeof(InterruptFrames[0])); -#if defined(a64) - InterruptFrames[0] = (void *)Frame->rip; -#elif defined(a32) - InterruptFrames[0] = (void *)Frame->eip; -#elif defined(aa64) - InterruptFrames[0] = (void *)Frame->pc; -#endif - CPUData *CoreData = GetCurrentCPU(); int Core = 0; if (likely(CoreData != nullptr)) diff --git a/core/panic/diag.cpp b/core/panic/diag.cpp new file mode 100644 index 0000000..3bacd89 --- /dev/null +++ b/core/panic/diag.cpp @@ -0,0 +1,145 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(a64) +#include "../../arch/amd64/cpu/gdt.hpp" +#include "../arch/amd64/cpu/apic.hpp" +#elif defined(a32) +#include "../../arch/i386/cpu/gdt.hpp" +#include "../arch/i386/cpu/apic.hpp" +#elif defined(aa64) +#endif + +#include "../../kernel.h" +#include "keyboard.hpp" + +extern void ExPrint(const char *Format, ...); +extern Video::Font *CrashFont; +extern void DisplayTopOverlay(); +extern CPU::ExceptionFrame *ExFrame; + +/* TODO: Add more info */ +struct DiagnosticFile +{ + __packed __aligned(16) struct + { + uint8_t Signature[5] = {'D', 'I', 'A', 'G', '\0'}; + uint32_t Version = 1; + char Is64Bit = 0; + uint32_t Length = 0; + } Header; + + __packed __aligned(16) struct + { + CPU::ExceptionFrame Frame; + + uint32_t KernelMemoryLength; + uint8_t KernelMemory[]; + } Data; +}; + +nsa bool WriteDiagDataToNode(vfs::RefNode *refFile) +{ + uintptr_t KStart = (uintptr_t)&_kernel_start; + uintptr_t kEnd = (uintptr_t)&_kernel_end; + size_t kSize = kEnd - KStart; + + size_t fileSize = sizeof(DiagnosticFile) + kSize; + uint8_t *buf = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(fileSize)); + if (!buf) + { + ExPrint("\eFF0000Failed to allocate memory for diagnostic data\n"); + Display->UpdateBuffer(); + return false; + } + + DiagnosticFile *file = (DiagnosticFile *)buf; + file->Header = {}; + file->Header.Length = uint32_t(fileSize); + file->Header.Is64Bit = sizeof(void *) == 8; + + file->Data.Frame = *ExFrame; + file->Data.KernelMemoryLength = uint32_t(kSize); + memcpy(file->Data.KernelMemory, (void *)KStart, kSize); + + ExPrint("\eFAFAFAWriting to %s\n", refFile->node->FullPath); + size_t w = refFile->write(buf, fileSize); + if (w != fileSize) + { + debug("%d out of %d bytes written", w, fileSize); + ExPrint("\eFF0000Failed to write diagnostic data to file: %s\n", + strerror((int)w)); + Display->UpdateBuffer(); + return false; + } + + return true; +} + +nsa void DiagnosticDataCollection() +{ + Display->ClearBuffer(); + DisplayTopOverlay(); + + ExPrint("\n\eFAFAFAPlease wait while we collect some diagnostic information...\n"); + ExPrint("This may take a while...\n"); + + vfs::Node *panicDir = fs->CreateIfNotExists("/var/panic", vfs::DIRECTORY); + if (!panicDir) + { + ExPrint("\eFF0000Failed to create /var/panic\n"); + Display->UpdateBuffer(); + return; + } + + Time::Clock clock = Time::ReadClock(); + char filename[64]; + for (int i = 0; i < INT32_MAX; i++) + { + sprintf(filename, "dump-%d-%d-%d-%d.dmp", + clock.Year, clock.Month, clock.Day, i); + if (fs->PathExists(filename, panicDir)) + continue; + + fs->Create(filename, vfs::FILE, panicDir); + break; + } + + vfs::RefNode *refFile = fs->Open(filename, panicDir); + if (!WriteDiagDataToNode(refFile)) + { + delete refFile; + return; + } + + ExPrint("You can find the diagnostic file in /var/panic/%s\n", filename); + Display->UpdateBuffer(); + delete refFile; +} diff --git a/core/panic/handler.cpp b/core/panic/handler.cpp new file mode 100644 index 0000000..d0acbbc --- /dev/null +++ b/core/panic/handler.cpp @@ -0,0 +1,336 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(a64) +#include "../../arch/amd64/cpu/gdt.hpp" +#include "../arch/amd64/cpu/apic.hpp" +#elif defined(a32) +#include "../../arch/i386/cpu/gdt.hpp" +#include "../arch/i386/cpu/apic.hpp" +#elif defined(aa64) +#endif + +#include "../../kernel.h" + +extern const char *x86ExceptionMnemonics[]; +extern void DisplayCrashScreen(CPU::ExceptionFrame *Frame); +extern bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame); +extern void DisplayStackSmashing(); +extern void DisplayBufferOverflow(); + +Video::Font *CrashFont = nullptr; + +nsa void __printfWrapper(char c, void *) +{ + Display->Print(c, CrashFont, true); +} + +nsa void ExPrint(const char *Format, ...) +{ + va_list args; + va_start(args, Format); + vfctprintf(__printfWrapper, NULL, Format, args); + va_end(args); +} + +nsa void HaltAllCores() +{ + if (SMP::CPUCores <= 1) + return; + +#if defined(a86) + if (Interrupts::apic[0] == nullptr) + return; + + APIC::InterruptCommandRegister icr{}; + + bool x2APIC = ((APIC::APIC *)Interrupts::apic[0])->x2APIC; + if (likely(x2APIC)) + { + icr.x2.VEC = s_cst(uint8_t, CPU::x86::IRQ31); + icr.x2.MT = APIC::Fixed; + icr.x2.L = APIC::Assert; + + for (int i = 1; i < SMP::CPUCores; i++) + { + icr.x2.DES = uint8_t(i); + ((APIC::APIC *)Interrupts::apic[i])->ICR(icr); + } + } + else + { + icr.VEC = s_cst(uint8_t, CPU::x86::IRQ31); + icr.MT = APIC::Fixed; + icr.L = APIC::Assert; + + for (int i = 1; i < SMP::CPUCores; i++) + { + icr.DES = uint8_t(i); + ((APIC::APIC *)Interrupts::apic[i])->ICR(icr); + } + } +#elif defined(aa64) +#endif +} + +nsa void InitFont() +{ + if (CrashFont == nullptr) + { + /* Hope we won't crash here */ + CrashFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start, + &_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end, + Video::FontType::PCScreenFont2); + } +} + +std::atomic UnrecoverableLock = false; +nsa __noreturn void HandleUnrecoverableException(CPU::ExceptionFrame *Frame) +{ + static int setOnce = 0; + if (!setOnce++) /* FIXME: SMP */ + { + for (uint32_t x = 0; x < Display->GetWidth; x++) + for (uint32_t y = 0; y < Display->GetHeight; y++) + Display->SetPixel(x, y, 0xFF250500); + + Display->SetBufferCursor(0, 0); + } + + CPUData *core = GetCurrentCPU(); + + while (UnrecoverableLock.exchange(true, std::memory_order_acquire)) + CPU::Pause(); + + ExPrint("\eFFFFFF-----------------------------------------------\n"); + ExPrint("Unrecoverable exception %#lx on CPU %d\n", + Frame->InterruptNumber, core->ID); +#if defined(a86) + ExPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", + Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4, Frame->cr8); + ExPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", + Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3, Frame->dr6, Frame->dr7); + ExPrint("GS=%#lx FS=%#lx ES=%#lx DS=%#lx SS=%#lx CS=%#lx\n", + Frame->gs, Frame->fs, Frame->es, Frame->ds, Frame->ss, Frame->cs); +#endif +#if defined(a64) + ExPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", + Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13, + Frame->r14, Frame->r15); +#endif +#if defined(a86) + ExPrint("AX=%#lx BX=%#lx CX=%#lx DX=%#lx SI=%#lx DI=%#lx BP=%#lx SP=%#lx\n", + +#ifdef a64 + Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi, + Frame->rbp, Frame->rsp); +#else + Frame->eax, Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi, + Frame->ebp, Frame->esp); +#endif /* a64 */ + + ExPrint("IP=%#lx FL=%#lx INT=%#lx ERR=%#lx\n", + +#ifdef a64 + Frame->rip, Frame->rflags.raw, +#else + Frame->eip, Frame->eflags.raw, +#endif /* a64 */ + Frame->InterruptNumber, Frame->ErrorCode); +#endif /* a86 */ + + Display->UpdateBuffer(); + error("Unrecoverable Exception: %#lx", Frame->InterruptNumber); + + UnrecoverableLock.store(false, std::memory_order_release); + CPU::Stop(); +} + +nsa __noreturn void HandleExceptionInsideException(CPU::ExceptionFrame *Frame) +{ + ExPrint("\eFFFFFF-----------------------------------------------\n"); + ExPrint("Exception inside exception: %#lx at %#lx\n", + Frame->InterruptNumber, +#if defined(a64) + Frame->rip); +#elif defined(a32) + Frame->eip); +#elif defined(aa64) + Frame->pc); +#endif +#if defined(a86) + ExPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", + Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4, Frame->cr8); + ExPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", + Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3, Frame->dr6, Frame->dr7); + ExPrint("GS=%#lx FS=%#lx ES=%#lx DS=%#lx SS=%#lx CS=%#lx\n", + Frame->gs, Frame->fs, Frame->es, Frame->ds, Frame->ss, Frame->cs); +#endif +#if defined(a64) + ExPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", + Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13, + Frame->r14, Frame->r15); +#endif +#if defined(a86) + ExPrint("AX=%#lx BX=%#lx CX=%#lx DX=%#lx SI=%#lx DI=%#lx BP=%#lx SP=%#lx\n", + +#ifdef a64 + Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi, + Frame->rbp, Frame->rsp); +#else + Frame->eax, Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi, + Frame->ebp, Frame->esp); +#endif /* a64 */ + + ExPrint("IP=%#lx FL=%#lx INT=%#lx ERR=%#lx\n", + +#ifdef a64 + Frame->rip, Frame->rflags.raw, +#else + Frame->eip, Frame->eflags.raw, +#endif /* a64 */ + Frame->InterruptNumber, Frame->ErrorCode); +#endif /* a86 */ + Display->UpdateBuffer(); + CPU::Stop(); +} + +std::atomic ExceptionLock = false; +nsa void HandleException(CPU::ExceptionFrame *Frame) +{ + /* We don't need to restore the page table + because the ExceptionHandlerStub will + do it for us if we return. */ + CPU::PageTable(KernelPageTable); + InitFont(); + + /* First check the exception */ + if (unlikely(Frame->InterruptNumber == CPU::x86::DoubleFault)) + { + ExceptionLock.store(true, std::memory_order_release); + HandleUnrecoverableException(Frame); + } + + if (Frame->cs == GDT_USER_CODE && Frame->cs == GDT_USER_DATA) + { + if (UserModeExceptionHandler(Frame)) + goto ExceptionExit; + + CPUData *core = GetCurrentCPU(); + if (likely(core->CurrentThread->Security.IsCritical == false)) + TaskManager->Yield(); + + error("Critical thread \"%s\"(%d) died", + core->CurrentThread->Name, + core->CurrentThread->ID); + } + + debug("-----------------------------------------------------------------------------------"); + error("Exception: %#x", Frame->InterruptNumber); + debug("%ld MiB / %ld MiB (%ld MiB Reserved)", + TO_MiB(KernelAllocator.GetUsedMemory()), + TO_MiB(KernelAllocator.GetTotalMemory()), + TO_MiB(KernelAllocator.GetReservedMemory())); + + if (ExceptionLock.load(std::memory_order_acquire)) + HandleExceptionInsideException(Frame); + ExceptionLock.store(true, std::memory_order_release); + + { + const char msg[] = "Entering in panic mode..."; + size_t msgLen = strlen(msg); + size_t msgPixels = msgLen * CrashFont->GetInfo().Width; + uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2); + uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2); + Display->SetBufferCursor(x, y); + Display->PrintString("\eFF2525"); + Display->PrintString(msg, CrashFont); + Display->UpdateBuffer(); + } + + if (DriverManager) + DriverManager->Panic(); + if (TaskManager) + TaskManager->Panic(); + Interrupts::RemoveAll(); + HaltAllCores(); + ForceUnlock = true; + + DisplayCrashScreen(Frame); + CPU::Stop(); + +ExceptionExit: + ExceptionLock.store(false, std::memory_order_release); +} + +nsa void BaseBufferStackError() +{ + /* We don't need to restore the page table + because the ExceptionHandlerStub will + do it for us if we return. */ + CPU::PageTable(KernelPageTable); + + if (CrashFont == nullptr) + { + /* Hope we won't crash here */ + CrashFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start, + &_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end, + Video::FontType::PCScreenFont2); + } + + ExceptionLock.store(true, std::memory_order_release); + + if (DriverManager) + DriverManager->Panic(); + if (TaskManager) + TaskManager->Panic(); + HaltAllCores(); + ForceUnlock = true; + + debug("-----------------------------------------------------------------------------------"); + error("Buffer overflow detected"); + debug("%ld MiB / %ld MiB (%ld MiB Reserved)", + TO_MiB(KernelAllocator.GetUsedMemory()), + TO_MiB(KernelAllocator.GetTotalMemory()), + TO_MiB(KernelAllocator.GetReservedMemory())); +} + +nsa __noreturn void HandleStackSmashing() +{ + BaseBufferStackError(); + DisplayStackSmashing(); + CPU::Stop(); +} + +nsa __noreturn void HandleBufferOverflow() +{ + BaseBufferStackError(); + DisplayBufferOverflow(); + CPU::Stop(); +} diff --git a/core/panic/keyboard.cpp b/core/panic/keyboard.cpp new file mode 100644 index 0000000..a3e1b2d --- /dev/null +++ b/core/panic/keyboard.cpp @@ -0,0 +1,388 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "keyboard.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#if defined(a64) +#include "../../arch/amd64/cpu/gdt.hpp" +#elif defined(a32) +#elif defined(aa64) +#endif + +#include "../../kernel.h" + +#define ERROR_COLOR "\eFF0000" +#define WARN_COLOR "\eFFAA00" +#define DEFAULT_COLOR "\e00FF00" + +extern void ExPrint(const char *Format, ...); +extern void ArrowInput(uint8_t key); +extern void UserInput(char *Input); + +const char sc_ascii_low[] = {'?', '?', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y', + 'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '}; + +const char sc_ascii_high[] = {'?', '?', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y', + 'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ';', '\"', '~', '?', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '}; + +static int LowerCase = true; + +nsa static inline int GetLetterFromScanCode(uint8_t ScanCode) +{ + if (ScanCode & 0x80) + { + switch (ScanCode) + { + case KEY_U_LSHIFT: + LowerCase = true; + return KEY_INVALID; + case KEY_U_RSHIFT: + LowerCase = true; + return KEY_INVALID; + default: + return KEY_INVALID; + } + } + else + { + switch (ScanCode) + { + case KEY_D_RETURN: + return '\n'; + case KEY_D_LSHIFT: + LowerCase = false; + return KEY_INVALID; + case KEY_D_RSHIFT: + LowerCase = false; + return KEY_INVALID; + case KEY_D_BACKSPACE: + return ScanCode; + default: + { + if (ScanCode > 0x39) + break; + if (LowerCase) + return sc_ascii_low[ScanCode]; + else + return sc_ascii_high[ScanCode]; + } + } + } + return KEY_INVALID; +} + +nsa void CrashKeyboardDriver::PS2Wait(bool Read) +{ + TimeoutCallNumber++; +#if defined(a86) + int Timeout = 100000; + uint8_t Status = 0; + while (Timeout--) + { + Status = inb(0x64); + if (Read) + { + if ((Status & 1) == 1) + return; + } + else + { + if ((Status & 2) == 0) + return; + } + } + ExPrint(WARN_COLOR "PS/2 controller timeout (%s;%d)\n" DEFAULT_COLOR, + Read ? "read" : "write", TimeoutCallNumber - 1); +#endif // a86 +} + +/* + This simple driver relies on the PS/2 controller to handle the keyboard. + + Maybe is not the most efficient way but most x86 devices out there + still has PS/2 support (emulated or not). + + We even have to make sure IRQ1 is enabled in the PIC but on x64 we use + the I/O APIC... "outb(0x21, 0b11111101);" can be used but the EOI is + automatically sent to I/O APIC if enabled/supported which is bad. + + FIXME: On some real devices, the PS/2 keyboard doesn't send interrupts. + + TODO: Implement a way to handle USB keyboards in the future. +*/ +CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */ +{ +#define WaitRead PS2Wait(true) +#define WaitWrite PS2Wait(false) +#define SetMessageLocation \ + Display->SetBufferCursor(8, \ + Display->GetHeight - \ + Display->GetCurrentFont()->GetInfo().Height - 24) + CPU::Interrupts(CPU::Disable); + + /* Dots will be printed at the bottom of the screen as a progress bar. */ + Display->SetBufferCursor(8, + Display->GetHeight - + Display->GetCurrentFont()->GetInfo().Height - 8); +#if defined(a86) + + /* Disable port 1 & 2 */ + { + /* Disable Port 1 */ + WaitWrite; + outb(0x64, 0xAD); + + /* Disable Port 2 */ + WaitWrite; + outb(0x64, 0xA7); + } + Display->Print('.'); + + /* Flush */ + { + int Timeout = 100000; + while ((inb(0x64) & 1) && Timeout-- > 0) + inb(0x60); + + if (Timeout <= 0) + { + SetMessageLocation; + ExPrint(ERROR_COLOR + "PS/2 controller timeout (flush;0)\n" DEFAULT_COLOR); + CPU::Stop(); + } + } + + Display->Print('.'); + /* Test controller */ + { + /* Save config */ + WaitWrite; + outb(0x64, 0x20); + WaitRead; + uint8_t cfg = inb(0x60); + + /* Test PS/2 controller */ + WaitWrite; + outb(0x64, 0xAA); + WaitRead; + uint8_t test = inb(0x60); + if (test != 0x55) + { + if (test == 0xFA) + { + trace("PS/2 controller sent ACK to test request."); + + WaitRead; + test = inb(0x60); + } + + if (test != 0x55) + { + SetMessageLocation; + ExPrint(ERROR_COLOR + "PS/2 controller self test failed (%#x)\n" DEFAULT_COLOR, + test); + CPU::Stop(); + } + } + + /* Restore config */ + WaitWrite; + outb(0x64, 0x60); + WaitWrite; + outb(0x60, cfg); + } + Display->Print('.'); + + /* Disable scanning; Enable port 1; Set default settings */ + { + /* Disable scanning */ + outb(0x60, 0xF5); + + /* Enable Port 1 */ + WaitWrite; + outb(0x64, 0xAE); + + /* Set default settings */ + outb(0x60, 0xF6); + } + Display->Print('.'); + + /* Test port 1 */ + { + WaitWrite; + outb(0x64, 0xAB); + WaitRead; + uint8_t test = inb(0x60); + + if (test != 0x00) + { + if (test == 0xFA) + { + trace("PS/2 keyboard sent ACK to test request."); + + WaitRead; + test = inb(0x60); + } + + if (test != 0x00) + { + SetMessageLocation; + ExPrint(ERROR_COLOR + "PS/2 keyboard self test failed (%#x)\n" DEFAULT_COLOR, + test); + CPU::Stop(); + } + } + } + Display->Print('.'); + + /* Configure the controller */ + { + /* Read Controller Configuration */ + WaitWrite; + outb(0x64, 0x20); + WaitRead; + uint8_t cfg = inb(0x60); + + /* Enable Port 1 & Port 1 translation */ + cfg |= 0b01000001; + + /* Write Controller Configuration */ + WaitWrite; + outb(0x64, 0x60); + WaitWrite; + outb(0x60, cfg); + } + Display->Print('.'); + + /* Enable port 1; Set scan code; Enable scanning */ + { + /* Enable Port 1 */ + outb(0x64, 0xAE); + + /* Set scan code set 1 */ + WaitWrite; + outb(0x60, 0xF0); + WaitWrite; + outb(0x60, 0x02); + + /* Check if we have scan code set 1 */ + WaitWrite; + outb(0x60, 0xF0); + WaitWrite; + outb(0x60, 0x00); + + /* Read scan code set */ + WaitRead; + uint8_t scs = inb(0x60); + if (scs == 0xFA || scs == 0xFE) + { + if (scs == 0xFA) + trace("PS/2 keyboard sent ACK to scan code set request."); + if (scs == 0xFE) + trace("PS/2 keyboard sent RESEND to scan code set request."); + + WaitRead; + scs = inb(0x60); + } + + if (scs != 0x41) + { + SetMessageLocation; + ExPrint(WARN_COLOR + "PS/2 keyboard scan code set 1 not supported (%#x)\n" DEFAULT_COLOR, + scs); + } + + /* Enable scanning */ + outb(0x60, 0xF4); + } + Display->Print('.'); + +#endif // defined(a86) + + CPU::Interrupts(CPU::Enable); +} + +nsa void CrashKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame) +{ +#if defined(a86) + UNUSED(Frame); + uint8_t scanCode = inb(0x60); + if (scanCode == KEY_D_TAB || + scanCode == KEY_D_LCTRL || + scanCode == KEY_D_LALT || + scanCode == KEY_U_LCTRL || + scanCode == KEY_U_LALT) + return; + + switch (scanCode) + { + case KEY_D_UP: + case KEY_D_LEFT: + case KEY_D_RIGHT: + case KEY_D_DOWN: + ArrowInput(scanCode); + break; + default: + break; + } + + int key = GetLetterFromScanCode(scanCode); + if (key != KEY_INVALID) + { + if (key == KEY_D_BACKSPACE) + { + if (BackSpaceLimit > 0) + { + Display->Print('\b'); + backspace(UserInputBuffer); + BackSpaceLimit--; + } + } + else if (key == '\n') + { + UserInput(UserInputBuffer); + BackSpaceLimit = 0; + UserInputBuffer[0] = '\0'; + } + else + { + append(UserInputBuffer, s_cst(char, key)); + Display->Print((char)key); + BackSpaceLimit++; + } + Display->UpdateBuffer(); /* Update as we type. */ + } +#endif // a64 || a32 +} diff --git a/core/crash/chfcts.hpp b/core/panic/keyboard.hpp similarity index 58% rename from core/crash/chfcts.hpp rename to core/panic/keyboard.hpp index a7905ab..3b6ccfc 100644 --- a/core/crash/chfcts.hpp +++ b/core/panic/keyboard.hpp @@ -15,69 +15,9 @@ along with Fennix Kernel. If not, see . */ -#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__ -#define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__ - -#include - #include -#include -#include - -#if defined(a64) - -struct CRData -{ - CPU::TrapFrame *Frame; - - CPU::x64::CR0 cr0; - CPU::x64::CR2 cr2; - CPU::x64::CR3 cr3; - CPU::x64::CR4 cr4; - CPU::x64::CR8 cr8; - CPU::x64::EFER efer; - uintptr_t dr0, dr1, dr2, dr3; - CPU::x64::DR6 dr6; - CPU::x64::DR7 dr7; - - long ID; - void *CPUData; - Tasking::PCB *Process; - Tasking::TCB *Thread; -}; - -#elif defined(a32) - -struct CRData -{ - CPU::TrapFrame *Frame; - - CPU::x32::CR0 cr0; - CPU::x32::CR2 cr2; - CPU::x32::CR3 cr3; - CPU::x32::CR4 cr4; - CPU::x32::CR8 cr8; - uintptr_t dr0, dr1, dr2, dr3; - CPU::x32::DR6 dr6; - CPU::x32::DR7 dr7; - long ID; - void *CPUData; - Tasking::PCB *Process; - Tasking::TCB *Thread; -}; -#elif defined(aa64) - -struct CRData -{ - CPU::TrapFrame *Frame; - - long ID; - void *CPUData; - Tasking::PCB *Process; - Tasking::TCB *Thread; -}; -#endif +#pragma once enum Keys { @@ -263,56 +203,17 @@ enum Keys KEY_U_F12 = 0xd8, }; -namespace CrashHandler +class CrashKeyboardDriver : public Interrupts::Handler { - extern int SBIdx; - - class CrashKeyboardDriver : public Interrupts::Handler - { - private: - void PS2Wait(bool Read); - void OnInterruptReceived(CPU::TrapFrame *Frame); +private: + void PS2Wait(bool Read); + void OnInterruptReceived(CPU::TrapFrame *Frame); - public: - CrashKeyboardDriver(); - ~CrashKeyboardDriver(); - }; + int BackSpaceLimit = 0; + char UserInputBuffer[256]; + int TimeoutCallNumber = 0; - void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel); - - void ArrowInput(uint8_t key); - void UserInput(char *Input); - - void DisplayMainScreen(CRData data); - void DisplayDetailsScreen(CRData data); - void DisplayStackFrameScreen(CRData data); - void DisplayTasksScreen(CRData data); - void DisplayConsoleScreen(CRData data); -} - -void DivideByZeroExceptionHandler(CPU::TrapFrame *Frame); -void DebugExceptionHandler(CPU::TrapFrame *Frame); -void NonMaskableInterruptExceptionHandler(CPU::TrapFrame *Frame); -void BreakpointExceptionHandler(CPU::TrapFrame *Frame); -void OverflowExceptionHandler(CPU::TrapFrame *Frame); -void BoundRangeExceptionHandler(CPU::TrapFrame *Frame); -void InvalidOpcodeExceptionHandler(CPU::TrapFrame *Frame); -void DeviceNotAvailableExceptionHandler(CPU::TrapFrame *Frame); -void DoubleFaultExceptionHandler(CPU::TrapFrame *Frame); -void CoprocessorSegmentOverrunExceptionHandler(CPU::TrapFrame *Frame); -void InvalidTSSExceptionHandler(CPU::TrapFrame *Frame); -void SegmentNotPresentExceptionHandler(CPU::TrapFrame *Frame); -void StackFaultExceptionHandler(CPU::TrapFrame *Frame); -void GeneralProtectionExceptionHandler(CPU::TrapFrame *Frame); -void PageFaultExceptionHandler(CPU::TrapFrame *Frame); -void x87FloatingPointExceptionHandler(CPU::TrapFrame *Frame); -void AlignmentCheckExceptionHandler(CPU::TrapFrame *Frame); -void MachineCheckExceptionHandler(CPU::TrapFrame *Frame); -void SIMDFloatingPointExceptionHandler(CPU::TrapFrame *Frame); -void VirtualizationExceptionHandler(CPU::TrapFrame *Frame); -void SecurityExceptionHandler(CPU::TrapFrame *Frame); -void UnknownExceptionHandler(CPU::TrapFrame *Frame); - -bool UserModeExceptionHandler(CPU::TrapFrame *Frame); - -#endif // !__FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__ +public: + CrashKeyboardDriver(); + ~CrashKeyboardDriver() {} +}; diff --git a/core/panic/ui.cpp b/core/panic/ui.cpp new file mode 100644 index 0000000..c33a5a0 --- /dev/null +++ b/core/panic/ui.cpp @@ -0,0 +1,920 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(a64) +#include "../../arch/amd64/cpu/gdt.hpp" +#include "../arch/amd64/cpu/apic.hpp" +#elif defined(a32) +#include "../../arch/i386/cpu/gdt.hpp" +#include "../arch/i386/cpu/apic.hpp" +#elif defined(aa64) +#endif + +#include "../../kernel.h" +#include "keyboard.hpp" + +extern void ExPrint(const char *Format, ...); +extern Video::Font *CrashFont; +extern void DiagnosticDataCollection(); +extern void InitFont(); + +struct StackFrame +{ + struct StackFrame *bp; + uintptr_t ip; +}; + +struct x86ExceptionName +{ + const char *Mnemonic; + const char *Name; + const char *Cause; +}; + +/* AMD64 Programmer's Manual Volume 2: 8.2 Vectors */ +x86ExceptionName x86Exceptions[] = { + /* 0*/ {"#DE", "Divide-by-Zero-Error", "DIV, IDIV, AAM instructions"}, + /* 1*/ {"#DB", "Debug", "Instruction accesses and data accesses"}, + /* 2*/ {"NMI", "Non-Maskable-Interrupt", "Non-maskable interrupt"}, + /* 3*/ {"#BP", "Breakpoint", "INT3 instruction"}, + /* 4*/ {"#OF", "Overflow", "INTO instruction"}, + /* 5*/ {"#BR", "Bound-Range", "BOUND instruction"}, + /* 6*/ {"#UD", "Invalid-Opcode", "Invalid instructions"}, + /* 7*/ {"#NM", "Device-Not-Available", "x87 instructions"}, + /* 8*/ {"#DF", "Double-Fault", "Exception during the handling of another exception or interrupt"}, + /* 9*/ {"#--", "Coprocessor-Segment-Overrun", "Unsupported (Reserved)"}, + /*10*/ {"#TS", "Invalid-TSS", "Task-state segment access and task switch"}, + /*11*/ {"#NP", "Segment-Not-Present", "Segment register loads"}, + /*12*/ {"#SS", "Stack", "SS register loads and stack references"}, + /*13*/ {"#GP", "General-Protection", "Memory accesses and protection checks"}, + /*14*/ {"#PF", "Page-Fault", "Memory accesses when paging enabled"}, + /*15*/ {"#r0", "Reserved", "Reserved"}, + /*16*/ {"#MF", "x87 Floating-Point Exception-Pending", "x87 floating-point instructions"}, + /*17*/ {"#AC", "Alignment-Check", "Misaligned memory accesses"}, + /*18*/ {"#MC", "Machine-Check", "Model specific"}, + /*19*/ {"#XF", "SIMD Floating-Point", "SSE floating-point instructions"}, + /*20*/ {"#VE", "Virtualization Exception", "Virtualization event"}, /* AMD says this is reserved */ + /*21*/ {"#CP", "Control-Protection Exception", "RET/IRET or other control transfer"}, + /*22*/ {"#r1", "Reserved", "Reserved"}, + /*23*/ {"#r2", "Reserved", "Reserved"}, + /*24*/ {"#r3", "Reserved", "Reserved"}, + /*25*/ {"#r4", "Reserved", "Reserved"}, + /*26*/ {"#r5", "Reserved", "Reserved"}, + /*27*/ {"#r6", "Reserved", "Reserved"}, + /*28*/ {"#HV", "Hypervisor Injection Exception", "Event injection"}, + /*29*/ {"#VC", "VMM Communication Exception", "Virtualization event"}, + /*30*/ {"#SX", "Security Exception", "Security-sensitive event in host"}, + /*31*/ {"#r7", "Reserved", "Reserved"}, +}; + +static const char *x86PageFaultDescriptions[9] = { + "Supervisor tried to read a non-present page entry\n", + "Supervisor tried to read a page and caused a protection fault\n", + "Supervisor tried to write to a non-present page entry\n", + "Supervisor tried to write a page and caused a protection fault\n", + "User tried to read a non-present page entry\n", + "User tried to read a page and caused a protection fault\n", + "User tried to write to a non-present page entry\n", + "User tried to write a page and caused a protection fault\n", + "One or more page directory entries contain reserved bits which are set to 1.\n"}; + +int ActiveScreen = 0; + +nsa const char *ExGetKSymbol(CPU::ExceptionFrame *Frame) +{ + if (Frame->rip < (uintptr_t)&_kernel_start && + Frame->rip > (uintptr_t)&_kernel_end) + return ""; + + if (KernelSymbolTable) +#if defined(a64) + return KernelSymbolTable->GetSymbol(Frame->rip); +#elif defined(a32) + return KernelSymbolTable->GetSymbol(Frame->eip); +#elif defined(aa64) + return KernelSymbolTable->GetSymbol(Frame->pc); +#endif + return ""; +} + +nsa char *TrimWhiteSpace(char *str) +{ + char *end; + while (*str == ' ') + str++; + if (*str == 0) + return str; + end = str + strlen(str) - 1; + while (end > str && *end == ' ') + end--; + *(end + 1) = 0; + return str; +} + +nsa void ExDumpData(void *Address, unsigned long Length) +{ + ExPrint("\eAAAAAA-------------------------------------------------------------------------\n"); + Display->UpdateBuffer(); + unsigned char *AddressChar = (unsigned char *)Address; + unsigned char Buffer[17]; + unsigned long Iterate; + for (Iterate = 0; Iterate < Length; Iterate++) + { + if ((Iterate % 16) == 0) + { + if (Iterate != 0) + ExPrint(" \e8A78FF%s\eAABBCC\n", Buffer); + ExPrint(" \e9E9E9E%04x\eAABBCC ", Iterate); + Display->UpdateBuffer(); + } + ExPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]); + if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e)) + Buffer[Iterate % 16] = '.'; + else + Buffer[Iterate % 16] = AddressChar[Iterate]; + Buffer[(Iterate % 16) + 1] = '\0'; + } + + while ((Iterate % 16) != 0) + { + ExPrint(" "); + Display->UpdateBuffer(); + Iterate++; + } + + ExPrint(" \e8A78FF%s\eAAAAAA\n", Buffer); + ExPrint("-------------------------------------------------------------------------\n\n."); + Display->UpdateBuffer(); +} + +nsa void DisplayTopOverlay() +{ + Video::Font *f = Display->GetCurrentFont(); + Video::FontInfo fi = f->GetInfo(); + + for (uint32_t i = 0; i < Display->GetWidth; i++) + { + for (uint32_t j = 0; j < fi.Height + 8; j++) + { + // uint32_t grayValue = 0x505050 - (j * 0x020202); + // Display->SetPixel(i, j, grayValue); + Display->SetPixel(i, j, 0x202020); + } + } + + for (uint32_t i = 0; i < Display->GetWidth; i++) + Display->SetPixel(i, fi.Height + 8, 0x404040); + + Display->SetBufferCursor(8, (fi.Height + 8) / 6); + + /* This wouldn't have enough space for a 640x480 screen */ + // ExPrint("%sMAIN %sDETAILS %sSTACK %sPROCESS \eAAAAAA| ", + // ActiveScreen == 0 ? "\e00AAFF" : "\eAAAAAA", + // ActiveScreen == 1 ? "\e00AAFF" : "\eAAAAAA", + // ActiveScreen == 2 ? "\e00AAFF" : "\eAAAAAA", + // ActiveScreen == 3 ? "\e00AAFF" : "\eAAAAAA"); + + ExPrint("%s %s %s %s \eAAAAAA| ", + ActiveScreen == 0 ? "\eAAAAAA" + "MAIN " + : "\e5A5A5A" + "M", + ActiveScreen == 1 ? "\eAAAAAA" + "DETAIL " + : "\e5A5A5A" + "D", + ActiveScreen == 2 ? "\eAAAAAA" + "STACK " + : "\e5A5A5A" + "S", + ActiveScreen == 3 ? "\eAAAAAA" + "PROCESS" + : "\e5A5A5A" + "P"); + + ExPrint("%s %s %s | ", KERNEL_NAME, KERNEL_ARCH, KERNEL_VERSION); + ExPrint("%ld | ", TO_MiB(KernelAllocator.GetFreeMemory())); + ExPrint("%s %s", CPU::Hypervisor(), CPU::Vendor()); + + Display->SetBufferCursor(0, fi.Height + 10); + + /* https://imgflip.com/i/77slbl */ + if ((Random::rand32() % 100) >= 98) + { + debug("Easter egg activated!"); + int BaseXOffset = Display->GetWidth - 14; + int BaseYOffset = 8; + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E); + + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E); + + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E); + + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF); + + Display->UpdateBuffer(); + } +} + +nsa void DisplayBottomOverlay() +{ + Video::Font *f = Display->GetCurrentFont(); + Video::FontInfo fi = f->GetInfo(); + + for (uint32_t i = 0; i < Display->GetWidth; i++) + for (uint32_t j = Display->GetHeight - fi.Height - 8; j < Display->GetHeight; j++) + Display->SetPixel(i, j, 0x202020); + + for (uint32_t i = 0; i < Display->GetWidth; i++) + Display->SetPixel(i, Display->GetHeight - fi.Height - 8, 0x404040); + + Display->SetBufferCursor(8, Display->GetHeight - fi.Height - 4); + ExPrint("\eAAAAAA> \eFAFAFA"); +} + +nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame) +{ + ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n"); + + ExPrint("\nError: %s (%s 0x%x)\n", +#if defined(a86) + x86Exceptions[Frame->InterruptNumber].Name, + x86Exceptions[Frame->InterruptNumber].Mnemonic, +#elif defined(aa64) +#error "AA64 not implemented" +#endif + Frame->InterruptNumber); +#if defined(a86) + ExPrint("Cause: %s\n", x86Exceptions[Frame->InterruptNumber].Cause); +#endif + ExPrint("Exception occurred in function %s (%#lx)\n", + ExGetKSymbol(Frame), +#if defined(a64) + Frame->rip); +#elif defined(a32) + Frame->eip); +#elif defined(aa64) + Frame->pc); +#endif + + CPUData *core = GetCurrentCPU(); + if (TaskManager) + { + ExPrint("Core: %d / pid: %d / tid: %d\n", core->ID, + core->CurrentProcess->ID, core->CurrentThread->ID); + } + else if (core->IsActive) + ExPrint("Core: %d\n", core->ID); + + ExPrint("\nWhat to do:\n"); + ExPrint(" 1. Restart your device and see if the problem persists.\n"); + ExPrint(" 2. Remove any newly installed hardware.\n"); + ExPrint(" 3. Check for any available updates for your operating system.\n"); + ExPrint(" 4. Uninstall any recently installed drivers or software.\n"); + ExPrint(" If none of the above steps resolve the issue, create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n"); + + ExPrint("\nUse command 'diag' to create a diagnostic report.\n"); +} + +nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame) +{ + ExPrint("\n\eFAFAFAException Frame:\n"); + ExPrint(" General Purpose Registers:\n\eAAAAAA"); + ExPrint(" RAX: %#lx RBX: %#lx RCX: %#lx RDX: %#lx\n", + Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + ExPrint(" RSI: %#lx RDI: %#lx R8: %#lx R9: %#lx\n", + Frame->rsi, Frame->rdi, Frame->r8, Frame->r9); + ExPrint(" R10: %#lx R11: %#lx R12: %#lx R13: %#lx\n", + Frame->r10, Frame->r11, Frame->r12, Frame->r13); + ExPrint(" R14: %#lx R15: %#lx\n", Frame->r14, Frame->r15); + + ExPrint("\eFAFAFA Control Registers:\n\eAAAAAA"); + ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n", + Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4); + ExPrint(" CR8: %#lx\n", Frame->cr8); + + ExPrint("\eFAFAFA Segment Registers:\n\eAAAAAA"); + ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n", + Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs); + + ExPrint("\eFAFAFA Debug Registers:\n\eAAAAAA"); + ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n", + Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3); + ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7); + + ExPrint("\eFAFAFA Other:\n\eAAAAAA"); + ExPrint(" INT: %#lx ERR: %#lx RIP: %#lx RFLAGS: %#lx\n", + Frame->InterruptNumber, Frame->ErrorCode, + Frame->rip, Frame->rflags.raw); + ExPrint(" RSP: %#lx RBP: %#lx\n", + Frame->rsp, Frame->rbp); + + ExPrint("\eFAFAFAException Details:\n"); + switch (Frame->InterruptNumber) + { + case CPU::x86::PageFault: + { + CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode}; + ExPrint("P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n", + pfCode.P, pfCode.W, pfCode.U, pfCode.R, + pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX); + + ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]); + if (Frame->ErrorCode & 0x8) + ExPrint("%s", x86PageFaultDescriptions[8]); + break; + } + case CPU::x86::StackSegmentFault: + case CPU::x86::GeneralProtectionFault: + { + CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode}; + ExPrint("Kernel performed an illegal operation.\n"); + ExPrint("External: %d\n", sCode.External); + ExPrint("Table: %d\n", sCode.Table); + ExPrint("Index: %#x\n", sCode.Idx); + break; + } + default: + ExPrint("No additional information available for this exception.\n"); + break; + } + + if (!TaskManager) + return; + + CPUData *core = GetCurrentCPU(); + Tasking::PCB *proc = core->CurrentProcess.load(); + Tasking::TCB *thread = core->CurrentThread.load(); + ExPrint("Exception in %s process %s(%d) thread %s(%d)\n", + proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel", + proc->Name, proc->ID, + thread->Name, thread->ID); +} + +nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame) +{ + Memory::Virtual vmm; + struct StackFrame *sf; +#if defined(a64) + sf = (struct StackFrame *)Frame->rbp; +#elif defined(a32) + sf = (struct StackFrame *)Frame->ebp; +#endif + + ExPrint("\n\eFAFAFAStack trace (%#lx):\n", sf); + + if (!vmm.Check(sf)) + { + void *ptr = ((Memory::PageTable *)Frame->cr3)->Get(sf); + debug("Virtual pointer %#lx -> %#lx", sf, ptr); + if (vmm.Check(ptr)) + sf = (struct StackFrame *)ptr; + else + { + ExPrint("\eFF0000< No stack trace available. >\n"); + return; + } + } + + /* FIXME: Get symbol offset more efficiently */ + + uintptr_t fIP; +#if defined(a64) + fIP = Frame->rip; +#elif defined(a32) + fIP = Frame->eip; +#elif defined(aa64) + fIP = Frame->pc; +#endif + + ExPrint("\eAAAAAA%p", (void *)fIP); + ExPrint("\e5A5A5A in "); + if ((fIP >= (uintptr_t)&_kernel_start && + fIP <= (uintptr_t)&_kernel_end)) + { + const char *sym = KernelSymbolTable->GetSymbol(fIP); + ssize_t offset = fIP - KernelSymbolTable->GetSymbol(sym); + if (offset < 0) + offset = -offset; + + ExPrint("\eFAFAFA%s\e5A5A5A+%#lx \eFFAAAA<- Exception\n", + sym, offset); + } + else + ExPrint("\eFF5555???\n"); + + if (!sf || !sf->ip || !sf->bp) + { + ExPrint("\n\eFF0000< No stack trace available. >\n"); + return; + } + + for (int i = 0; i < 16; ++i) + { + if (!sf->ip) + break; + + ExPrint("\eAAAAAA%p", (void *)sf->ip); + ExPrint("\e5A5A5A in "); + if ((sf->ip >= (uintptr_t)&_kernel_start && + sf->ip <= (uintptr_t)&_kernel_end)) + { + const char *sym = KernelSymbolTable->GetSymbol(sf->ip); + ssize_t offset = sf->ip - KernelSymbolTable->GetSymbol(sym); + if (offset < 0) + offset = -offset; + + ExPrint("\eFAFAFA%s\e5A5A5A+%#lx\n", sym, offset); + } + else + ExPrint("\eFF5555???\n"); + + if (!vmm.Check(sf->bp)) + return; + sf = sf->bp; + } +} + +nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame) +{ + const char *StatusColor[] = { + "FF0000", // Unknown + "AAFF00", // Ready + "00AA00", // Running + "FFAA00", // Sleeping + "FFAA00", // Blocked + "FFAA00", // Stopped + "FFAA00", // Waiting + + "FF00FF", // Core dump + "FF0088", // Zombie + "FF0000", // Terminated + }; + + const char *StatusString[] = { + "UNK", // Unknown + "RDY", // Ready + "RUN", // Running + "SLP", // Sleeping + "BLK", // Blocked + "STP", // Stopped + "WTG", // Waiting + + "CRD", // Core dump + "ZMB", // Zombie + "TRM", // Terminated + }; + + if (!TaskManager) + { + ExPrint("\eFF5555Scheduler is not initialized\n"); + return; + } + + size_t textLimit = 32; + if (Display->GetWidth > 800 && Display->GetHeight > 600) + textLimit = 128; + + std::list Plist = TaskManager->GetProcessList(); + + ExPrint("\n\eFAFAFAProcess list (%ld):\n", Plist.size()); + bool pRdy = false; + foreach (auto Process in Plist) + { + if (Process->State == Tasking::Ready) + { + pRdy = true; + debug("Ignoring ready process %s(%d)", + Process->Name, Process->ID); + continue; + } + + ExPrint("\eAAAAAA-> \eFAFAFA%.*s%s\e8A8A8A(%ld) \e%s%s\n", + textLimit, Process->Name, + strlen(Process->Name) > textLimit ? "\e8A8A8A..." : "", + Process->ID, StatusColor[Process->State.load()], + StatusString[Process->State.load()]); + + bool tRdy = false; + foreach (auto Thread in Process->Threads) + { + if (Thread->State == Tasking::Ready) + { + tRdy = true; + debug("Ignoring ready thread %s(%d)", + Thread->Name, Thread->ID); + continue; + } + + ExPrint("\eAAAAAA -> \eFAFAFA%.*s%s\e8A8A8A(%ld) \e%s%s\n", + textLimit, Thread->Name, + strlen(Thread->Name) > textLimit ? "\e8A8A8A..." : "", + Thread->ID, StatusColor[Thread->State.load()], + StatusString[Thread->State.load()]); + } + if (tRdy) + ExPrint("\eAAAAAA%s -> \e8A8A8A...\n"); + } + if (pRdy) + ExPrint("\eAAAAAA-> \e8A8A8A...\n"); + + ExPrint("\e5A5A5ANote: Some processes may not be displayed.\n"); +} + +CPU::ExceptionFrame *ExFrame; +nsa void DisplayCrashScreen(CPU::ExceptionFrame *Frame) +{ + ExFrame = Frame; + + /* TODO */ + // void *BufferBeforeUpdate = KernelAllocator.RequestPages(TO_PAGES(Display->GetSize)); + // if (BufferBeforeUpdate) + // memcpy(BufferBeforeUpdate, Display->GetBuffer, Display->GetSize); + + Display->ClearBuffer(); + if (Config.InterruptsOnCrash == false) + { + Display->SetBufferCursor(0, 0); + DisplayMainScreen(Frame); + Display->UpdateBuffer(); + CPU::Stop(); + } + + DisplayTopOverlay(); + + DisplayMainScreen(Frame); + + Display->UpdateBuffer(); + new CrashKeyboardDriver; + + DisplayBottomOverlay(); + Display->UpdateBuffer(); + CPU::Halt(true); +} + +nsa void DisplayStackSmashing() +{ + InitFont(); + Display->ClearBuffer(); + DisplayTopOverlay(); + + ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n"); + ExPrint("\nError: Stack Smashing In Kernel Mode\n"); + + CPUData *core = GetCurrentCPU(); + if (TaskManager) + { + ExPrint("Core: %d / pid: %d / tid: %d\n", core->ID, + core->CurrentProcess->ID, core->CurrentThread->ID); + } + else if (core->IsActive) + ExPrint("Core: %d\n", core->ID); + + ExPrint("\nWhat to do:\n"); + ExPrint(" This is a kernel bug.\n"); + ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n"); + + Display->UpdateBuffer(); + + /* TODO: Add additional info */ +} + +nsa void DisplayBufferOverflow() +{ + InitFont(); + Display->ClearBuffer(); + DisplayTopOverlay(); + + ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n"); + ExPrint("\nError: Buffer Overflow In Kernel Mode\n"); + + CPUData *core = GetCurrentCPU(); + if (TaskManager) + { + ExPrint("Core: %d / pid: %d / tid: %d\n", core->ID, + core->CurrentProcess->ID, core->CurrentThread->ID); + } + else if (core->IsActive) + ExPrint("Core: %d\n", core->ID); + + ExPrint("\nWhat to do:\n"); + ExPrint(" This is a kernel bug.\n"); + ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n"); + + Display->UpdateBuffer(); + + /* TODO: Add additional info */ +} + +EXTERNC nsa __noreturn void DisplayAssertionFailed(const char *File, int Line, + const char *Expression) +{ + InitFont(); + Display->ClearBuffer(); + DisplayTopOverlay(); + + ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n"); + ExPrint("\nError: Assertion Failed\n"); + ExPrint("In file \"%s\" at line %d, \"%s\" failed\n", + File, Line, Expression); + + CPUData *core = GetCurrentCPU(); + if (TaskManager) + { + ExPrint("Core: %d / pid: %d / tid: %d\n", core->ID, + core->CurrentProcess->ID, core->CurrentThread->ID); + } + else if (core->IsActive) + ExPrint("Core: %d\n", core->ID); + + ExPrint("\nWhat to do:\n"); + ExPrint(" This is a kernel bug.\n"); + ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n"); + + Display->UpdateBuffer(); + CPU::Stop(); +} + +nsa void ArrowInput(uint8_t key) +{ + switch (key) + { + case KEY_D_RIGHT: + if (ActiveScreen < 3) + ActiveScreen++; + else + return; + break; + case KEY_D_LEFT: + if (ActiveScreen > 0) + ActiveScreen--; + else + return; + break; + case KEY_D_DOWN: + case KEY_D_UP: + default: + return; + } + + Display->ClearBuffer(); + DisplayTopOverlay(); + + switch (ActiveScreen) + { + case 0: + DisplayMainScreen(ExFrame); + break; + case 1: + DisplayDetailsScreen(ExFrame); + break; + case 2: + DisplayStackScreen(ExFrame); + break; + case 3: + DisplayProcessScreen(ExFrame); + break; + default: + break; + } + + DisplayBottomOverlay(); + Display->UpdateBuffer(); +} + +nsa void UserInput(char *Input) +{ + debug("User input: %s", Input); + Display->ClearBuffer(); + DisplayTopOverlay(); + + if (strcmp(Input, "help") == 0) + { + ExPrint("Commands:\n"); + ExPrint("\eAAAAAA help - Display this help message.\n"); + ExPrint("\eCACACA clear - Clear the screen.\n"); + ExPrint("\eAAAAAA exit - Shutdown the device.\n"); + ExPrint("\eCACACA reboot - Reboot the device.\n"); + ExPrint("\eAAAAAA bitmap - Display the kernel's bitmap.\n"); + ExPrint("\eCACACA mem - Display memory information.\n"); + ExPrint("\eAAAAAA dump [addr] [len] - Dump [len] bytes from [addr].\n"); + ExPrint("\eCACACA diag - Collect diagnostic information.\n"); + } + else if (strcmp(Input, "clear") == 0) + { + Display->ClearBuffer(); + DisplayTopOverlay(); + } + else if (strcmp(Input, "exit") == 0) + { + Display->ClearBuffer(); + + const char msg[] = "Shutting down..."; + size_t msgLen = strlen(msg); + size_t msgPixels = msgLen * CrashFont->GetInfo().Width; + uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2); + uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2); + Display->SetBufferCursor(x, y); + Display->PrintString("\eAAAAAA"); + Display->PrintString(msg, CrashFont); + + Display->UpdateBuffer(); + PowerManager->Shutdown(); + CPU::Stop(); + } + else if (strcmp(Input, "reboot") == 0) + { + Display->ClearBuffer(); + + const char msg[] = "Rebooting..."; + size_t msgLen = strlen(msg); + size_t msgPixels = msgLen * CrashFont->GetInfo().Width; + uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2); + uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2); + Display->SetBufferCursor(x, y); + Display->PrintString("\eAAAAAA"); + Display->PrintString(msg, CrashFont); + + Display->UpdateBuffer(); + PowerManager->Reboot(); + CPU::Stop(); + } + else if (strncmp(Input, "bitmap", 6) == 0) + { + Bitmap bm = KernelAllocator.GetPageBitmap(); + Video::Font *oldFont = CrashFont; + CrashFont = Display->GetDefaultFont(); + + ExPrint("\n\eAAAAAA[0%%] %08ld: ", 0); + for (size_t i = 0; i < bm.Size; i++) + { + if (bm.Get(i)) + Display->PrintString("\eFF0000"); + else + Display->PrintString("\e00FF00"); + Display->Print('0'); + if (i % 128 == 127) + { + short Percentage = s_cst(short, (i * 100) / bm.Size); + ExPrint("\n\eAAAAAA[%03ld%%] %08ld: ", Percentage, i); + Display->UpdateBuffer(); + } + } + ExPrint("\n\eAAAAAA--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size); + DisplayTopOverlay(); + Display->UpdateBuffer(); + CrashFont = oldFont; + } + else if (strcmp(Input, "mem") == 0) + { + uint64_t Total = KernelAllocator.GetTotalMemory(); + uint64_t Used = KernelAllocator.GetUsedMemory(); + uint64_t Free = KernelAllocator.GetFreeMemory(); + uint64_t Reserved = KernelAllocator.GetReservedMemory(); + + ExPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved); + int Progress = s_cst(int, (Used * 100) / Total); + int ReservedProgress = s_cst(int, (Reserved * 100) / Total); + ExPrint("\e22AA44%3d%% \eCCCCCC[", Progress); + for (int i = 0; i < Progress; i++) + ExPrint("\eFF0000|"); + for (int i = 0; i < 100 - Progress; i++) + ExPrint("\e00FF00|"); + for (int i = 0; i < ReservedProgress; i++) + ExPrint("\eFF00FF|"); + ExPrint("\eCCCCCC]\eAAAAAA\n"); + } + else if (strncmp(Input, "dump", 4) == 0) + { + char *arg = TrimWhiteSpace(Input + 4); + char *addr = strtok(arg, " "); + char *len = strtok(NULL, " "); + if (addr == NULL || len == NULL) + { + ExPrint("\eFF0000Invalid arguments\n"); + goto End; + } + + uintptr_t Address = strtoul(addr, NULL, 16); + size_t Length = strtoul(len, NULL, 10); + + uintptr_t AlignedAddress = ROUND_DOWN(Address, PAGE_SIZE); + bool IsRangeValid = true; + { + Memory::Virtual vmm; + for (uintptr_t adr = AlignedAddress; + adr < Address + Length; + adr += PAGE_SIZE) + { + if (!vmm.Check((void *)adr)) + { + ExPrint("\eFFA500Address %#lx is not mapped\n", adr); + IsRangeValid = false; + } + } + } + + if (IsRangeValid) + { + debug("Dumping %ld bytes from %#lx\n", Length, Address); + + Video::Font *oldFont = CrashFont; + CrashFont = Display->GetDefaultFont(); + ExDumpData((void *)Address, (unsigned long)Length); + CrashFont = oldFont; + } + } + else if (strcmp(Input, "diag") == 0) + { + DiagnosticDataCollection(); + } +#ifdef DEBUG + else if (strcmp(Input, "pt") == 0) + { + /* Helpful for qemu "info tlb" command */ + CPU::PageTable((void *)ExFrame->cr3); + ExPrint("Here be dragons\n"); + } +#endif // DEBUG + else if (strlen(Input) > 0) + ExPrint("Unknown command: %s", Input); + else + ExPrint("Use the 'help' command to display a list of available commands."); + +End: + DisplayBottomOverlay(); + Display->UpdateBuffer(); +} diff --git a/core/panic/user.cpp b/core/panic/user.cpp new file mode 100644 index 0000000..f27ffd5 --- /dev/null +++ b/core/panic/user.cpp @@ -0,0 +1,225 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include +#include +#include + +#if defined(a64) +#include "../../arch/amd64/cpu/gdt.hpp" +#elif defined(a32) +#elif defined(aa64) +#endif + +#include "../../kernel.h" + +#ifdef DEBUG +nsa void dbgPrint(CPU::ExceptionFrame *Frame) +{ +#if defined(a64) + CPU::x64::CR0 cr0 = CPU::x64::readcr0(); + CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = Frame->cr2}; + 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); + uintptr_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); +#elif defined(a32) + CPU::x32::CR0 cr0 = CPU::x32::readcr0(); + CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = CrashHandler::PageFaultAddress}; + CPU::x32::CR3 cr3 = CPU::x32::readcr3(); + CPU::x32::CR4 cr4 = CPU::x32::readcr4(); + CPU::x32::CR8 cr8 = CPU::x32::readcr8(); + uintptr_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); +#elif defined(aa64) +#endif + +#if defined(a64) + debug("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, ds); + debug("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", Frame->r8, Frame->r9, Frame->r10, Frame->r11); + debug("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", Frame->r12, Frame->r13, Frame->r14, Frame->r15); + debug("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + debug("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + debug("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw); +#elif defined(a32) + debug("FS=%#x GS=%#x CS=%#x DS=%#x", + CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE), + Frame->cs, ds); + debug("EAX=%#x EBX=%#x ECX=%#x EDX=%#x", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx); + debug("ESI=%#x EDI=%#x EBP=%#x ESP=%#x", Frame->esi, Frame->edi, Frame->ebp, Frame->esp); + debug("EIP=%#x EFL=%#x INT=%#x ERR=%#x", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode); +#elif defined(aa64) +#endif + +#if defined(a86) + debug("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); + + debug("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", + 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); + + debug("CR2: PFLA: %#lx", + cr2.PFLA); + + debug("CR3: PWT:%s PCD:%s PDBR:%#llx", + cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); +#endif // defined(a86) + +#if defined(a64) + debug("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x", + 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); +#elif defined(a32) + debug("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x", + 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); +#endif + +#if defined(a86) + debug("CR8: TPL:%d", cr8.TPL); +#endif // defined(a86) + +#if defined(a64) + debug("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x", + 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.AlwaysOne, + Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); +#elif defined(a32) + debug("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x", + Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False", + Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False", + Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False", + Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False", + Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne, + Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2); +#elif defined(aa64) +#endif + +#if defined(a64) + debug("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", + 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); +#endif +} +#endif + +nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame) +{ + CPUData *core = GetCurrentCPU(); + Tasking::PCB *proc = core->CurrentProcess; + Tasking::TCB *thread = core->CurrentThread; + debug("Current process %s(%d) and thread %s(%d)", + proc->Name, proc->ID, thread->Name, thread->ID); + thread->SetState(Tasking::Waiting); + +#ifdef DEBUG + dbgPrint(Frame); +#endif + + switch (Frame->InterruptNumber) + { + case CPU::x86::PageFault: + { + bool Handled = proc->vma->HandleCoW(Frame->cr2); + if (!Handled) + Handled = thread->Stack->Expand(Frame->cr2); + + if (Handled) + { + debug("Page fault handled"); + thread->SetState(Tasking::Ready); + return true; + } + + proc->Signals->SendSignal(SIGSEGV, + {Tasking::KILL_CRASH}); + break; + } + case CPU::x86::Debug: + case CPU::x86::Breakpoint: + { + proc->Signals->SendSignal(SIGTRAP, + {Tasking::KILL_CRASH}); + break; + } + case CPU::x86::DivideByZero: + case CPU::x86::Overflow: + case CPU::x86::BoundRange: + case CPU::x86::x87FloatingPoint: + case CPU::x86::SIMDFloatingPoint: + { + proc->Signals->SendSignal(SIGFPE, + {Tasking::KILL_CRASH}); + break; + } + case CPU::x86::InvalidOpcode: + case CPU::x86::GeneralProtectionFault: + { + proc->Signals->SendSignal(SIGILL, + {Tasking::KILL_CRASH}); + break; + } + case CPU::x86::DeviceNotAvailable: + { + proc->Signals->SendSignal(SIGBUS, + {Tasking::KILL_CRASH}); + break; + } + case CPU::x86::NonMaskableInterrupt: + case CPU::x86::DoubleFault: + case CPU::x86::CoprocessorSegmentOverrun: + case CPU::x86::InvalidTSS: + case CPU::x86::SegmentNotPresent: + case CPU::x86::StackSegmentFault: + case CPU::x86::AlignmentCheck: + case CPU::x86::MachineCheck: + case CPU::x86::Virtualization: + case CPU::x86::Security: + default: + { + error("Unhandled exception %d on CPU %d", + Frame->InterruptNumber, core->ID); + break; + } + } + + error("User mode exception handler failed"); + return false; +} diff --git a/core/stack_check.cpp b/core/stack_check.cpp index a58bed7..030d940 100644 --- a/core/stack_check.cpp +++ b/core/stack_check.cpp @@ -21,9 +21,12 @@ #include "../kernel.h" -/* EXTERNC */ __weak uintptr_t __stack_chk_guard = 0; +extern __noreturn void HandleStackSmashing(); +extern __noreturn void HandleBufferOverflow(); -EXTERNC __weak __no_stack_protector uintptr_t __stack_chk_guard_init(void) +/* EXTERNC */ uintptr_t __stack_chk_guard = 0; + +EXTERNC __no_stack_protector uintptr_t __stack_chk_guard_init(void) { int MaxRetries = 0; #if UINTPTR_MAX == UINT32_MAX @@ -52,55 +55,26 @@ EXTERNC __constructor __no_stack_protector void __guard_setup(void) debug("Stack guard value: %ld", __stack_chk_guard); } -EXTERNC __weak __noreturn __no_stack_protector void __stack_chk_fail(void) +EXTERNC __noreturn __no_stack_protector void __stack_chk_fail(void) { - TaskingPanic(); - for (short i = 0; i < 10; i++) - error("Stack smashing detected!"); - debug("Current stack check guard value: %#lx", __stack_chk_guard); - KPrint("\eFF0000Stack smashing detected!"); - void *Stack = nullptr; -#if defined(a86) - #if defined(a64) asmv("movq %%rsp, %0" : "=r"(Stack)); #elif defined(a32) asmv("movl %%esp, %0" : "=r"(Stack)); -#endif - #elif defined(aa64) - asmv("mov %%sp, %0" : "=r"(Stack)); - #endif error("Stack address: %#lx", Stack); - if (DebuggerIsAttached) -#ifdef a86 - asmv("int $0x3"); -#elif defined(aa64) - asmv("brk #0"); -#endif - - CPU::Stop(); + HandleStackSmashing(); } // https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c -EXTERNC __weak __noreturn __no_stack_protector void __chk_fail(void) +EXTERNC __noreturn nsa void __chk_fail(void) { - TaskingPanic(); - for (short i = 0; i < 10; i++) - error("Buffer overflow detected!"); - KPrint("\eFF0000Buffer overflow detected!"); - -#if defined(a86) - while (1) - asmv("cli; hlt"); -#elif defined(aa64) - asmv("wfe"); -#endif + HandleBufferOverflow(); } diff --git a/include/ints.hpp b/include/ints.hpp index 6fde08c..21acd24 100644 --- a/include/ints.hpp +++ b/include/ints.hpp @@ -38,7 +38,6 @@ namespace Interrupts /* APIC::Timer */ extern void *apicTimer[255]; // MAX_CPU #elif defined(aa64) #endif - extern void *InterruptFrames[INT_FRAMES_MAX]; void Initialize(int Core); void Enable(int Core); diff --git a/include_std/assert.h b/include_std/assert.h index 6270014..619dd49 100644 --- a/include_std/assert.h +++ b/include_std/assert.h @@ -20,15 +20,18 @@ #include -#define assert(x) \ - do \ - { \ - if (__builtin_expect(!!(!(x)), 0)) \ - { \ - error("Assertion failed! [%s]", #x); \ - int3; \ - __builtin_unreachable(); \ - } \ +EXTERNC void __attribute__((noreturn)) DisplayAssertionFailed(const char *File, int Line, + const char *Expression); + +#define assert(x) \ + do \ + { \ + if (__builtin_expect(!!(!(x)), 0)) \ + { \ + error("Assertion failed! [%s]", #x); \ + DisplayAssertionFailed(__FILE__, __LINE__, #x); \ + __builtin_unreachable(); \ + } \ } while (0) #define assert_allow_continue(x) \