Browse Source

:new: 实现了异常捕获模块

fslongjin 3 years ago
parent
commit
06cfb1ceb9
10 changed files with 743 additions and 28 deletions
  1. 3 1
      .vscode/settings.json
  2. 11 4
      kernel/Makefile
  3. 12 0
      kernel/common/asm.h
  4. 5 0
      kernel/common/glib.h
  5. 237 0
      kernel/exception/entry.S
  6. 118 10
      kernel/exception/gate.h
  7. 319 0
      kernel/exception/trap.c
  8. 4 3
      kernel/exception/trap.h
  9. 5 3
      kernel/head.S
  10. 29 7
      kernel/main.c

+ 3 - 1
.vscode/settings.json

@@ -4,6 +4,8 @@
         "stdbool.h": "c",
         "printk.h": "c",
         "stdarg.h": "c",
-        "font.h": "c"
+        "font.h": "c",
+        "trap.h": "c",
+        "gate.h": "c"
     }
 }

+ 11 - 4
kernel/Makefile

@@ -7,21 +7,28 @@ all: kernel
 	objcopy -I elf64-x86-64 -S -R  ".eh_frame" -R ".comment" -O binary kernel ../bin/kernel/kernel.bin
 
 
-kernel: head.o main.o printk.o
-	ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o printk.o -T link.lds
+kernel: head.o entry.o main.o printk.o trap.o
+	ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o -T link.lds
 
 head.o: head.S
 	gcc -E head.S > head.s # 预处理
 	as --64 -o head.o head.s
 
+entry.o: exception/entry.S
+	gcc -E exception/entry.S > exception/entry.s
+	as --64 -o exception/entry.o exception/entry.s
+
 main.o: main.c 
 # -fno-builtin: 不使用C语言内建函数
 # The -m64 option sets int to 32bits and long and pointer to 64 bits and generates code for AMD’s x86-64 architecture.
-	gcc -mcmodel=large -fno-builtin -m64 -c main.c  -fno-stack-protector
+	gcc -mcmodel=large -fno-builtin -m64 -c main.c  -o main.o -fno-stack-protector
 
 
 printk.o: common/printk.c
-	gcc -mcmodel=large -fno-builtin -m64 -c common/printk.c -fno-stack-protector
+	gcc -mcmodel=large -fno-builtin -m64 -c common/printk.c -o common/printk.o -fno-stack-protector
+
+trap.o:	exception/trap.c
+	gcc -mcmodel=large -fno-builtin -m64 -c exception/trap.c -o exception/trap.o -fno-stack-protector
 
 clean: 
 	rm -rf $(GARBAGE)

+ 12 - 0
kernel/common/asm.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#ifndef __ASM__
+#define __ASM__
+
+
+#define ENTRY(name)\
+    .global name;    \
+    name:
+
+
+#endif

+ 5 - 0
kernel/common/glib.h

@@ -26,6 +26,11 @@
 
 #define ABS(x) ((x) > 0 ? (x) : -(x))   // 绝对值
 
