150 lines
2.5 KiB
C++

#include <luna/CString.h>
#include <luna/Check.h>
#include <luna/Types.h>
struct IDTEntry
{
u16 offset0;
u16 selector;
u8 ist;
u8 type_attr;
u16 offset1;
u32 offset2;
u32 ignore;
void set_offset(u64 offset);
u64 get_offset() const;
};
static_assert(sizeof(IDTEntry) == 16UL);
void IDTEntry::set_offset(u64 offset)
{
offset0 = (u16)(offset & 0x000000000000ffff);
offset1 = (u16)((offset & 0x00000000ffff0000) >> 16);
offset2 = (u32)((offset & 0xffffffff00000000) >> 32);
}
u64 IDTEntry::get_offset() const
{
u64 offset = 0;
offset |= (u64)offset0;
offset |= (u64)offset1 << 16;
offset |= (u64)offset2 << 32;
return offset;
}
static IDTEntry idt[256];
#define IDT_TA_InterruptGate 0b10001110
#define IDT_TA_UserCallableInterruptGate 0b11101110
#define IDT_TA_TrapGate 0b10001111
struct [[gnu::packed]] IDTR
{
u16 limit;
u64 offset;
};
static_assert(sizeof(IDTR) == 10UL);
static void idt_add_handler(short num, void* handler, u8 type_attr)
{
check(handler != nullptr);
expect(num < 256, "IDT can only hold up to 256 entries");
IDTEntry* const entry_for_handler = &idt[num];
entry_for_handler->selector = 0x08;
entry_for_handler->type_attr = type_attr;
entry_for_handler->set_offset((u64)handler);
}
#define INT(x) extern "C" void _isr##x()
#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate)
#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate)
#define SYS(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_UserCallableInterruptGate)
INT(0);
INT(1);
INT(2);
INT(3);
INT(4);
INT(5);
INT(6);
INT(7);
INT(8);
INT(10);
INT(11);
INT(12);
INT(13);
INT(14);
INT(16);
INT(17);
INT(18);
INT(19);
INT(20);
INT(21);
INT(32);
INT(33);
INT(34);
INT(35);
INT(36);
INT(37);
INT(38);
INT(39);
INT(40);
INT(41);
INT(42);
INT(43);
INT(44);
INT(45);
INT(46);
INT(47);
INT(66);
void setup_idt()
{
memset(idt, 0, sizeof(idt));
TRAP(0);
TRAP(1);
TRAP(2);
TRAP(3);
TRAP(4);
TRAP(5);
TRAP(6);
TRAP(7);
TRAP(8);
TRAP(10);
TRAP(11);
TRAP(12);
TRAP(13);
TRAP(14);
TRAP(16);
TRAP(17);
TRAP(18);
TRAP(19);
TRAP(20);
TRAP(21);
IRQ(32);
IRQ(33);
IRQ(34);
IRQ(35);
IRQ(36);
IRQ(37);
IRQ(38);
IRQ(39);
IRQ(40);
IRQ(41);
IRQ(42);
IRQ(43);
IRQ(44);
IRQ(45);
IRQ(46);
IRQ(47);
SYS(66);
static IDTR idtr;
idtr.limit = 0x0FFF;
idtr.offset = (u64)idt;
asm volatile("lidt %0" : : "m"(idtr));
}