feat(IDT): IDT and exception handling support
This commit is contained in:
@@ -1,9 +1,40 @@
|
||||
#include "Panic.hpp"
|
||||
|
||||
void Panic(const char *meditationString, System::Registers) {
|
||||
kerr << "=========== Kernel panic ===========" << Kt::newline;
|
||||
kerr << meditationString << Kt::newline;
|
||||
void Panic(const char *meditationString, System::PanicFrame* frame) {
|
||||
kerr << "\nGuru Meditation" << "\n" << "\n";
|
||||
|
||||
kerr << "\t" << "MeditationString: " << meditationString << Kt::newline;
|
||||
|
||||
#if defined (__x86_64__)
|
||||
if (frame != nullptr) {
|
||||
if (frame->InterruptVector == 0xE) { // In case of #PF the CPU pushes some other data to the frame
|
||||
auto pf_frame = (System::PageFaultPanicFrame*)frame;
|
||||
frame = (System::PanicFrame*)&pf_frame->IP;
|
||||
|
||||
kerr << "\t" << "InterruptVector: " << "0x" << base::hex << 0xE << "\n";
|
||||
|
||||
/* Page fault error details */
|
||||
kerr << "\t" << "PageFaultPresent: " << base::dec << pf_frame->PageFaultError.Present << "\n";
|
||||
kerr << "\t" << "PageFaultWrite: " << base::dec << pf_frame->PageFaultError.Write << "\n";
|
||||
kerr << "\t" << "PageFaultUser: " << base::dec << pf_frame->PageFaultError.User << "\n";
|
||||
kerr << "\t" << "PageFaultReservedWrite: " << base::dec << pf_frame->PageFaultError.ReservedWrite << "\n";
|
||||
kerr << "\t" << "PageFaultInstructionFetch: " << base::dec << pf_frame->PageFaultError.InstructionFetch << "\n";
|
||||
kerr << "\t" << "PageFaultProtectionKey: " << base::dec << pf_frame->PageFaultError.ProtectionKey << "\n";
|
||||
kerr << "\t" << "PageFaultShadowStack: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n";
|
||||
kerr << "\t" << "PageFaultSGX: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
kerr << "\t" << "InterruptVector: " << "0x" << base::hex << frame->InterruptVector << "\n";
|
||||
}
|
||||
|
||||
kerr << "\t" << "InstructionPointer: " << "0x" << base::hex << frame->IP << "\n";
|
||||
kerr << "\t" << "CodeSegment: " << "0x" << base::hex << frame->CS << "\n";
|
||||
kerr << "\t" << "Flags: " << "0x" << base::hex << frame->Flags << "\n";
|
||||
kerr << "\t" << "StackPointer: " << "0x" << base::hex << frame->SP << "\n";
|
||||
kerr << "\t" << "StackSegment: " << "0x" << base::hex << frame->SS << "\n";
|
||||
}
|
||||
#endif
|
||||
while (true) {
|
||||
#if defined (__x86_64__)
|
||||
asm ("cli");
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
#include <Platform/Registers.hpp>
|
||||
#include <Terminal/terminal.hpp>
|
||||
|
||||
void Panic(const char *meditationString, System::Registers registers);
|
||||
void Panic(const char *meditationString, System::PanicFrame* frame);
|
||||
@@ -50,6 +50,13 @@ kcp::cstringstream& kcp::cstringstream::operator<<(char* str) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
kcp::cstringstream& kcp::cstringstream::operator<<(const char* str) {
|
||||
*this << (char*)str;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
kcp::cstringstream& kcp::cstringstream::operator<<(int num) {
|
||||
char* out_str = Lib::int2basestr(num, current_base);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace kcp {
|
||||
|
||||
cstringstream& operator<<(char c);
|
||||
cstringstream& operator<<(char* str);
|
||||
cstringstream& operator<<(const char* str);
|
||||
|
||||
cstringstream& operator<<(int num);
|
||||
cstringstream& operator<<(uint32_t val);
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* IDT.cpp
|
||||
* Intel Interrupt Descriptor Table implementation
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*/
|
||||
|
||||
#include "IDT.hpp"
|
||||
|
||||
#include <Memory/Heap.hpp>
|
||||
#include <Common/Panic.hpp>
|
||||
#include <Platform/Registers.hpp>
|
||||
#include <CppLib/Stream.hpp>
|
||||
|
||||
namespace Hal {
|
||||
constexpr auto InterruptGate = 0x8E;
|
||||
constexpr auto TrapGate = 0x8F;
|
||||
|
||||
InterruptDescriptor* IDT;
|
||||
IDTRStruct IDTR{};
|
||||
|
||||
const char* ExceptionStrings[] = {
|
||||
"Division Error",
|
||||
"Debug",
|
||||
"Non-Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Overflow",
|
||||
"Bound Rage Exceeded",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Invalid TSS",
|
||||
"Segment Not Present",
|
||||
"Stack-Segment Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Reserved",
|
||||
"x87 Floating-Point Exception",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"SMID Floating-Point Exception",
|
||||
"Virtualization Exception",
|
||||
"Control Protection Exception",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Hypervisor Injection Exception",
|
||||
"VMM Communication Exception",
|
||||
"Security Exception",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
template<size_t i>
|
||||
__attribute__((interrupt)) void ExceptionHandler(System::PanicFrame* frame)
|
||||
{
|
||||
kcp::cstringstream stream;
|
||||
stream << "Caught " << base::hex << "0x" << i << " " << ExceptionStrings[i] << " in kernel";
|
||||
|
||||
frame->InterruptVector = i;
|
||||
|
||||
Panic(stream.cstr(), frame);
|
||||
}
|
||||
|
||||
void LoadIDT(IDTRStruct& idtr) {
|
||||
asm("lidt %0" : : "m"(idtr));
|
||||
}
|
||||
|
||||
InterruptDescriptor* GetInterruptDescriptor(size_t index) {
|
||||
InterruptDescriptor* descriptor = (InterruptDescriptor*)(IDTR.Base + index * sizeof(InterruptDescriptor));
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
uint64_t GetHandlerAddress(InterruptDescriptor* descriptor) {
|
||||
uint64_t result{};
|
||||
|
||||
result |= (uint64_t)descriptor->Offset1;
|
||||
result |= (uint64_t)descriptor->Offset2 << 16;
|
||||
result |= (uint64_t)descriptor->Offset3 << 32;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IDTEncodeInterrupt(size_t i, void* handler, uint8_t type_attr) {
|
||||
uint64_t offset = (uint64_t)handler;
|
||||
auto ptr = GetInterruptDescriptor(i);
|
||||
|
||||
*ptr = InterruptDescriptor {
|
||||
.Offset1 = (uint16_t)(offset & 0x000000000000ffff),
|
||||
|
||||
.Selector = 0x08,
|
||||
.IST = 0x00,
|
||||
.TypeAttributes = type_attr,
|
||||
|
||||
.Offset2 = (uint16_t)((offset & 0x00000000ffff0000) >> 16),
|
||||
.Offset3 = (uint32_t)((offset & 0xffffffff00000000) >> 32),
|
||||
|
||||
.Zero = 0x00
|
||||
};
|
||||
}
|
||||
|
||||
template<int I, int N>
|
||||
struct SetHandler {
|
||||
static void run() {
|
||||
IDTEncodeInterrupt(I, (void*)&ExceptionHandler<I>, TrapGate);
|
||||
SetHandler<I+1,N>::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct SetHandler<N,N> {static void run() {}};
|
||||
|
||||
void IDTInitialize() {
|
||||
IDT = (InterruptDescriptor*)Memory::g_heap->Request(4096);
|
||||
IDTR.Limit = 0x0FF;
|
||||
IDTR.Base = (uint64_t)&IDT;
|
||||
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
SetHandler<0, 31>::run();
|
||||
}
|
||||
|
||||
kout << "[Hal] Created exception interrupt vectors" << "\n";
|
||||
|
||||
LoadIDT(IDTR);
|
||||
|
||||
kout << "[Hal] Loaded new IDT" << "\n";
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* IDT.hpp
|
||||
* Intel Interrupt Descriptor Table implementation
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Hal {
|
||||
struct InterruptDescriptor {
|
||||
uint16_t Offset1;
|
||||
uint16_t Selector;
|
||||
uint8_t IST;
|
||||
uint8_t TypeAttributes;
|
||||
uint16_t Offset2;
|
||||
uint32_t Offset3;
|
||||
uint32_t Zero;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct IDTRStruct {
|
||||
uint16_t Limit;
|
||||
uint64_t Base;
|
||||
}__attribute__((packed));
|
||||
|
||||
void IDTInitialize();
|
||||
};
|
||||
@@ -30,7 +30,7 @@ namespace Memory {
|
||||
}
|
||||
|
||||
[[unlikely]] if (currentLargestSection.address == 0) {
|
||||
Panic("Couldn't find a usable memory section.", System::Registers{});
|
||||
Panic("Couldn't find a usable memory section.", nullptr);
|
||||
}
|
||||
|
||||
return currentLargestSection;
|
||||
|
||||
@@ -5,8 +5,39 @@ using namespace std;
|
||||
|
||||
#if defined (__x86_64__)
|
||||
namespace System {
|
||||
struct Registers {
|
||||
|
||||
};
|
||||
struct PanicFrame {
|
||||
uint64_t IP;
|
||||
uint64_t CS;
|
||||
uint64_t Flags;
|
||||
uint64_t SP;
|
||||
uint64_t SS;
|
||||
|
||||
uint8_t InterruptVector;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct PageFaultErrorCode {
|
||||
uint8_t Present : 1;
|
||||
uint8_t Write : 1;
|
||||
uint8_t User : 1;
|
||||
uint8_t ReservedWrite : 1;
|
||||
uint8_t InstructionFetch : 1;
|
||||
uint8_t ProtectionKey : 1;
|
||||
uint8_t ShadowStack : 1;
|
||||
uint8_t SGX : 1;
|
||||
|
||||
uint64_t Reserved : 56;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct PageFaultPanicFrame {
|
||||
PageFaultErrorCode PageFaultError;
|
||||
uint64_t IP;
|
||||
uint64_t CS;
|
||||
uint64_t Flags;
|
||||
uint64_t SP;
|
||||
uint64_t SS;
|
||||
|
||||
uint8_t InterruptVector;
|
||||
}__attribute__((packed));
|
||||
|
||||
};
|
||||
#endif
|
||||
+11
-1
@@ -22,6 +22,8 @@
|
||||
#include <Platform/Limine.hpp>
|
||||
#include <Platform/Util.hpp>
|
||||
|
||||
#include <Hal/IDT.hpp>
|
||||
|
||||
using namespace Kt;
|
||||
|
||||
namespace Memory {
|
||||
@@ -87,8 +89,16 @@ extern "C" void kmain() {
|
||||
|
||||
Memory::g_heap = &allocator;
|
||||
} else {
|
||||
Panic("Guru Meditation Error: System memory map missing!", System::Registers{});
|
||||
Panic("Guru Meditation Error: System memory map missing!", nullptr);
|
||||
}
|
||||
|
||||
#if defined (__x86_64__)
|
||||
Hal::IDTInitialize();
|
||||
#endif
|
||||
|
||||
int*x =(int*)0xffffffff;
|
||||
|
||||
*x=0;
|
||||
|
||||
hcf();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user