summaryrefslogtreecommitdiffhomepage
path: root/Private/HALKit/AMD64/HalPlatformAMD64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Private/HALKit/AMD64/HalPlatformAMD64.cpp')
-rw-r--r--Private/HALKit/AMD64/HalPlatformAMD64.cpp66
1 files changed, 54 insertions, 12 deletions
diff --git a/Private/HALKit/AMD64/HalPlatformAMD64.cpp b/Private/HALKit/AMD64/HalPlatformAMD64.cpp
index b2e343b6..e9e7fb82 100644
--- a/Private/HALKit/AMD64/HalPlatformAMD64.cpp
+++ b/Private/HALKit/AMD64/HalPlatformAMD64.cpp
@@ -11,31 +11,73 @@
namespace HCore::HAL {
namespace Detail {
-struct RegisterAMD64 final {
+struct PACKED RegisterAMD64 final {
UIntPtr base;
UShort limit;
};
} // namespace Detail
void GDTLoader::Load(Register64 &gdt) {
- Detail::RegisterAMD64 *reg = new Detail::RegisterAMD64();
- MUST_PASS(reg);
+ Detail::RegisterAMD64 *gdtReg = new Detail::RegisterAMD64();
+ MUST_PASS(gdtReg);
- reg->base = gdt.Base;
- reg->limit = gdt.Limit;
+ gdtReg->base = gdt.Base;
+ gdtReg->limit = gdt.Limit;
- rt_cli();
- rt_load_gdt(reg);
- rt_sti();
+ rt_load_gdt((VoidPtr)gdtReg);
}
+namespace Detail::AMD64 {
+struct InterruptDescriptorAMD64 final {
+ UInt16 OffsetLow; // offset bits 0..15
+ UInt16 Selector; // a code segment selector in GDT or LDT
+ UInt8
+ Ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
+ UInt8 TypeAttributes; // gate type, dpl, and p fields
+ UInt16 OffsetMid; // offset bits 16..31
+ UInt32 OffsetHigh; // offset bits 32..63
+ UInt32 Zero; // reserved
+};
+} // namespace Detail::AMD64
+
+#define kInterruptGate 0xE
+#define kTrapGate 0xF
+#define kRing0 (0 << 5)
+#define kRing3 (3 << 5)
+#define kIdtPresent (1 << 7)
+#define kGdtSelector 0x08
+
+extern "C" HCore::UIntPtr rt_handle_interrupts(HCore::UIntPtr &rsp);
+
+static ALIGN(
+ 0x10) Detail::AMD64::InterruptDescriptorAMD64 kIdtRegs[kMaxSyscalls];
+static HAL::Register64 kRegIdt;
+
void IDTLoader::Load(Register64 &idt) {
- Detail::RegisterAMD64 *reg = new Detail::RegisterAMD64();
+ for (auto i = 0; i < 32; i++) {
+ kIdtRegs[i].Selector = kGdtSelector;
+ kIdtRegs[i].Ist = 0x00;
+ kIdtRegs[i].TypeAttributes = kInterruptGate | kRing0 | kIdtPresent;
+ kIdtRegs[i].OffsetLow = (((UIntPtr *)idt.Base)[i]) & 0xFFFF;
+ kIdtRegs[i].OffsetMid = (((UIntPtr *)idt.Base)[i] >> 16) & 0xFFFF;
+ kIdtRegs[i].OffsetHigh = (((UIntPtr *)idt.Base)[i] >> 32) & 0xFFFF;
+ kIdtRegs[i].Zero = 0;
+ }
+
+ kIdtRegs[0x21].Selector = kGdtSelector;
+ kIdtRegs[0x21].Ist = 0x00;
+ kIdtRegs[0x21].TypeAttributes = kInterruptGate | kRing3 | kIdtPresent;
+ kIdtRegs[0x21].OffsetLow = (((UIntPtr *)idt.Base)[0x21]) & 0xFFFF;
+ kIdtRegs[0x21].OffsetMid = (((UIntPtr *)idt.Base)[0x21] >> 16) & 0xFFFF;
+ kIdtRegs[0x21].OffsetHigh = (((UIntPtr *)idt.Base)[0x21] >> 32) & 0xFFFF;
+ kIdtRegs[0x21].Zero = 0;
+
+ kRegIdt.Base = (UIntPtr)kIdtRegs;
+ kRegIdt.Limit = sizeof(Detail::AMD64::InterruptDescriptorAMD64) * idt.Limit;
- reg->base = idt.Base;
- reg->limit = idt.Limit;
+ rt_load_idt((VoidPtr)&kRegIdt);
- rt_load_idt(reg);
+ kcout << "Krnl: IDT loaded\n";
}
void GDTLoader::Load(Ref<Register64> &gdt) { GDTLoader::Load(gdt.Leak()); }