my strategy was to statically allocate enough space for the first 16 interrupt descriptors, set all the present flags to 0, then put a handler for DE exception in IDT[0].
I still fault however when dividing by zero. I've attached the interrupt handling code, which is entered into by calling load_IDT();
interrupts.h:
Code: Select all
#ifndef interrupts_h
#define interrupts_h
#include "ktype.h"
struct opts {
uint8_t ist_index : 3;
uint8_t reserved : 5;
uint8_t int_or_trap : 1;
uint8_t must_be_one : 3;
uint8_t must_be_zro : 1;
uint8_t privelage_l : 2;
uint8_t present : 1;
}__attribute__((packed));
typedef struct idt_entry {
uint16_t ptr_low;
uint16_t selector;
struct opts opts;
uint16_t ptr_mid;
uint32_t ptr_high;
uint32_t _zero;
}__attribute__((packed)) idt_entry_t;
typedef struct {
uint16_t max_byte;
uint64_t virt_start;
}__attribute__((packed)) descriptor_table_t;
idt_entry_t create_empty();
idt_entry_t create(uint16_t, size_t);
uint16_t cs();
struct opts *set_handler(uint8_t loc, size_t fn_ptr);
void load_IDT();
#endif
Code: Select all
#include "ktype.h"
#include "interrupts.h"
#include "libk.h"
idt_entry_t IDT[16];
static inline void _load_IDT(void* base, uint16_t size) {
// This function works in 32 and 64bit mode
struct {
uint16_t length;
void* base;
} __attribute__((packed)) IDTR = { size, base };
asm ( "lidt %0" : : "m"(IDTR) ); // let the compiler choose an addressing mode
}
void divide_by_zero_handler() {
for(;;);
}
void IDT_init() {
for(int i=0;i<16;i++) {
IDT[i] = create_empty();
}
}
void load_IDT() {
IDT_init();
struct opts *options = set_handler(0, (uint64_t)÷_by_zero_handler);
_load_IDT(IDT, sizeof(IDT)-1);
}
struct opts *set_handler(uint8_t loc, size_t fn_ptr) {
IDT[loc] = create(cs(), fn_ptr);
return (struct opts *)&(IDT[loc].opts);
}
idt_entry_t create(uint16_t gdt_selector, size_t fn_ptr) {
idt_entry_t result;
result.selector = gdt_selector;
result.ptr_low = (uint8_t)fn_ptr;
result.ptr_mid = (uint8_t)(fn_ptr >> 16);
result.ptr_high = (uint16_t)(fn_ptr >> 32);
result.opts.ist_index = 0;
result.opts.reserved = 0;
result.opts.int_or_trap = 0;
result.opts.must_be_one = 0x07;
result.opts.must_be_zro = 0;
result.opts.privelage_l = 0;
result.opts.present = 1;
return result;
}
idt_entry_t create_empty() {
idt_entry_t result;
memset(&result, 0, sizeof(idt_entry_t));
result.opts.must_be_one = 0x07;
return result;
}
inline uint16_t cs(void) {
uint16_t val;
asm volatile ( "mov %%cs, %0" : "=r"(val) );
return val;
}
//intel 8259 support later!
Like i have in the comment at the bottom of that last file, I know that for keyboard support I will have to interface with the 8259 (which I think is the id for the dual PIC on x86). I'm not trying to go that far yet, just get these exceptions caught.