feat(IDT): IDT and exception handling support

This commit is contained in:
Daniel Hammer
2025-03-08 10:40:12 +01:00
parent 3656df42bc
commit 942adef65f
9 changed files with 245 additions and 9 deletions
+34 -3
View File
@@ -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");
+1 -1
View File
@@ -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);
+7
View File
@@ -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);
+1
View File
@@ -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);
+129
View File
@@ -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";
}
};
+27
View File
@@ -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();
};
+1 -1
View File
@@ -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;
+34 -3
View File
@@ -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
View File
@@ -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();
}