1#include"../common/asm.h" 2.code64 3//.section .text 4 5R15 = 0x00 6R14 = 0x08 7R13 = 0x10 8R12 = 0x18 9R11 = 0x20 10R10 = 0x28 11R9 = 0x30 12R8 = 0x38 13RBX = 0x40 14RCX = 0x48 15RDX = 0x50 16RSI = 0x58 17RDI = 0x60 18RBP = 0x68 19DS = 0x70 20ES = 0x78 21RAX = 0x80 22FUNC = 0x88 23ERRCODE = 0x90 24// 以下几个字段,在中断产生时,由处理器压入栈内 25RIP = 0x98 26CS = 0xa0 27RFLAGS = 0xa8 28OLD_RSP = 0xb0 29OLDSS = 0xb8 30 31Restore_all: 32 // === 恢复调用现场 === 33 popq %r15 34 popq %r14 35 popq %r13 36 popq %r12 37 popq %r11 38 popq %r10 39 popq %r9 40 popq %r8 41 popq %rbx 42 popq %rcx 43 popq %rdx 44 popq %rsi 45 popq %rdi 46 popq %rbp 47 48 popq %rax // 不允许直接pop到ds 49 movq %rax, %ds 50 51 popq %rax 52 movq %rax, %es 53 54 popq %rax 55 addq $0x10, %rsp // 弹出变量FUNC和errcode 56 57 sti 58 iretq 59 60ret_from_exception: 61 // === 从中断中返回 === 62 63ENTRY(ret_from_intr) 64 65 // 进入信号处理流程 66 cli 67 68 // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 69 movq %rsp, %rdi 70 callq do_signal 71 72 // 恢复寄存器 73 jmp Restore_all 74 75 76Err_Code: 77 78 // ===== 有错误码的情况下,保存寄存器并跳转服务程序 79 pushq %rax 80 movq %es, %rax 81 pushq %rax 82 movq %ds, %rax 83 pushq %rax 84 xorq %rax, %rax 85 86 pushq %rbp 87 pushq %rdi 88 pushq %rsi 89 pushq %rdx 90 pushq %rcx 91 pushq %rbx 92 pushq %r8 93 pushq %r9 94 pushq %r10 95 pushq %r11 96 pushq %r12 97 pushq %r13 98 pushq %r14 99 pushq %r15 100 101 cld 102 103 movq ERRCODE(%rsp), %rsi // 把错误码装进rsi,作为函数的第二个参数 104 movq FUNC(%rsp), %rdx 105 106 movq $0x10, %rdi // 加载内核段的地址 107 movq %rdi, %ds 108 movq %rdi, %es 109 110 movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数 111 112 callq *%rdx //调用服务程序 带*号表示调用的是绝对地址 113 jmp ret_from_exception 114 115 116// 0 #DE 除法错误 117ENTRY(divide_error) 118 119 pushq $0 //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0 120 pushq %rax // 先将rax入栈 121 leaq do_divide_error(%rip), %rax // 获取中断服务程序的地址 122 123 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 124 jmp Err_Code 125 126// 1 #DB 调试异常 127ENTRY(debug) 128 pushq $0 129 pushq %rax 130 leaq do_debug(%rip), %rax // 获取中断服务程序的地址 131 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 132 jmp Err_Code 133 134// 2 不可屏蔽中断 135ENTRY(nmi) 136 // 不可屏蔽中断不是异常,而是一个外部中断,不会产生错误码 137 // 应执行中断处理流程 138 pushq $0 //占位err_code 139 140 pushq %rax 141 leaq do_nmi(%rip), %rax 142 xchgq %rax, (%rsp) 143 jmp Err_Code 144 145// 3 #BP 断点异常 146ENTRY(int3) 147 pushq $0 148 pushq %rax 149 leaq do_int3(%rip), %rax // 获取中断服务程序的地址 150 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 151 jmp Err_Code 152 153// 4 #OF 溢出异常 154ENTRY(overflow) 155 pushq $0 156 pushq %rax 157 leaq do_overflow(%rip), %rax // 获取中断服务程序的地址 158 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 159 jmp Err_Code 160 161// 5 #BR 越界异常 162ENTRY(bounds) 163 pushq $0 164 pushq %rax 165 leaq do_bounds(%rip), %rax // 获取中断服务程序的地址 166 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 167 jmp Err_Code 168 169// 6 #UD 无效/未定义的机器码 170ENTRY(undefined_opcode) 171 pushq $0 172 pushq %rax 173 leaq do_undefined_opcode(%rip), %rax // 获取中断服务程序的地址 174 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 175 jmp Err_Code 176 177// 7 #NM 设备异常(FPU不存在) 178ENTRY(dev_not_avaliable) 179 pushq $0 180 pushq %rax 181 leaq do_dev_not_avaliable(%rip), %rax // 获取中断服务程序的地址 182 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 183 jmp Err_Code 184 185// 8 #DF 双重错误 186ENTRY(double_fault) 187 pushq %rax 188 leaq do_double_fault(%rip), %rax // 获取中断服务程序的地址 189 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 190 jmp Err_Code 191 192// 9 协处理器越界(保留) 193ENTRY(coprocessor_segment_overrun) 194 pushq $0 195 pushq %rax 196 leaq do_coprocessor_segment_overrun(%rip), %rax // 获取中断服务程序的地址 197 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 198 jmp Err_Code 199 200// 10 #TS 无效的TSS段 201ENTRY(invalid_TSS) 202 // === 不正确的任务状态段 #TS == 203 // 有错误码,处理器已经自动在异常处理程序栈中压入错误码 204 pushq %rax 205 leaq do_invalid_TSS(%rip), %rax 206 xchgq %rax, (%rsp) 207 jmp Err_Code 208 209// 11 #NP 段不存在 210ENTRY(segment_not_exists) 211 pushq %rax 212 leaq do_segment_not_exists(%rip), %rax // 获取中断服务程序的地址 213 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 214 jmp Err_Code 215 216// 12 #SS 段错误 217ENTRY(stack_segment_fault) 218 pushq %rax 219 leaq do_stack_segment_fault(%rip), %rax // 获取中断服务程序的地址 220 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 221 jmp Err_Code 222 223// 13 #GP 通用保护性异常 224ENTRY(general_protection) 225 pushq %rax 226 leaq do_general_protection(%rip), %rax // 获取中断服务程序的地址 227 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 228 jmp Err_Code 229 230// 14 #PF 页错误 231ENTRY(page_fault) 232 // === 页故障 #PF == 233 // 有错误码 234 pushq %rax 235 leaq do_page_fault(%rip), %rax 236 xchgq %rax, (%rsp) 237 jmp Err_Code 238 239// 15 Intel保留,请勿使用 240 241// 16 #MF X87 FPU错误(计算错误) 242ENTRY(x87_FPU_error) 243 pushq $0 244 pushq %rax 245 leaq do_x87_FPU_error(%rip), %rax // 获取中断服务程序的地址 246 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 247 jmp Err_Code 248 249// 17 #AC 对齐检测 250ENTRY(alignment_check) 251 pushq %rax 252 leaq do_alignment_check(%rip), %rax // 获取中断服务程序的地址 253 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 254 jmp Err_Code 255 256// 18 #MC 机器检测 257ENTRY(machine_check) 258 pushq $0 259 pushq %rax 260 leaq do_machine_check(%rip), %rax // 获取中断服务程序的地址 261 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 262 jmp Err_Code 263 264// 19 #XM SIMD浮点异常 265ENTRY(SIMD_exception) 266 pushq $0 267 pushq %rax 268 leaq do_SIMD_exception(%rip), %rax // 获取中断服务程序的地址 269 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 270 jmp Err_Code 271 272// 20 #VE 虚拟化异常 273ENTRY(virtualization_exception) 274 pushq $0 275 pushq %rax 276 leaq do_virtualization_exception(%rip), %rax // 获取中断服务程序的地址 277 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 278 jmp Err_Code 279 280 281 282// 系统调用入口 283// 0x80 系统调用门 284ENTRY(syscall_int) 285 pushq $0 286 pushq %rax 287 leaq syscall_handler(%rip), %rax // 获取系统调用服务程序的地址 288 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 289 jmp Err_Code 290 291// irq模块初始化后的ignore_int入点 292ENTRY(ignore_int) 293 pushq $0 294 pushq %rax 295 leaq ignore_int_handler(%rip), %rax // 获取ignore处理程序的地址 296 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 297 jmp Err_Code 298 299