+// 定义类型的缩写
+typedef unsigned long ul;
+typedef unsigned long long ull;
+typedef long long ll;
+
 //链表数据结构
 struct List
 {

+ 237 - 0
kernel/exception/entry.S

@@ -1,3 +1,4 @@
+#include"../common/asm.h"
 
 R15 =   0x00
 R14 =   0x08
@@ -24,3 +25,239 @@ RFLAGS	=	0xa8
 OLD_RSP	=	0xb0
 OLDSS	=	0xb8
 
+Restore_all:
+    // === 恢复调用现场 ===
+    popq %r15
+    popq %r14
+    popq %r13
+    popq %r12
+    popq %r11
+    popq %r10
+    popq %r9
+    popq %r8
+    popq %rbx
+    popq %rcx
+    popq %rdx
+    popq %rsi
+    popq %rdi
+    popq %rbp
+
+    popq %rax   //  不允许直接pop到ds
+    movq %rax, %ds
+
+    popq %rax
+    movq %rax, %es
+
+    popq %rax
+    addq $0x10, %rsp // 弹出变量FUNC和errcode
+
+    iretq
+
+ret_from_exception:
+    // === 从中断中返回 ===
+ENTRY(ret_from_intr)
+    jmp Restore_all
+
+Err_Code:
+    // ===== 有错误码的情况下,保存寄存器并跳转服务程序
+
+    pushq %rax
+    movq %es, %rax
+    pushq %rax
+    movq %ds, %rax
+    pushq %rax
+
+    xorq %rax, %rax
+
+    pushq	%rbp
+    pushq	%rdi
+    pushq	%rsi
+    pushq	%rdx
+    pushq	%rcx
+    pushq	%rbx
+    pushq	%r8
+    pushq	%r9
+    pushq	%r10
+    pushq	%r11
+    pushq	%r12
+    pushq	%r13
+    pushq	%r14
+    pushq	%r15
+
+    cld
+
+    movq ERRCODE(%rsp), %rsi    // 把错误码装进rsi,作为函数的第二个参数
+    movq FUNC(%rsp), %rdx
+
+    movq $0x10, %rdi    // 加载内核段的地址
+    movq %rdi, %ds
+    movq %rdi, %es
+
+    movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数
+
+    callq *%rdx //调用服务程序 带*号表示调用的是绝对地址
+
+    jmp ret_from_exception
+
+
+// 0 #DE 除法错误
+ENTRY(divide_error)
+    pushq $0    //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0
+    pushq %rax  // 先将rax入栈
+    leaq do_divide_error(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 1 #DB 调试异常
+ENTRY(debug)
+    pushq $0    
+    pushq %rax  
+    leaq do_debug(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 2 不可屏蔽中断
+ENTRY(nmi)
+    // 不可屏蔽中断不是异常,而是一个外部中断,不会产生错误码
+    // 应执行中断处理流程
+    pushq $0  //占位err_code
+
+    pushq %rax
+    leaq do_nmi(%rip), %rax
+    xchgq %rax, (%rsp)
+    jmp Err_Code
+
+// 3 #BP 断点异常
+ENTRY(int3)
+    pushq $0
+    pushq %rax
+    leaq do_int3(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 4 #OF 溢出异常
+ENTRY(overflow)
+    pushq $0
+    pushq %rax
+    leaq do_overflow(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 5 #BR 越界异常
+ENTRY(bounds)
+    pushq $0
+    pushq %rax
+    leaq do_bounds(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 6 #UD 无效/未定义的机器码
+ENTRY(undefined_opcode)
+    pushq $0
+    pushq %rax
+    leaq do_undefined_opcode(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 7 #NM 设备异常(FPU不存在)
+ENTRY(dev_not_available)
+    pushq $0
+    pushq %rax
+    leaq do_dev_not_avaliable(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 8 #DF 双重错误
+ENTRY(double_fault)
+    pushq %rax
+    leaq do_double_fault(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 9 协处理器越界(保留)
+ENTRY(coprocessor_segment_overrun)
+    pushq $0
+    pushq %rax
+    leaq do_coprocessor_segment_overrun(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 10 #TS 无效的TSS段
+ENTRY(invalid_TSS)
+    // === 不正确的任务状态段 #TS ==
+    // 有错误码,处理器已经自动在异常处理程序栈中压入错误码
+    pushq %rax
+    leaq do_invalid_TSS(%rip), %rax
+    xchgq %rax, (%rsp)
+    jmp Err_Code
+
+// 11 #NP 段不存在
+ENTRY(segment_not_exists)
+    pushq %rax
+    leaq do_segment_not_exists(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 12 #SS 段错误
+ENTRY(stack_segment_fault)
+    pushq %rax
+    leaq do_stack_segment_fault(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 13 #GP 通用保护性异常
+ENTRY(general_protection)
+    pushq %rax
+    leaq do_general_protection(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 14 #PF 页错误
+ENTRY(page_fault)
+    // === 页故障 #PF ==
+    // 有错误码
+    pushq %rax
+    leaq do_page_fault(%rip), %rax
+    xchgq %rax, (%rsp)
+    jmp Err_Code
+
+// 15 Intel保留,请勿使用
+
+// 16 #MF X87 FPU错误(计算错误)
+ENTRY(x87_FPU_error)
+    pushq $0
+    pushq %rax
+    leaq do_x87_FPU_error(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 17 #AC 对齐检测
+ENTRY(alignment_check)
+    pushq %rax
+    leaq do_alignment_check(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 18 #MC 机器检测
+ENTRY(machine_check)
+    pushq $0
+    pushq %rax
+    leaq do_machine_check(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 19 #XM SIMD浮点异常
+ENTRY(SIMD_exception)
+    pushq $0
+    pushq %rax
+    leaq do_SIMD_exception(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code
+
+// 20 #VE 虚拟化异常
+ENTRY(virtualization_exception)
+    pushq $0
+    pushq %rax
+    leaq do_virtualization_exception(%rip), %rax    // 获取中断服务程序的地址
+    xchgq %rax, (%rsp)  // 把FUNC的地址换入栈中
+    jmp Err_Code

+ 118 - 10
kernel/exception/gate.h

@@ -8,6 +8,21 @@
 
 #pragma once
 
+//描述符表的结构体
+struct desc_struct
+{
+    unsigned char x[8];
+};
+
+//门的结构体
+struct gate_struct
+{
+    unsigned char x[16];
+};
+
+extern struct desc_struct GDT_Table[]; //GDT_Table是head.S中的GDT_Table
+extern struct gate_struct IDT_Table[]; //IDT_Table是head.S中的IDT_Table
+extern unsigned int TSS64_Table[26];
 
 /**
  * @brief 初始化中段描述符表内的门描述符(每个16B)
@@ -17,26 +32,119 @@
  * @param code_addr 中断服务程序的地址
  */
 // todo:在系统异常处理主功能完成后,将这段代码用C来写一遍。这段汇编实在是太晦涩难懂了,我看了半个钟才看明白。
+
+/*
 #define _set_gate(gate_selector_addr, attr, ist, code_addr) \
-do{
+do{                                                         \
     unsigned long __d0, __d1;                               \
     __asm__ __volatile__ (  "movw   %%dx,   %%ax    \n\t"   \
-                            "andq   $0x7,   %%rcx   \n\t"   \   // 清空rcx中除了2:0以外的所有位(此前ist的值已经被赋给了rcx)
-                            "addq   %4,     %%rcx   \n\t"   \   // 将P,DPL, Type的值加到rcx中
+                            "andq   $0x7,   %%rcx   \n\t"   // 清空rcx中除了2:0以外的所有位 此前ist的值已经被赋给了rcx \   
+                            "addq   %4,     %%rcx   \n\t"   // 将P,DPL, Type的值加到rcx中 \   
                             "shlq   $32,    %%rcx   \n\t"   \ 
-                            "addq   %%rcx,  %%rax   \n\t"   \   // 设置ist
-                            "xorq   %%rcx,  %%rcx   \n\t"   \   // 清空rcx
+                            "addq   %%rcx,  %%rax   \n\t"   // 设置ist \   
+                            "xorq   %%rcx,  %%rcx   \n\t"   // 清空rcx \   
                             "movl   %%edx,  %%ecx   \n\t"   \ 
                             "shrq   $16,    %%ecx   \n\t"   \
-                            "shlq   $48,    %%rcx   \n\t"   \   // 左移到低8B中表示段内偏移的[31:16]处
-                            "addq   %%rcx,  %%rax   \n\t"   \   // 设置段内偏移[31:16]
-                            "movq   %%rax,  %0      \n\t"   \   // 输出到门选择子的低8B
+                            "shlq   $48,    %%rcx   \n\t"   // 左移到低8B中表示段内偏移的[31:16]处 \   
+                            "addq   %%rcx,  %%rax   \n\t"  // 设置段内偏移[31:16] \   
+                            "movq   %%rax,  %0      \n\t"   // 输出到门选择子的低8B \   
                             "shrq   $32,    %%rdx   \n\t"   \
-                            "movq   %%rdx,  %1      \n\t"   \   // 输出到门选择子的高8B
+                            "movq   %%rdx,  %1      \n\t"   // 输出到门选择子的高8B \   
                             :"=m"(*((unsigned long *)(gate_selector_addr)))	,					                \
 					            "=m"(*(1 + (unsigned long *)(gate_selector_addr))),"=&a"(__d0),"=&d"(__d1)		\
 					        :"i"(attr << 8),									                                \
 					            "3"((unsigned long *)(code_addr)),"2"(0x8 << 16),"c"(ist)				        \
 					        :"memory"		                                                                    \
-    )
+    );                                                                                                          \
 }while(0)
+*/
+//由于带上注释就编译不过,因此复制一份到这里
+#define _set_gate(gate_selector_addr, attr, ist, code_addr)                                                 \
+    do                                                                                                      \
+    {                                                                                                       \
+        unsigned long __d0, __d1;                                                                           \
+        __asm__ __volatile__("movw	%%dx,	%%ax	\n\t"                                                         \
+                             "andq	$0x7,	%%rcx	\n\t"                                                        \
+                             "addq	%4,	%%rcx	\n\t"                                                          \
+                             "shlq	$32,	%%rcx	\n\t"                                                         \
+                             "addq	%%rcx,	%%rax	\n\t"                                                       \
+                             "xorq	%%rcx,	%%rcx	\n\t"                                                       \
+                             "movl	%%edx,	%%ecx	\n\t"                                                       \
+                             "shrq	$16,	%%rcx	\n\t"                                                         \
+                             "shlq	$48,	%%rcx	\n\t"                                                         \
+                             "addq	%%rcx,	%%rax	\n\t"                                                       \
+                             "movq	%%rax,	%0	\n\t"                                                          \
+                             "shrq	$32,	%%rdx	\n\t"                                                         \
+                             "movq	%%rdx,	%1	\n\t"                                                          \
+                             : "=m"(*((unsigned long *)(gate_selector_addr))),                              \
+                               "=m"(*(1 + (unsigned long *)(gate_selector_addr))), "=&a"(__d0), "=&d"(__d1) \
+                             : "i"(attr << 8),                                                              \
+                               "3"((unsigned long *)(code_addr)), "2"(0x8 << 16), "c"(ist)                  \
+                             : "memory");                                                                   \
+    } while (0)
+
+/**
+ * @brief 加载任务状态段寄存器
+ * @param n TSS基地址在GDT中的第几项
+ * 左移3位的原因是GDT每项占8字节
+ */
+#define load_TR(n)                                     \
+    do                                                 \
+    {                                                  \
+        __asm__ __volatile__("ltr %%ax" ::"a"(n << 3)); \
+    } while (0)
+
+/**
+ * @brief 设置中断门
+ * 
+ * @param n 中断号
+ * @param ist ist
+ * @param addr 服务程序的地址
+ */
+void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
+{
+    _set_gate(IDT_Table + n, 0x8E, ist, addr); // p=1,DPL=0, type=E
+}
+
+/**
+ * @brief 设置64位,DPL=0的陷阱门
+ * 
+ * @param n 中断号
+ * @param ist ist
+ * @param addr 服务程序的地址
+ */
+void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
+{
+    _set_gate(IDT_Table + n, 0x8F, ist, addr); // p=1,DPL=0, type=F
+}
+
+/**
+ * @brief 设置64位,DPL=3的陷阱门
+ * 
+ * @param n 中断号
+ * @param ist ist
+ * @param addr 服务程序的地址
+ */
+void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
+{
+    _set_gate(IDT_Table + n, 0xEF, ist, addr); // p=1,DPL=3, type=F
+}
+
+/**
+ * @brief 初始化TSS表的内容
+ * 
+ */
+void set_TSS64(ul rsp0, ul rsp1, ul rsp2, ul ist1, ul ist2, ul ist3, ul ist4, ul ist5, ul ist6, ul ist7)
+{
+    *(ul *)(TSS64_Table + 1) = rsp0;
+    *(ul *)(TSS64_Table + 3) = rsp1;
+    *(ul *)(TSS64_Table + 5) = rsp2;
+
+    *(ul *)(TSS64_Table + 9) = ist1;
+    *(ul *)(TSS64_Table + 11) = ist2;
+    *(ul *)(TSS64_Table + 13) = ist3;
+    *(ul *)(TSS64_Table + 15) = ist4;
+    *(ul *)(TSS64_Table + 17) = ist5;
+    *(ul *)(TSS64_Table + 19) = ist6;
+    *(ul *)(TSS64_Table + 21) = ist7;
+}

+ 319 - 0
kernel/exception/trap.c

@@ -0,0 +1,319 @@
+#include "trap.h"
+#include "gate.h"
+
+void init_sys_vector()
+{
+    set_trap_gate(0, 1, divide_error);
+    set_trap_gate(1, 1, debug);
+    set_intr_gate(2, 1, nmi);
+    set_system_trap_gate(3, 1, int3);
+    set_system_trap_gate(4, 1, overflow);
+    set_system_trap_gate(5, 1, bounds);
+    set_trap_gate(6, 1, undefined_opcode);
+    set_trap_gate(7, 1, dev_not_available);
+    set_trap_gate(8, 1, double_fault);
+    set_trap_gate(9, 1, coprocessor_segment_overrun);
+    set_trap_gate(10, 1, invalid_TSS);
+    set_trap_gate(11, 1, segment_not_exists);
+    set_trap_gate(12, 1, stack_segment_fault);
+    set_trap_gate(13, 1, general_protection);
+    set_trap_gate(14, 1, page_fault);
+    // 中断号15由Intel保留,不能使用
+    set_trap_gate(16, 1, x87_FPU_error);
+    set_trap_gate(17, 1, alignment_check);
+    set_trap_gate(18, 1, machine_check);
+    set_trap_gate(19, 1, SIMD_exception);
+    set_trap_gate(20, 1, virtualization_exception);
+    // 中断号21-31由Intel保留,不能使用
+
+    // 32-255为用户自定义中断内部
+}
+
+// 0 #DE 除法错误
+void do_divide_error(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_divide_error(0),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 1 #DB 调试异常
+void do_debug(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR / TRAP");
+    printk(" ] do_debug(1),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 2 不可屏蔽中断
+void do_nmi(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(BLUE, BLACK, "INT");
+    printk(" ] do_nmi(2),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 3 #BP 断点异常
+void do_int3(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(YELLOW, BLACK, "TRAP");
+    printk(" ] do_int3(3),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 4 #OF 溢出异常
+void do_overflow(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(YELLOW, BLACK, "TRAP");
+    printk(" ] do_overflow(4),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 5 #BR 越界异常
+void do_bounds(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_bounds(5),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 6 #UD 无效/未定义的机器码
+void do_undefined_opcode(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_undefined_opcode(6),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 7 #NM 设备异常(FPU不存在)
+void do_dev_not_avaliable(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_dev_not_avaliable(7),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 8 #DF 双重错误
+void do_double_fault(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "Terminate");
+    printk(" ] do_double_fault(8),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 9 协处理器越界(保留)
+void do_coprocessor_segment_overrun(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_coprocessor_segment_overrun(9),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 10 #TS 无效的TSS段
+void do_invalid_TSS(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[");
+    printk_color(RED, BLACK, "ERROR");
+    printk("] do_invalid_TSS(10),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    printk_color(YELLOW, BLACK, "Information:\n");
+    // 解析错误码
+    if (error_code & 0x01)
+        printk("The exception occurred during delivery of an event external to the program.\n");
+
+    if (error_code & 0x02)
+        printk("Refers to a descriptor in the IDT.\n");
+    else
+    {
+        if (error_code & 0x04)
+            printk("Refers to a descriptor in the current LDT.\n");
+        else
+            printk("Refers to a descriptor in the GDT.\n");
+    }
+
+    printk("Segment Selector Index:%10x\n", error_code & 0xfff8);
+
+    printk("\n");
+
+    while (1)
+        ;
+}
+
+// 11 #NP 段不存在
+void do_segment_not_exists(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_segment_not_exists(11),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 12 #SS SS段错误
+void do_stack_segment_fault(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_stack_segment_fault(12),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 13 #GP 通用保护性异常
+void do_general_protection(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_general_protection(13),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 14 #PF 页故障
+void do_page_fault(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long cr2 = 0;
+    // 先保存cr2寄存器的值,避免由于再次触发页故障而丢失值
+    // cr2存储着触发异常的线性地址
+    __asm__ __volatile__("movq %%cr2, %0"
+                         : "=r"(cr2)::"memory");
+
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[");
+    printk_color(RED, BLACK, "ERROR");
+    printk("] do_page_fault(14),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\tCR2:%18lx\n", error_code, rsp, *rip, cr2);
+
+    printk_color(YELLOW, BLACK, "Information:\n");
+    if (!(error_code & 0x01))
+        printk("Page does not exist.\n");
+
+    if (error_code & 0x02)
+        printk("Fault occurred during operation: writing\n");
+    else
+        printk("Fault occurred during operation: reading\n");
+
+    if (error_code & 0x04)
+        printk("Fault in user level(3).\n");
+    else
+        printk("Fault in supervisor level(0,1,2).\n");
+
+    if (error_code & 0x08)
+        printk("Reserved bit caused the fault.\n");
+
+    if (error_code & 0x10)
+        printk("Fault occurred during fetching instruction.\n");
+
+    while (1)
+        ;
+}
+
+// 15 Intel保留,请勿使用
+
+// 16 #MF x87FPU错误
+void do_x87_FPU_error(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_x87_FPU_error(16),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 17 #AC 对齐检测
+void do_alignment_check(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_alignment_check(17),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 18 #MC 机器检测
+void do_machine_check(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_machine_check(18),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 19 #XM SIMD浮点异常
+void do_SIMD_exception(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_SIMD_exception(19),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 20 #VE 虚拟化异常
+void do_virtualization_exception(unsigned long rsp, unsigned long error_code)
+{
+    unsigned long *rip = (unsigned long *)(rsp + 0x98);
+    printk("[ ");
+    printk_color(RED, BLACK, "ERROR");
+    printk(" ] do_virtualization_exception(20),\tError Code:%18lx,\tRSP:%18lx,\tRIP:%18lx\n", error_code, rsp, *rip);
+
+    while (1)
+        ;
+}
+
+// 21-21 Intel保留,请勿使用

+ 4 - 3
kernel/exception/trap.h

@@ -8,8 +8,9 @@
 
 #pragma once
 
-#include <common/printk.h>
-#include <common/glib.h>
+#include "../common/printk.h"
+#include "../common/glib.h"
+#include "../common/asm.h"
 
 /**
  * @brief 初始化系统中断表
@@ -36,7 +37,7 @@ void dev_not_available();
 void double_fault();
 void coprocessor_segment_overrun();
 void invalid_TSS();
-void segment_not_present();
+void segment_not_exists();
 void stack_segment_fault();
 void general_protection();
 // 缺页异常

+ 5 - 3
kernel/head.S

@@ -113,9 +113,9 @@ SetUp_TSS64:
     shrq $32, %rdx
     movq %rdx, 72(%rdi) // 高8B存到GDT低9项
 
-    // 装载任务状态段寄存器
-    mov $0x40, %ax // 设置起始地址为64
-    ltr %ax
+    // 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载)
+    // mov $0x40, %ax // 设置起始地址为64
+    // ltr %ax
 
     // 切换到内核主程序
     movq go_to_kernel(%rip), %rax
@@ -134,6 +134,8 @@ m_ignore_int:
     pushq %rax
     lretq
 
+    lretq
+
 
 go_to_ignore_int:
     .quad ignore_int

+ 29 - 7
kernel/main.c

@@ -4,6 +4,8 @@
 
 #include "common/glib.h"
 #include "common/printk.h"
+#include "exception/gate.h"
+#include "exception/trap.h"
 
 int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
 
@@ -23,7 +25,7 @@ void show_welcome()
     printk_color(BLACK, 0x00e0ebeb, "      Welcome to DragonOS !     \n");
     for (int i = 0; i < 74; ++i)
         printk(" ");
-    printk_color(0x00e0ebeb, 0x00e0ebeb, "                                \n");
+    printk_color(0x00e0ebeb, 0x00e0ebeb, "                                \n\n");
 }
 
 void test_printk()
@@ -54,16 +56,37 @@ void test_printk()
     printk("\nTest base 16 : %d --> %x\n", 255, 255);
     printk("\nTest base 16 : %d --> %X\n", 255, 255);
 }
-//操作系统内核从这里开始执行
-void Start_Kernel(void)
+
+void init()
 {
     // 初始化printk
     init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16);
 
+    load_TR(8); // 加载TR寄存器
+
+    // 初始化任务状态段表
+    ul tss_item_addr = 0xffff800000007c00;
+    set_TSS64(tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr,
+     tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
+
+    // 初始化中断描述符表
+    init_sys_vector();
+    
+}
+//操作系统内核从这里开始执行
+void Start_Kernel(void)
+{
+
+    init();
     show_welcome();
+
+
+
     //test_printk();
-    
-    int t = 1 / 0;  // 测试异常处理模块ignore_int能否正常工作
+
+    //int t = 1 / 0; // 测试异常处理模块能否正常工作 触发除法错误
+    int t = *(int*) 0xffff80000aa00000; // 触发页故障
+
 
     while (1)
         ;
@@ -74,6 +97,5 @@ void ignore_int()
     printk("[");
     printk_color(YELLOW, BLACK, "WARN");
     printk("] Unknown interrupt or fault at RIP.\n");
-    while (1)
-        ;
+    return;
 }