From 06cfb1ceb9b868a1b0547b939b0dd37f4ebc1c58 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Tue, 25 Jan 2022 18:04:18 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=8D=95=E8=8E=B7=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 +- kernel/Makefile | 15 +- kernel/common/asm.h | 12 ++ kernel/common/glib.h | 5 + kernel/exception/entry.S | 237 +++++++++++++++++++++++++++++ kernel/exception/gate.h | 128 ++++++++++++++-- kernel/exception/trap.c | 319 +++++++++++++++++++++++++++++++++++++++ kernel/exception/trap.h | 7 +- kernel/head.S | 8 +- kernel/main.c | 38 ++++- 10 files changed, 744 insertions(+), 29 deletions(-) create mode 100644 kernel/common/asm.h create mode 100644 kernel/exception/trap.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 182aab42..c8dca873 100644 --- a/.vscode/settings.json +++ b/.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" } } \ No newline at end of file diff --git a/kernel/Makefile b/kernel/Makefile index 6854d4da..16cb308b 100644 --- a/kernel/Makefile +++ b/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) \ No newline at end of file diff --git a/kernel/common/asm.h b/kernel/common/asm.h new file mode 100644 index 00000000..3d7ecaf6 --- /dev/null +++ b/kernel/common/asm.h @@ -0,0 +1,12 @@ +#pragma once + +#ifndef __ASM__ +#define __ASM__ + + +#define ENTRY(name)\ + .global name; \ + name: + + +#endif \ No newline at end of file diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 4dec60a6..f70c9a2a 100644 --- a/kernel/common/glib.h +++ b/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 { diff --git a/kernel/exception/entry.S b/kernel/exception/entry.S index d44ac31d..dd4527bf 100644 --- a/kernel/exception/entry.S +++ b/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 diff --git a/kernel/exception/gate.h b/kernel/exception/gate.h index d0bdb0b4..40352002 100644 --- a/kernel/exception/gate.h +++ b/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; +} \ No newline at end of file diff --git a/kernel/exception/trap.c b/kernel/exception/trap.c new file mode 100644 index 00000000..72f01819 --- /dev/null +++ b/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保留,请勿使用 \ No newline at end of file diff --git a/kernel/exception/trap.h b/kernel/exception/trap.h index 3a47c855..feb5403d 100644 --- a/kernel/exception/trap.h +++ b/kernel/exception/trap.h @@ -8,8 +8,9 @@ #pragma once -#include -#include +#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(); // 缺页异常 diff --git a/kernel/head.S b/kernel/head.S index 1bdb2eee..03ed9b53 100644 --- a/kernel/head.S +++ b/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 diff --git a/kernel/main.c b/kernel/main.c index c16d9587..edd7dcfd 100644 --- a/kernel/main.c +++ b/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); - show_welcome(); - //test_printk(); + 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(); - int t = 1 / 0; // 测试异常处理模块ignore_int能否正常工作 +} +//操作系统内核从这里开始执行 +void Start_Kernel(void) +{ + + init(); + show_welcome(); + + + + //test_printk(); + + //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; }