Page 1 of 1

General Protection Fault after setting up IDT then calling sti.

Posted: Sun Oct 13, 2024 9:01 am
by AlexTheHobbyOS
After creating a idt for my hobby os then right after calling sti i get a interrupt 32 (GPF) and i have absolutely no idea why i went over my PIC remmaping logic and it looks good also have no idea why a Protection Fault is happening as the sti correctly displays interrupts. Anyways here are the code parts for analysing:

idt_load:

Code: Select all

global idt_load
global enable_interrupts
section .text

idt_load:
    cli
    lidt [rdi]       
    ret           

enable_interrupts:
    sti                   
    ret                  
idt.c

Code: Select all

#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
#define PIC_EOI 0x20

#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01

struct idt_entry idt[IDT_ENTRIES];
struct idt_ptr idtp;

extern void load_segment_selectors();
extern void idt_load(uint64_t);

static void idt_set_gate(int num, uint64_t base, uint16_t sel, uint8_t flags) {
    idt[num].base_low = base & 0xFFFF;
    idt[num].base_mid = (base >> 16) & 0xFFFF;
    idt[num].base_high = (base >> 32) & 0xFFFFFFFF;
    idt[num].sel = sel;
    idt[num].always0 = 0;
    idt[num].flags = flags;
    idt[num].reserved = 0;
}

static void pic_remap(int offset1, int offset2) {
    uint8_t a1, a2;

    a1 = inb(PIC1_DATA);
    a2 = inb(PIC2_DATA);

    outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); 
    outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
    outb(PIC1_DATA, offset1);
    outb(PIC2_DATA, offset2); 
    outb(PIC1_DATA, 4); 
    outb(PIC2_DATA, 2);

    outb(PIC1_DATA, ICW4_8086);
    outb(PIC2_DATA, ICW4_8086);

    outb(PIC1_DATA, a1); // Restore saved masks
    outb(PIC2_DATA, a2);

}

void init_idt() {
    idtp.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1;
    idtp.base = (uint64_t)&idt;

    for (int i = 0; i < IDT_ENTRIES; i++) {
        idt_set_gate(i, 0, 0, 0);
    }

    idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E); 
    idt_set_gate(1, (uint64_t)isr1, 0x08, 0x8E); 
    idt_set_gate(8, (uint64_t)isr8, 0x08, 0x8E);  
    idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E);
    idt_set_gate(14, (uint64_t)isr14, 0x08, 0x8E);
    idt_set_gate(32, (uint64_t)isr32, 0x08, 0x8E); 

    idt_load((uint64_t)&idtp);

    pic_remap(0x20, 0x28); 

    load_segment_selectors(); 

    enable_interrupts();
and struct

Code: Select all

#define IDT_ENTRIES 256

struct idt_entry {
    uint16_t base_low;
    uint16_t sel;
    uint8_t always0;
    uint8_t flags;
    uint16_t base_mid;
    uint32_t base_high;
    uint32_t reserved;
} __attribute__((packed));

struct idt_ptr {
    uint16_t limit;
    uint64_t base;
} __attribute__((packed));

Re: General Protection Fault after setting up IDT then calling sti.

Posted: Sun Oct 13, 2024 11:55 am
by MichaelPetch
I helped this person on Stackoverflow. After returning from their `kernel_main` function with interrupts on they reached a single `hlt` instruction. With no code after the `hlt`, the CPU ended up calling whatever happened to be in memory and then it faulted. I recommended putting the `hlt` in an infinite loop. That resolved their issue.

Re: General Protection Fault after setting up IDT then calling sti.

Posted: Sun Oct 13, 2024 1:09 pm
by nullplan
There is nothing obviously wrong in the code you posted, so we can only guess at the problem. Might I suggest you publish all of your code on something like github? Then we can take a look at all of it. Oh, and GPF is not interrupt 32.