cassemblyx86-64interruptisr

Can't get Interrupts (IRQs) handled in my 64bit, c kernel crashes


Title says it all, my pic masking works. If i send an IRQ (key-stroke) the kernel crashes. I'm using nasm. What should i do to get the exception_handler function executed when an interrupt gets send?

idt.h

#pragma once

#include "../types.h"
#define IDT_MAX_DESCRIPTORS 256
#define GDT_OFFSET_KERNEL_CODE (0x01 * 0x08) //!!!! just to test

extern uint64_t isr_stub_table[];


typedef struct {
    uint16_t isr_low;   // The lower 16 bits of the ISR's address
    uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
    uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
    uint8_t attributes; // Type and attributes; see the IDT page
    uint16_t isr_mid;   // The higher 16 bits of the lower 32 bits of the ISR's address
    uint32_t isr_high;  // The higher 32 bits of the ISR's address
    uint32_t reserved;  // Set to zero
} __attribute__((packed)) idt_desc_t;



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

static idtr_t idtr;
void idt_reload(idtr_t* idtr);
void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist);



void idt_init(void);



static bool vectors[IDT_MAX_DESCRIPTORS];

idt.c:

#include "idt.h"
#include "../types.h"
idt_desc_t idt[IDT_MAX_DESCRIPTORS]; // Create an array of IDT entries; aligned for performance

void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist) {
    idt_desc_t* descriptor = &idt[vector];

    descriptor->isr_low = isr & 0xFFFF;
    descriptor->kernel_cs = GDT_OFFSET_KERNEL_CODE;
    descriptor->ist = ist;
    descriptor->attributes = flags;
    descriptor->isr_mid = (isr >> 16) & 0xFFFF;
    descriptor->isr_high = (isr >> 32) & 0xFFFFFFFF;
    descriptor->reserved = 0;
}
void idt_init() {
    idtr.base = (uintptr_t)&idt[0];
    idtr.limit = (uint16_t)sizeof(idt_desc_t) * IDT_MAX_DESCRIPTORS - 1;

    for (uint8_t vector = 0; vector < 32; vector++) {
        idt_set_descriptor(vector, isr_stub_table[vector], 0x8E, 1); 
        vectors[vector] = true;
    }
    __asm__ volatile("lidt %0" : : "memory"(idtr)); // load the new IDT
    __asm__ volatile("sti");                        // set the interrupt flag

}
void exception_handler() {
    terminal_puts("Hello");
     __asm__ volatile ("cli; hlt"); // Completely hangs the computer
}

If I remove the __asm__ volatile("sti"); part it doen't crash anymore but still doesn't handle the interrupt.

idt.asm:

extern exception_handler

%macro isr_err_stub 1
isr_stub_%+%1:
    call exception_handler
    iretq
%endmacro

%macro isr_no_err_stub 1
isr_stub_%+%1:
    call exception_handler
    iretq
%endmacro

isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub    8
isr_no_err_stub 9
isr_err_stub    10
isr_err_stub    11
isr_err_stub    12
isr_err_stub    13
isr_err_stub    14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub    17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub    30
isr_no_err_stub 31




global isr_stub_table
isr_stub_table:
%assign i 0 
%rep    32 
    dq isr_stub_%+i
%assign i i+1 
%endrep

I don't know anymore details to add so pls ask for more if you need them. I've used this tutorial: https://wiki.osdev.org/Interrupts_tutorial


Solution

  • everything was right but the gdt wasn't initialized the right way