Yet another forum user with IDT issues
Posted: Tue Aug 10, 2021 4:40 pm
As the title says, I'm having trouble with interrupts. QEMU triple faults whenever I enable them. I have a higher half 64-bit kernel with Limine as the bootloader. here is the relevant code:
If it helps, I've verified through GDB that the address in the IDT register indeed matches the address of IDT (my table).
Thanks in advance for your help.
Code: Select all
#include "../drivers/ports.h"
#include "stdint.h"
struct IDT_entry{
uint16_t offset_lowerbits;
uint16_t selector;
uint8_t ist;
uint8_t type_attr;
uint16_t offset_higherbits;
uint32_t offset_highestbits;
uint32_t zero;
} __attribute__((packed));
struct IDTR{
uint16_t limit;
uint64_t base;
} __attribute__((packed));
struct IDT_entry IDT[256];
struct IDTR idtr;
void load_idt(struct IDTR idt_ptr) {
__asm__ volatile(
"lidt %0"
:
: "m" (idt_ptr)
);
}
void sti() {
__asm__ volatile("sti;");
}
void fillentry(uint8_t i, uint64_t address) {
IDT[i].offset_lowerbits = (uint16_t) address;
IDT[i].selector = 0x08;
IDT[i].ist = 0;
IDT[i].type_attr = 0x8E;
IDT[i].offset_higherbits = (uint16_t)(address >> 16);
IDT[i].offset_highestbits = (uint32_t)(address >> 32);
IDT[i].zero = 0;
}
void picremap() {
byteout(0x20, 0x11);
byteout(0xA0, 0x11);
byteout(0x21, 0x20);
byteout(0xA1, 40);
byteout(0x21, 0x04);
byteout(0xA1, 0x02);
byteout(0x21, 0x01);
byteout(0xA1, 0x01);
byteout(0x21, 0x0);
byteout(0xA1, 0x0);
}
void idt_install() {
extern uint64_t irq0();
extern uint64_t irq1();
extern uint64_t irq2();
extern uint64_t irq3();
extern uint64_t irq4();
extern uint64_t irq5();
extern uint64_t irq6();
extern uint64_t irq7();
extern uint64_t irq8();
extern uint64_t irq9();
extern uint64_t irq10();
extern uint64_t irq11();
extern uint64_t irq12();
extern uint64_t irq13();
extern uint64_t irq14();
extern uint64_t irq15();
picremap();
fillentry(0, (uint64_t)irq0);
fillentry(1, (uint64_t)irq1);
fillentry(2, (uint64_t)irq2);
fillentry(3, (uint64_t)irq3);
fillentry(4, (uint64_t)irq4);
fillentry(5, (uint64_t)irq5);
fillentry(6, (uint64_t)irq6);
fillentry(7, (uint64_t)irq7);
fillentry(8, (uint64_t)irq8);
fillentry(9, (uint64_t)irq9);
fillentry(10, (uint64_t)irq10);
fillentry(11, (uint64_t)irq11);
fillentry(12, (uint64_t)irq11);
fillentry(13, (uint64_t)irq12);
fillentry(14, (uint64_t)irq13);
fillentry(15, (uint64_t)irq14);
idtr.limit = sizeof(struct IDT_entry) * 256 - 1;
idtr.base = (uint64_t)IDT;
initgdt();
load_idt(idtr);
sti();
}
Thanks in advance for your help.