150 lines
2.5 KiB
C++
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));
|
|
}
|