feat(IDT): IDT and exception handling support
This commit is contained in:
@@ -1,9 +1,40 @@
|
|||||||
#include "Panic.hpp"
|
#include "Panic.hpp"
|
||||||
|
|
||||||
void Panic(const char *meditationString, System::Registers) {
|
void Panic(const char *meditationString, System::PanicFrame* frame) {
|
||||||
kerr << "=========== Kernel panic ===========" << Kt::newline;
|
kerr << "\nGuru Meditation" << "\n" << "\n";
|
||||||
kerr << meditationString << Kt::newline;
|
|
||||||
|
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) {
|
while (true) {
|
||||||
#if defined (__x86_64__)
|
#if defined (__x86_64__)
|
||||||
asm ("cli");
|
asm ("cli");
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
#include <Platform/Registers.hpp>
|
#include <Platform/Registers.hpp>
|
||||||
#include <Terminal/terminal.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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kcp::cstringstream& kcp::cstringstream::operator<<(const char* str) {
|
||||||
|
*this << (char*)str;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
kcp::cstringstream& kcp::cstringstream::operator<<(int num) {
|
kcp::cstringstream& kcp::cstringstream::operator<<(int num) {
|
||||||
char* out_str = Lib::int2basestr(num, current_base);
|
char* out_str = Lib::int2basestr(num, current_base);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace kcp {
|
|||||||
|
|
||||||
cstringstream& operator<<(char c);
|
cstringstream& operator<<(char c);
|
||||||
cstringstream& operator<<(char* str);
|
cstringstream& operator<<(char* str);
|
||||||
|
cstringstream& operator<<(const char* str);
|
||||||
|
|
||||||
cstringstream& operator<<(int num);
|
cstringstream& operator<<(int num);
|
||||||
cstringstream& operator<<(uint32_t val);
|
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) {
|
[[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;
|
return currentLargestSection;
|
||||||
|
|||||||
@@ -5,8 +5,39 @@ using namespace std;
|
|||||||
|
|
||||||
#if defined (__x86_64__)
|
#if defined (__x86_64__)
|
||||||
namespace System {
|
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
|
#endif
|
||||||
+11
-1
@@ -22,6 +22,8 @@
|
|||||||
#include <Platform/Limine.hpp>
|
#include <Platform/Limine.hpp>
|
||||||
#include <Platform/Util.hpp>
|
#include <Platform/Util.hpp>
|
||||||
|
|
||||||
|
#include <Hal/IDT.hpp>
|
||||||
|
|
||||||
using namespace Kt;
|
using namespace Kt;
|
||||||
|
|
||||||
namespace Memory {
|
namespace Memory {
|
||||||
@@ -87,8 +89,16 @@ extern "C" void kmain() {
|
|||||||
|
|
||||||
Memory::g_heap = &allocator;
|
Memory::g_heap = &allocator;
|
||||||
} else {
|
} 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();
|
hcf();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user