瀏覽代碼

handle int 13

greatbridf 4 年之前
父節點
當前提交
cdd34f456e
共有 3 個文件被更改,包括 65 次插入0 次删除
  1. 23 0
      include/kernel/interrupt.h
  2. 8 0
      src/asm/interrupt.s
  3. 34 0
      src/kernel/interrupt.c

+ 23 - 0
include/kernel/interrupt.h

@@ -4,6 +4,17 @@
 
 #define INTERRUPT_GATE_TYPE (0x8e)
 
+struct regs_32 {
+    uint32_t edi;
+    uint32_t esi;
+    uint32_t ebp;
+    uint32_t esp;
+    uint32_t ebx;
+    uint32_t edx;
+    uint32_t ecx;
+    uint32_t eax;
+};
+
 // external interrupt handler function
 // stub in assembly MUST be called irqN
 #define SET_UP_IRQ(N, SELECTOR)        \
@@ -11,6 +22,11 @@
     ptr_t addr_irq##N = (ptr_t)irq##N; \
     SET_IDT_ENTRY(0x20 + (N), (addr_irq##N), (SELECTOR));
 
+#define SET_IDT_ENTRY_FN(N, FUNC_NAME, SELECTOR) \
+    extern void FUNC_NAME();                     \
+    ptr_t addr_##FUNC_NAME = (ptr_t)FUNC_NAME;   \
+    SET_IDT_ENTRY((N), (addr_##FUNC_NAME), (SELECTOR));
+
 #define SET_IDT_ENTRY(N, ADDR, SELECTOR)      \
     IDT[(N)].offset_low = (ADDR)&0x0000ffff;  \
     IDT[(N)].selector = (SELECTOR);           \
@@ -37,6 +53,13 @@ void init_idt();
 // [1] bit 16:47 => address
 extern void asm_load_idt(uint16_t idt_descriptor[3]);
 
+void int13_handler(
+    struct regs_32 s_regs,
+    uint32_t error_code,
+    ptr_t eip,
+    uint16_t cs,
+    uint32_t eflags);
+
 void irq0_handler(void);
 void irq1_handler(void);
 void irq2_handler(void);

+ 8 - 0
src/asm/interrupt.s

@@ -2,6 +2,14 @@
 
 .text
 
+.globl int13
+.type  int13 @function
+int13:
+    pushal
+    call int13_handler
+    popal
+    iret
+
 .globl irq0
 .type  irq0 @function
 irq0:

+ 34 - 0
src/kernel/interrupt.c

@@ -4,6 +4,7 @@
 #include <kernel/interrupt.h>
 #include <kernel/stdio.h>
 #include <kernel/vga.h>
+#include <kernel_main.h>
 
 static struct IDT_entry IDT[256];
 
@@ -23,6 +24,10 @@ void init_idt()
     asm_outb(0x21, 0x00);
     asm_outb(0xa1, 0x00);
 
+    // handle general protection fault (handle segmentation fault)
+    SET_IDT_ENTRY_FN(13, int13, 0x08);
+    // SET_IDT_ENTRY(0x0c, /* addr */ 0, 0x08);
+
     // 0x08 stands for kernel code segment
     SET_UP_IRQ(0, 0x08);
     SET_UP_IRQ(1, 0x08);
@@ -48,6 +53,35 @@ void init_idt()
     asm_load_idt(idt_descriptor);
 }
 
+void int13_handler(
+    struct regs_32 s_regs,
+    uint32_t error_code,
+    ptr_t eip,
+    uint16_t cs,
+    uint32_t eflags)
+{
+    char buf[512] = { 0 };
+
+    vga_printk("---- SEGMENTATION FAULT ----\n", 0x0fu);
+
+    snprintf(
+        buf, 512,
+        "eax: %d, ebx: %d, ecx: %d, edx: %d\n"
+        "esp: %d, ebp: %d, esi: %d, edi: %d\n"
+        "eip: %d, cs: %d, error_code: %d   \n"
+        "eflags: %d                        \n",
+        s_regs.eax, s_regs.ebx, s_regs.ecx,
+        s_regs.edx, s_regs.esp, s_regs.ebp,
+        s_regs.esi, s_regs.edi, eip,
+        cs, error_code, eflags);
+    vga_printk(buf, 0x0fu);
+
+    vga_printk("----   HALTING SYSTEM   ----", 0x0fu);
+
+    asm_cli();
+    asm_hlt();
+}
+
 void irq0_handler(void)
 {
     asm_outb(0x20, 0x20);