391 lines
11 KiB
C++

/*
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 <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#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
}
}