Home > Enterprise >  OSDEV. Why does my int 0x80 cause a General Protection fault?
OSDEV. Why does my int 0x80 cause a General Protection fault?

Time:10-08

I am learning to use gcc, nasm, and qemu to develop a toy OS on i386.
And I tried to initialize the IDT and added some interrupt handlers. But I got a strange error I can't understand.

Here is the github repo. Following are some details about the problem.

I think the problem is hidden in the main.c.

#define IDT_ADDR 0x2000
#define AR_INTGATE32 0x8e

typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;

//remapping pic
#define PIC0_ICW1 0x20
#define PIC0_OCW2 0x20
#define PIC0_IMR  0x21
#define PIC0_ICW2 0x21
#define PIC0_ICW3 0x21
#define PIC0_ICW4 0x21
#define PIC1_ICW1 0xa0
#define PIC1_OCW2 0xa0
#define PIC1_IMR  0xa1
#define PIC1_ICW2 0xa1
#define PIC1_ICW3 0xa1
#define PIC1_ICW4 0xa1

static inline void outb(uint16_t port, uint8_t val) {
    asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
}

void init_pic() {
    outb(PIC0_IMR, 0xff);
    outb(PIC1_IMR, 0xff);
    outb(PIC0_ICW1, 0x11);
    outb(PIC0_ICW2, 0x20);   /* IRQ0-7 -> INT 0x20-0x27*/
    outb(PIC0_ICW3, 1<<2);
    outb(PIC0_ICW4, 0x01);
    outb(PIC1_ICW1, 0x11);
    outb(PIC1_ICW2, 0x28);   /* IRQ8-15 -> INT 0x28-0x2f */
    outb(PIC1_ICW3, 2);
    outb(PIC1_ICW4, 0x01);
    outb(PIC0_IMR, 0xfc);    /* 11111011 PIC1*/
    outb(PIC1_IMR, 0xff);
}

struct idt_entry_t {
    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     reserved;     // Set to zero
    uint8_t     attributes;   // Type and attributes; see the IDT page
    uint16_t    isr_high;     // The higher 16 bits of the ISR's address
} __attribute__((packed));

void set_intrdesc(struct idt_entry_t *id, void* isr, uint16_t cs, uint8_t attr) {
    id->isr_low = (uint32_t)isr & 0xffff;
    id->kernel_cs = cs;
    id->reserved = 0;
    id->attributes = attr;
    id->isr_high = (uint32_t)isr >> 16;
}

struct idt_entry_t *idt = (struct idt_entry_t*)IDT_ADDR;

struct interrupt_frame {
    uint32_t tf_eip;
    uint16_t tf_cs;
    uint16_t tf_padding4;
    uint32_t tf_eflags;
};

__attribute__ ((interrupt))
void interrupt_handler_0x80(struct interrupt_frame *frame) {
    asm("mov $0x20,            
  • Related