#include #include #include 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)); }