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;
+private:
+ void PS2Wait(bool Read);
+ void OnInterruptReceived(CPU::TrapFrame *Frame);
- class CrashKeyboardDriver : public Interrupts::Handler
- {
- private:
- void PS2Wait(bool Read);
- void OnInterruptReceived(CPU::TrapFrame *Frame);
+ int BackSpaceLimit = 0;
+ char UserInputBuffer[256];
+ int TimeoutCallNumber = 0;
- public:
- CrashKeyboardDriver();
- ~CrashKeyboardDriver();
- };
-
- 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) \