mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
391 lines
11 KiB
C++
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
|
|
{
|
|
SafeFunction void DisplayMainScreen(CRData data)
|
|
{
|
|
CHArchTrapFrame *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
|
|
}
|
|
}
|