Ok so I've just started coding my OS and it has been fun so far. However I ran into a problem.
Whenever an interrupt fires, be it an exception or an IRQ, a loop of general protection faults is fired after the handler for that interrupt.
I've spent hours debugging already and found a bunch of things that aren't the problem.
-The GDT is set up correctly
-The IDT is also set up correctly
-The PIC is set up correctly
-The timer is masked
So after a while i became frustrated and tried bochs.
Error code: cs_check(0x0010): not a valid code segment!
interrupts.c
Code:
#include "Headers/interrupts.h"
void initializeIDT(const uint16_t selector, const uint8_t exceptionTypeAttr, const uint8_t IRQTypeAttr) {
for (uint16_t i = 0; i < 256; i++)
setGateDescriptor(i, (uint32_t*)&_unused, selector, IRQTypeAttr);
setGateDescriptor(0, (uint32_t*)&_exception0, selector, exceptionTypeAttr);
setGateDescriptor(1, (uint32_t*)&_exception1, selector, exceptionTypeAttr);
setGateDescriptor(2, (uint32_t*)&_exception2, selector, exceptionTypeAttr);
setGateDescriptor(3, (uint32_t*)&_exception3, selector, exceptionTypeAttr);
...
setGateDescriptor(32, (uint32_t*)&_irq32, selector, IRQTypeAttr);
setGateDescriptor(33, (uint32_t*)&_irq33, selector, IRQTypeAttr);
setGateDescriptor(34, (uint32_t*)&_irq34, selector, IRQTypeAttr);
...
}
void enableInterrupts() {
asm volatile ("sti");
}
void disableInterrupts() {
asm volatile ("cli");
}
void resetPIC(const uint8_t offsetVector) {
uint8_t PIC1Mask = inb(PORT_NB_PIC_MASTER_DATA);
uint8_t PIC2Mask = inb(PORT_NB_PIC_SLAVE_DATA);
//Restart PICs (CW4 needed | cascade mode | edge triggered mode)
outb(PORT_NB_PIC_MASTER_CMD, 0b00010001);
outb(PORT_NB_PIC_SLAVE_CMD, 0b00010001);
//Set vector offset to 32
outb(PORT_NB_PIC_MASTER_DATA, offsetVector);
outb(PORT_NB_PIC_SLAVE_DATA, offsetVector + 8);
//Set up cascade mode
outb(PORT_NB_PIC_MASTER_DATA, 0x04);
outb(PORT_NB_PIC_SLAVE_DATA, 0x02);
//ICW4 (8086 mode)
outb(PORT_NB_PIC_MASTER_DATA, 0x1);
outb(PORT_NB_PIC_SLAVE_DATA, 0x1);
//Clearing masks
outb(PORT_NB_PIC_MASTER_DATA, PIC1Mask);
outb(PORT_NB_PIC_SLAVE_DATA, PIC2Mask);
}
void setPICMask(const uint16_t mask) {
outb(PORT_NB_PIC_MASTER_DATA, (uint8_t)(mask & 0x00FF));
outb(PORT_NB_PIC_SLAVE_DATA, (uint8_t)(mask >> 8));
}
void resetPICMask() {
outb(PORT_NB_PIC_MASTER_DATA, 0x0);
outb(PORT_NB_PIC_SLAVE_DATA, 0x0);
}
uint16_t getPICMask() {
return ((uint16_t)(inb(PORT_NB_PIC_MASTER_DATA)) |
((uint16_t)(inb(PORT_NB_PIC_SLAVE_DATA))) << 8);
}
void sendEOIMasterPIC() {
outb(PORT_NB_PIC_MASTER_CMD, 0x20);
}
void sendEOISlavePIC() {
outb(PORT_NB_PIC_SLAVE_CMD, 0x20);
}
void handleIRQ(uint8_t nb) {
printf(" INTERRUPT:");
hexDump(&nb, 1);
if (nb >= 32 && nb < 40)
sendEOIMasterPIC();
else if (nb >= 40 && nb < 48) {
sendEOISlavePIC();
sendEOIMasterPIC();
}
}
void handleException(uint8_t nb) {
clearScreen();
printf("EXCEPTION ");
hexDump(&nb, 1);
printRegisters();
printf(" STACK: ");
hexDump(&nb - 16, 24);
while (1) {}
}
kernelMain.c
Code:
#include "Headers/types.h"
#include "Headers/debug.h"
#include "Headers/GDT.h"
#include "Headers/IDT.h"
#include "Headers/interrupts.h"
void setUpGDT() {
setSegmentDescriptor(0, 0, 0, 0, 0);
setSegmentDescriptor(1, 0, 0xFFFFFFFF, GDT_ACCESS_CODE_SEGMENT, 0b1100);
setSegmentDescriptor(2, 0, 0xFFFFFFFF, GDT_ACCESS_DATA_SEGMENT, 0b1100);
loadGDT(3);
}
void setUpInterrupts() {
setPICMask(0x01);
resetPIC(0x20);
initializeIDT(1 * 8, IDT_TYPE_ATTR_TRAP_GATE, IDT_TYPE_ATTR_INT_GATE);
enableInterrupts();
}
extern void kernelMain(void *multiboot_structure, uint32_t magic) {
clearScreen();
setUpGDT();
setUpInterrupts();
while (1) {
}
}
interruptStubs.s
Code:
.extern handleIRQ
.extern handleException
.global _exception0
_exception0:
pushal
pushl $0
call handleException
add $4, %esp
popal
iretl
.global _exception1
_exception1:
pushal
pushl $1
call handleException
add $4, %esp
popal
iretl
.global _exception2
_exception2:
pushal
pushl $2
call handleException
add $4, %esp
popal
iretl
...
.global _unused
_unused:
iretl
.global _irq32
_irq32:
pushal
pushl $32
call handleIRQ
add $4, %esp
popal
iretl
.global _irq33
_irq33:
pushal
pushl $33
call handleIRQ
add $4, %esp
popal
iretl
.global _irq34
_irq34:
pushal
pushl $34
call handleIRQ
add $4, %esp
popal
iretl
...
Thanks in advance for taking the time to help me