55 lines
1.3 KiB
C++
55 lines
1.3 KiB
C++
#define MODULE "idt"
|
|
|
|
#include "interrupts/IDT.h"
|
|
#include "assert.h"
|
|
#include "log/Log.h"
|
|
|
|
struct IDTEntry
|
|
{
|
|
uint16_t offset0;
|
|
uint16_t selector;
|
|
uint8_t ist;
|
|
uint8_t type_attr;
|
|
uint16_t offset1;
|
|
uint32_t offset2;
|
|
uint32_t ignore;
|
|
void set_offset(uint64_t offset);
|
|
uint64_t get_offset();
|
|
};
|
|
|
|
static IDTEntry entries[256];
|
|
|
|
void IDTEntry::set_offset(uint64_t offset)
|
|
{
|
|
offset0 = (uint16_t)(offset & 0x000000000000ffff);
|
|
offset1 = (uint16_t)((offset & 0x00000000ffff0000) >> 16);
|
|
offset2 = (uint32_t)((offset & 0xffffffff00000000) >> 32);
|
|
}
|
|
|
|
uint64_t IDTEntry::get_offset()
|
|
{
|
|
uint64_t offset = 0;
|
|
offset |= (uint64_t)offset0;
|
|
offset |= (uint64_t)offset1 << 16;
|
|
offset |= (uint64_t)offset2 << 32;
|
|
return offset;
|
|
}
|
|
|
|
void IDT::add_handler(short interrupt_number, void* handler, uint8_t type_attr)
|
|
{
|
|
ASSERT(handler != nullptr);
|
|
ASSERT(interrupt_number < 256);
|
|
IDTEntry* entry_for_handler = &entries[interrupt_number];
|
|
entry_for_handler->selector = 0x08;
|
|
entry_for_handler->type_attr = type_attr;
|
|
entry_for_handler->set_offset((uint64_t)handler);
|
|
}
|
|
|
|
IDTR idtr;
|
|
void IDT::load()
|
|
{
|
|
idtr.limit = 0x0FFF;
|
|
idtr.offset = (uint64_t)entries;
|
|
kdbgln("Loading IDT at offset %lx, limit %d", idtr.offset, idtr.limit);
|
|
asm("lidt %0" : : "m"(idtr));
|
|
} |