I am trying to enable hardware interrupts and currently implementing PIC, But kernel is going into panic state.
I am using nasm and C to write my kernel. Please help.
When i call enable_interrupts() in kernel.c, it leads to kernel in panic state.p
this is my kernel. asm code snippet
; Remap the master PIC mov al, 00010001b out 0x20, al ; Send the command to the master PIC mov al, 0x20 ; Interrupt 0x20 is the starting point of the master PIC interrupt out 0x21, al ; Send the command to the master PIC mov al, 00000001b ; Put the master PIC in 8086 mode out 0x21, al ; Send the command to the master PIC;End of PIC remapping call kernel_main
this is my kernel.c main function
void kernel_main() { terminal_initialize(); print("Hello World \n This is my os \n"); print("Initializing IDT...\n"); idt_init(); print("IDT initialized.\n"); print("Enabling interrupts...\n"); enable_interrupts(); print("Interrupts enabled.\n"); print("Kernel initialization complete.\n");}
This is my idt.asm
section .asmextern int21h_handlerextern no_interrupt_handlerglobal idt_loadglobal int21hglobal enable_interruptsglobal disable_interruptsglobal no_interruptenable_interrupts: sti retdisable_interrupts: cli retidt_load: push ebp mov ebp , esp mov eax , [ebp + 8] lidt [eax] pop ebp ret int21h: cli pushad ; Pushes the content of all the GPRs onto the stack call int21h_handler popad ; Pops the content of all the GPRs off the stack sti iret ; pops 5 things off the stack: CS, EIP, EFLAGS, SS, and ESP no_interrupt: cli pushad call no_interrupt_handler popad sti iret
This is my idt.c
#include "idt.h"#include "../config.h"#include "../memory/memory.h"#include "../kernel.h"#include "../io/io.h"// Define the variables herestruct idt_desc idt_descriptors[256];struct idtr_desc idtr_descriptor;extern void idt_load(struct idtr_desc* ptr);extern void int21h();extern void no_interrupt();void no_interrupt_handler() { print("Unhandled interrupt\n"); outb(0x20, 0x20);}void int21h_handler() { print("Keyboard pressed\n"); outb(0x20, 0x20); // Send EOI to master PIC}void idt_zero(){ print("Divide by zero error\n");}void idt_set(int interrupt_no , void* addr){ struct idt_desc* desc = &idt_descriptors[interrupt_no]; desc->offset_1 = (uint32_t) addr & 0x0000FFFF; desc->selector = KERNEL_CODE_SEGMENT; desc->zero = 0x00; desc->type_attr = 0x8E; desc->offset_2 = (uint32_t) addr >> 16;} void idt_init(){ memset(idt_descriptors , 0 , sizeof(idt_descriptors)); idtr_descriptor.limit = sizeof(idt_descriptors) - 1; idtr_descriptor.base = (uint32_t)idt_descriptors; for (int i = 0; i < PIZZAOS_TOTAL_INTERRUPTS; i++){ idt_set(i , no_interrupt); } idt_set(0 , idt_zero); idt_set(0x21 , int21h);// Load the idt idt_load(&idtr_descriptor);}
this is my idt.h
#ifndef IDT_H#define IDT_H#include <stdint.h>struct idt_desc{ uint16_t offset_1; // Offset bits 0 - 15 uint16_t selector; // Selector thats in our GDT uint8_t zero; // Does nothing, unused set to zero uint8_t type_attr; // Descriptor type and attributes uint16_t offset_2; // Offset bits 16-31} __attribute__((packed));struct idtr_desc{ uint16_t limit; // Size of descriptor table -1 uint32_t base; // Base address of the start of the interrupt descriptor table} __attribute__((packed));// Change these to extern declarationsextern struct idt_desc idt[256];extern struct idtr_desc idtr;void idt_init();void enable_interrupts();void disable_interrupts(); void idt_set(int interrupt_no , void* address );#endif
I am new to os dev, trying to follow along osdev but Just cant figure out whats wrong here.I tried setting master and Slave PIC but that doesnt seem to solve my issue.
My project is on Github in the branch bug---PIC