#pragma once #include class IDT { public: struct Pointer { uint16_t limit; uint32_t base; } __attribute__((packed)); enum InterruptType : uint8_t { Null = 0, InterruptGate = 0b110, // hardware interrupts are disabled while the handler runs TrapGate = 0b111, // hardware interrupts remain active while the handler runs TaskGate = 0b101, // selector points to TSS rather than a code segment }; class Entry { public: constexpr Entry(uint32_t offset = 0, uint16_t select = 0, InterruptType t = Null) { offset_0_15 = offset & 0xffff; offset_16_31 = (offset & 0xffff0000) >> 16; selector = select; type = t; if (offset != 0) { e = true; } } private: uint16_t offset_0_15; // 0-15 offset in the segment uint16_t selector; // 16-31 selector of the code segment [[maybe_unused]] uint8_t null = 0; // 32-39 unused in protected mode InterruptType type : 3; // 40-42 type [[maybe_unused]] bool d : 1 = true; // 43 true: 32-bit, false: 16-bit segment [[maybe_unused]] uint8_t u : 1 = 0; // 44 unused [[maybe_unused]] uint8_t dpl : 2 = 0; // 45-46 descriptor privilege level [[maybe_unused]] bool e : 1 = false; // 47 enable uint16_t offset_16_31; // 48-63 offset high } __attribute__((packed)); IDT(); private: Entry table[256]; }; struct interrupt_frame { uword_t ip; uword_t cs; uword_t flags; uword_t sp; uword_t ss; }; /* https://wiki.osdev.org/Interrupt_Service_Routines */ template __attribute__((interrupt)) void kirq(interrupt_frame* frame); template <> void kirq<0x0>(interrupt_frame* frame); template <> void kirq<0x1>(interrupt_frame* frame);