#include"../common/asm.h" .code64 //.section .text R15 = 0x00 R14 = 0x08 R13 = 0x10 R12 = 0x18 R11 = 0x20 R10 = 0x28 R9 = 0x30 R8 = 0x38 RBX = 0x40 RCX = 0x48 RDX = 0x50 RSI = 0x58 RDI = 0x60 RBP = 0x68 DS = 0x70 ES = 0x78 RAX = 0x80 FUNC = 0x88 ERRCODE = 0x90 // 以下几个字段,在中断产生时,由处理器压入栈内 RIP = 0x98 CS = 0xa0 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 sti iretq ret_from_exception: // === 从中断中返回 === ENTRY(ret_from_intr) // 进入信号处理流程 cli // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 movq %rsp, %rdi callq do_signal // 恢复寄存器 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 // 从系统调用中返回 ENTRY(ret_from_system_call) jmp Restore_all // 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_avaliable) 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 // 系统调用入口 // 0x80 系统调用门 ENTRY(syscall_int) pushq $0 pushq %rax leaq do_syscall_int(%rip), %rax // 获取系统调用服务程序的地址 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 jmp Err_Code // irq模块初始化后的ignore_int入点 ENTRY(ignore_int) pushq $0 pushq %rax leaq ignore_int_handler(%rip), %rax // 获取ignore处理程序的地址 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 jmp Err_Code