#pragma once #include #include "cpu/registers.h" class InterruptHandler { private: const uint8_t m_irq; protected: InterruptHandler(uint8_t irq); ~InterruptHandler(); public: virtual cpu_state_t* trigger(cpu_state_t*); }; class IDT { friend class InterruptHandler; public: struct Pointer { uint16_t limit; uint32_t base; } __attribute__((packed)); enum InterruptType : uint8_t { Null = 0, Task = 0b10000101, // 32-bit task gate selector points to TSS rather than a code segment Intr = 0b10001110, // 32-bit interrupt hardware interrupts are disabled while the handler runs Trap = 0b10001111, // 32-bit trap gate hardware interrupts remain active while the handler runs }; class Entry { public: constexpr Entry() = default; Entry(void (*handler)(), uint16_t select, InterruptType t); private: uint16_t offset_0_15 = 0; // 0-15 offset in the segment uint16_t selector = 0; // 16-31 selector of the code segment [[maybe_unused]] uint8_t null = 0; // 32-39 unused in protected mode InterruptType type = Null; // 40-43 type uint16_t offset_16_31 = 0; // 48-63 offset high } __attribute__((packed)); IDT(const uint16_t selector); void enable() { asm volatile("sti"); } private: static bool install(uint8_t, InterruptHandler*); static bool uninstall(uint8_t, InterruptHandler*); };