111f78b73SLoGin#include <common/asm.h> 211f78b73SLoGin.code64 311f78b73SLoGin//.section .text 411f78b73SLoGin 511f78b73SLoGinR15 = 0x00 611f78b73SLoGinR14 = 0x08 711f78b73SLoGinR13 = 0x10 811f78b73SLoGinR12 = 0x18 911f78b73SLoGinR11 = 0x20 1011f78b73SLoGinR10 = 0x28 1111f78b73SLoGinR9 = 0x30 1211f78b73SLoGinR8 = 0x38 1311f78b73SLoGinRBX = 0x40 1411f78b73SLoGinRCX = 0x48 1511f78b73SLoGinRDX = 0x50 1611f78b73SLoGinRSI = 0x58 1711f78b73SLoGinRDI = 0x60 1811f78b73SLoGinRBP = 0x68 1911f78b73SLoGinDS = 0x70 2011f78b73SLoGinES = 0x78 2111f78b73SLoGinRAX = 0x80 2211f78b73SLoGinFUNC = 0x88 2311f78b73SLoGinERRCODE = 0x90 2411f78b73SLoGin// 以下几个字段,在中断产生时,由处理器压入栈内 2511f78b73SLoGinRIP = 0x98 2611f78b73SLoGinCS = 0xa0 2711f78b73SLoGinRFLAGS = 0xa8 2811f78b73SLoGinOLD_RSP = 0xb0 2911f78b73SLoGinOLDSS = 0xb8 3011f78b73SLoGin 3111f78b73SLoGinRestore_all: 3211f78b73SLoGin // === 恢复调用现场 === 3311f78b73SLoGin popq %r15 3411f78b73SLoGin popq %r14 3511f78b73SLoGin popq %r13 3611f78b73SLoGin popq %r12 3711f78b73SLoGin popq %r11 3811f78b73SLoGin popq %r10 3911f78b73SLoGin popq %r9 4011f78b73SLoGin popq %r8 4111f78b73SLoGin popq %rbx 4211f78b73SLoGin popq %rcx 4311f78b73SLoGin popq %rdx 4411f78b73SLoGin popq %rsi 4511f78b73SLoGin popq %rdi 4611f78b73SLoGin popq %rbp 4711f78b73SLoGin 4811f78b73SLoGin popq %rax // 不允许直接pop到ds 4911f78b73SLoGin movq %rax, %ds 5011f78b73SLoGin 5111f78b73SLoGin popq %rax 5211f78b73SLoGin movq %rax, %es 5311f78b73SLoGin 5411f78b73SLoGin popq %rax 5511f78b73SLoGin addq $0x10, %rsp // 弹出变量FUNC和errcode 5611f78b73SLoGin 5711f78b73SLoGin iretq 5811f78b73SLoGin 5911f78b73SLoGinret_from_exception: 6011f78b73SLoGin // === 从中断中返回 === 6111f78b73SLoGin 6211f78b73SLoGinENTRY(ret_from_intr) 6311f78b73SLoGin 6411f78b73SLoGin // 进入信号处理流程 6511f78b73SLoGin cli 6611f78b73SLoGin 6711f78b73SLoGin // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 6811f78b73SLoGin movq %rsp, %rdi 6911f78b73SLoGin callq do_signal 7011f78b73SLoGin cli 7111f78b73SLoGin 7211f78b73SLoGin__entry_ret_from_intr_before_gs_check_2: 7311f78b73SLoGin push %rcx 7411f78b73SLoGin addq $8, %rsp 7511f78b73SLoGin movq CS(%rsp), %rcx 7611f78b73SLoGin subq $8, %rsp 7711f78b73SLoGin andq $0x3, %rcx 7811f78b73SLoGin cmpq $0x3, %rcx 7911f78b73SLoGin 8011f78b73SLoGin jne __entry_ret_from_intr_after_gs_check_2 8111f78b73SLoGin swapgs 8211f78b73SLoGin 8311f78b73SLoGin__entry_ret_from_intr_after_gs_check_2: 8411f78b73SLoGin popq %rcx 8511f78b73SLoGin 8611f78b73SLoGin // 恢复寄存器 8711f78b73SLoGin jmp Restore_all 8811f78b73SLoGin 8911f78b73SLoGin 9011f78b73SLoGinErr_Code: 9111f78b73SLoGin 9211f78b73SLoGin // ===== 有错误码的情况下,保存寄存器并跳转服务程序 9311f78b73SLoGin pushq %rax 9411f78b73SLoGin movq %es, %rax 9511f78b73SLoGin pushq %rax 9611f78b73SLoGin movq %ds, %rax 9711f78b73SLoGin pushq %rax 9811f78b73SLoGin xorq %rax, %rax 9911f78b73SLoGin 10011f78b73SLoGin pushq %rbp 10111f78b73SLoGin pushq %rdi 10211f78b73SLoGin pushq %rsi 10311f78b73SLoGin pushq %rdx 10411f78b73SLoGin pushq %rcx 10511f78b73SLoGin pushq %rbx 10611f78b73SLoGin pushq %r8 10711f78b73SLoGin pushq %r9 10811f78b73SLoGin pushq %r10 10911f78b73SLoGin pushq %r11 11011f78b73SLoGin pushq %r12 11111f78b73SLoGin pushq %r13 11211f78b73SLoGin pushq %r14 11311f78b73SLoGin pushq %r15 11411f78b73SLoGin 11511f78b73SLoGin cld 11611f78b73SLoGin 11711f78b73SLoGin movq ERRCODE(%rsp), %rsi // 把错误码装进rsi,作为函数的第二个参数 11811f78b73SLoGin movq FUNC(%rsp), %rdx 11911f78b73SLoGin 12011f78b73SLoGin movq $0x10, %rdi // 加载内核段的地址 12111f78b73SLoGin movq %rdi, %ds 12211f78b73SLoGin movq %rdi, %es 12311f78b73SLoGin 12411f78b73SLoGin movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数 12511f78b73SLoGin 12611f78b73SLoGin__entry_err_code_before_gs_check_1: 12711f78b73SLoGin pushq %rcx 12811f78b73SLoGin movq CS(%rdi), %rcx 12911f78b73SLoGin and $0x3, %rcx 13011f78b73SLoGin cmp $0x3, %rcx 13111f78b73SLoGin 13211f78b73SLoGin jne __entry_err_code_after_gs_check_1 13311f78b73SLoGin swapgs 13411f78b73SLoGin 13511f78b73SLoGin__entry_err_code_after_gs_check_1: 13611f78b73SLoGin popq %rcx 13711f78b73SLoGin 13811f78b73SLoGin callq *%rdx //调用服务程序 带*号表示调用的是绝对地址 13911f78b73SLoGin 14011f78b73SLoGin__entry_err_code_to_ret_from_exception: 14111f78b73SLoGin jmp ret_from_exception 14211f78b73SLoGin 14311f78b73SLoGin 14411f78b73SLoGin// 0 #DE 除法错误 145f2022a8aSLoGinENTRY(trap_divide_error) 14611f78b73SLoGin 14711f78b73SLoGin pushq $0 //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0 14811f78b73SLoGin pushq %rax // 先将rax入栈 14911f78b73SLoGin leaq do_divide_error(%rip), %rax // 获取中断服务程序的地址 15011f78b73SLoGin 15111f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 15211f78b73SLoGin jmp Err_Code 15311f78b73SLoGin 15411f78b73SLoGin// 1 #DB 调试异常 155f2022a8aSLoGinENTRY(trap_debug) 15611f78b73SLoGin pushq $0 15711f78b73SLoGin pushq %rax 15811f78b73SLoGin leaq do_debug(%rip), %rax // 获取中断服务程序的地址 15911f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 16011f78b73SLoGin jmp Err_Code 16111f78b73SLoGin 16211f78b73SLoGin// 2 不可屏蔽中断 163f2022a8aSLoGinENTRY(trap_nmi) 16411f78b73SLoGin // 不可屏蔽中断不是异常,而是一个外部中断,不会产生错误码 16511f78b73SLoGin // 应执行中断处理流程 16611f78b73SLoGin pushq $0 //占位err_code 16711f78b73SLoGin 16811f78b73SLoGin pushq %rax 16911f78b73SLoGin leaq do_nmi(%rip), %rax 17011f78b73SLoGin xchgq %rax, (%rsp) 17111f78b73SLoGin jmp Err_Code 17211f78b73SLoGin 17311f78b73SLoGin// 3 #BP 断点异常 174f2022a8aSLoGinENTRY(trap_int3) 17511f78b73SLoGin pushq $0 17611f78b73SLoGin pushq %rax 17711f78b73SLoGin leaq do_int3(%rip), %rax // 获取中断服务程序的地址 17811f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 17911f78b73SLoGin jmp Err_Code 18011f78b73SLoGin 18111f78b73SLoGin// 4 #OF 溢出异常 182f2022a8aSLoGinENTRY(trap_overflow) 18311f78b73SLoGin pushq $0 18411f78b73SLoGin pushq %rax 18511f78b73SLoGin leaq do_overflow(%rip), %rax // 获取中断服务程序的地址 18611f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 18711f78b73SLoGin jmp Err_Code 18811f78b73SLoGin 18911f78b73SLoGin// 5 #BR 越界异常 190f2022a8aSLoGinENTRY(trap_bounds) 19111f78b73SLoGin pushq $0 19211f78b73SLoGin pushq %rax 19311f78b73SLoGin leaq do_bounds(%rip), %rax // 获取中断服务程序的地址 19411f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 19511f78b73SLoGin jmp Err_Code 19611f78b73SLoGin 19711f78b73SLoGin// 6 #UD 无效/未定义的机器码 198f2022a8aSLoGinENTRY(trap_undefined_opcode) 19911f78b73SLoGin pushq $0 20011f78b73SLoGin pushq %rax 20111f78b73SLoGin leaq do_undefined_opcode(%rip), %rax // 获取中断服务程序的地址 20211f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 20311f78b73SLoGin jmp Err_Code 20411f78b73SLoGin 20511f78b73SLoGin// 7 #NM 设备异常(FPU不存在) 206f2022a8aSLoGinENTRY(trap_dev_not_avaliable) 20711f78b73SLoGin pushq $0 20811f78b73SLoGin pushq %rax 20911f78b73SLoGin leaq do_dev_not_avaliable(%rip), %rax // 获取中断服务程序的地址 21011f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 21111f78b73SLoGin jmp Err_Code 21211f78b73SLoGin 21311f78b73SLoGin// 8 #DF 双重错误 214f2022a8aSLoGinENTRY(trap_double_fault) 21511f78b73SLoGin pushq %rax 21611f78b73SLoGin leaq do_double_fault(%rip), %rax // 获取中断服务程序的地址 21711f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 21811f78b73SLoGin jmp Err_Code 21911f78b73SLoGin 22011f78b73SLoGin// 9 协处理器越界(保留) 221f2022a8aSLoGinENTRY(trap_coprocessor_segment_overrun) 22211f78b73SLoGin pushq $0 22311f78b73SLoGin pushq %rax 22411f78b73SLoGin leaq do_coprocessor_segment_overrun(%rip), %rax // 获取中断服务程序的地址 22511f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 22611f78b73SLoGin jmp Err_Code 22711f78b73SLoGin 22811f78b73SLoGin// 10 #TS 无效的TSS段 229f2022a8aSLoGinENTRY(trap_invalid_TSS) 23011f78b73SLoGin // === 不正确的任务状态段 #TS == 23111f78b73SLoGin // 有错误码,处理器已经自动在异常处理程序栈中压入错误码 23211f78b73SLoGin pushq %rax 23311f78b73SLoGin leaq do_invalid_TSS(%rip), %rax 23411f78b73SLoGin xchgq %rax, (%rsp) 23511f78b73SLoGin jmp Err_Code 23611f78b73SLoGin 23711f78b73SLoGin// 11 #NP 段不存在 238f2022a8aSLoGinENTRY(trap_segment_not_exists) 23911f78b73SLoGin pushq %rax 24011f78b73SLoGin leaq do_segment_not_exists(%rip), %rax // 获取中断服务程序的地址 24111f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 24211f78b73SLoGin jmp Err_Code 24311f78b73SLoGin 24411f78b73SLoGin// 12 #SS 段错误 245f2022a8aSLoGinENTRY(trap_stack_segment_fault) 24611f78b73SLoGin pushq %rax 24711f78b73SLoGin leaq do_stack_segment_fault(%rip), %rax // 获取中断服务程序的地址 24811f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 24911f78b73SLoGin jmp Err_Code 25011f78b73SLoGin 25111f78b73SLoGin// 13 #GP 通用保护性异常 252f2022a8aSLoGinENTRY(trap_general_protection) 25311f78b73SLoGin pushq %rax 25411f78b73SLoGin leaq do_general_protection(%rip), %rax // 获取中断服务程序的地址 25511f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 25611f78b73SLoGin jmp Err_Code 25711f78b73SLoGin 25811f78b73SLoGin// 14 #PF 页错误 259f2022a8aSLoGinENTRY(trap_page_fault) 26011f78b73SLoGin // === 页故障 #PF == 26111f78b73SLoGin // 有错误码 26211f78b73SLoGin pushq %rax 26311f78b73SLoGin leaq do_page_fault(%rip), %rax 26411f78b73SLoGin xchgq %rax, (%rsp) 26511f78b73SLoGin jmp Err_Code 26611f78b73SLoGin 26711f78b73SLoGin// 15 Intel保留,请勿使用 26811f78b73SLoGin 26911f78b73SLoGin// 16 #MF X87 FPU错误(计算错误) 270f2022a8aSLoGinENTRY(trap_x87_FPU_error) 27111f78b73SLoGin pushq $0 27211f78b73SLoGin pushq %rax 27311f78b73SLoGin leaq do_x87_FPU_error(%rip), %rax // 获取中断服务程序的地址 27411f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 27511f78b73SLoGin jmp Err_Code 27611f78b73SLoGin 27711f78b73SLoGin// 17 #AC 对齐检测 278f2022a8aSLoGinENTRY(trap_alignment_check) 27911f78b73SLoGin pushq %rax 28011f78b73SLoGin leaq do_alignment_check(%rip), %rax // 获取中断服务程序的地址 28111f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 28211f78b73SLoGin jmp Err_Code 28311f78b73SLoGin 28411f78b73SLoGin// 18 #MC 机器检测 285f2022a8aSLoGinENTRY(trap_machine_check) 28611f78b73SLoGin pushq $0 28711f78b73SLoGin pushq %rax 28811f78b73SLoGin leaq do_machine_check(%rip), %rax // 获取中断服务程序的地址 28911f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 29011f78b73SLoGin jmp Err_Code 29111f78b73SLoGin 29211f78b73SLoGin// 19 #XM SIMD浮点异常 293f2022a8aSLoGinENTRY(trap_SIMD_exception) 29411f78b73SLoGin pushq $0 29511f78b73SLoGin pushq %rax 29611f78b73SLoGin leaq do_SIMD_exception(%rip), %rax // 获取中断服务程序的地址 29711f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 29811f78b73SLoGin jmp Err_Code 29911f78b73SLoGin 30011f78b73SLoGin// 20 #VE 虚拟化异常 301f2022a8aSLoGinENTRY(trap_virtualization_exception) 30211f78b73SLoGin pushq $0 30311f78b73SLoGin pushq %rax 30411f78b73SLoGin leaq do_virtualization_exception(%rip), %rax // 获取中断服务程序的地址 30511f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 30611f78b73SLoGin jmp Err_Code 30711f78b73SLoGin 30811f78b73SLoGin 30911f78b73SLoGin 31011f78b73SLoGin// 系统调用入口 31111f78b73SLoGin// 0x80 系统调用门 31211f78b73SLoGinENTRY(syscall_int) 31311f78b73SLoGin pushq $0 31411f78b73SLoGin pushq %rax 31511f78b73SLoGin leaq syscall_handler(%rip), %rax // 获取系统调用服务程序的地址 31611f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 31711f78b73SLoGin jmp Err_Code 31811f78b73SLoGin 31911f78b73SLoGin// irq模块初始化后的ignore_int入点 32011f78b73SLoGinENTRY(ignore_int) 32111f78b73SLoGin pushq $0 32211f78b73SLoGin pushq %rax 32311f78b73SLoGin leaq ignore_int_handler(%rip), %rax // 获取ignore处理程序的地址 32411f78b73SLoGin xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 32511f78b73SLoGin jmp Err_Code 32611f78b73SLoGin 32711f78b73SLoGinENTRY(syscall_64) 32811f78b73SLoGin // 切换用户栈和内核栈 329*52bcb59eSGnoCiYeH cli 33011f78b73SLoGin swapgs 33111f78b73SLoGin movq %rsp, %gs:0x8 33211f78b73SLoGin movq %gs:0x0, %rsp 33311f78b73SLoGin 33411f78b73SLoGin pushq $43 // USER_DS 33511f78b73SLoGin pushq %gs:0x8 // rsp 33611f78b73SLoGin pushq %r11 // RFLAGS 33711f78b73SLoGin pushq $51 // USER_CS 33811f78b73SLoGin pushq %rcx // RIP 33911f78b73SLoGin pushq $0 // error code占位 34011f78b73SLoGin 34111f78b73SLoGin pushq %rax 34211f78b73SLoGin leaq syscall_handler(%rip), %rax // FUNC 34311f78b73SLoGin xchgq %rax, (%rsp) 34411f78b73SLoGin 34511f78b73SLoGin pushq %rax // rax 34611f78b73SLoGin 34711f78b73SLoGin movq %es, %rax 34811f78b73SLoGin pushq %rax // es 34911f78b73SLoGin movq %ds, %rax 35011f78b73SLoGin pushq %rax // ds 35111f78b73SLoGin xorq %rax, %rax 35211f78b73SLoGin 35311f78b73SLoGin pushq %rbp 35411f78b73SLoGin pushq %rdi 35511f78b73SLoGin pushq %rsi 35611f78b73SLoGin pushq %rdx 35711f78b73SLoGin pushq %rcx 35811f78b73SLoGin pushq %rbx 35911f78b73SLoGin pushq %r8 36011f78b73SLoGin pushq %r9 36111f78b73SLoGin pushq %r10 36211f78b73SLoGin pushq %r11 36311f78b73SLoGin pushq %r12 36411f78b73SLoGin pushq %r13 36511f78b73SLoGin pushq %r14 36611f78b73SLoGin pushq %r15 36711f78b73SLoGin 36811f78b73SLoGin cld 36911f78b73SLoGin 37011f78b73SLoGin xorq %rsi, %rsi 37111f78b73SLoGin movq FUNC(%rsp), %rdx 37211f78b73SLoGin 37311f78b73SLoGin movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数 37411f78b73SLoGin 375*52bcb59eSGnoCiYeH sti 37611f78b73SLoGin callq *%rdx //调用服务程序 37711f78b73SLoGin 3788612b6ceSLoGin // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 3798612b6ceSLoGin movq %rsp, %rdi 380*52bcb59eSGnoCiYeH 3818612b6ceSLoGin callq do_signal 3828612b6ceSLoGin 38311f78b73SLoGin cli 38411f78b73SLoGin 38511f78b73SLoGin // === 恢复调用现场 === 38611f78b73SLoGin popq %r15 38711f78b73SLoGin popq %r14 38811f78b73SLoGin popq %r13 38911f78b73SLoGin popq %r12 39011f78b73SLoGin popq %r11 39111f78b73SLoGin popq %r10 39211f78b73SLoGin popq %r9 39311f78b73SLoGin popq %r8 39411f78b73SLoGin popq %rbx 39511f78b73SLoGin popq %rcx 39611f78b73SLoGin popq %rdx 39711f78b73SLoGin popq %rsi 39811f78b73SLoGin popq %rdi 39911f78b73SLoGin popq %rbp 40011f78b73SLoGin 40111f78b73SLoGin popq %rax // 不允许直接pop到ds 40211f78b73SLoGin movq %rax, %ds 40311f78b73SLoGin 40411f78b73SLoGin popq %rax 40511f78b73SLoGin movq %rax, %es 40611f78b73SLoGin 40711f78b73SLoGin popq %rax 40811f78b73SLoGin addq $0x10, %rsp // 弹出变量FUNC和errcode 40911f78b73SLoGin 41011f78b73SLoGin popq %rcx // pop rip到rcx 41111f78b73SLoGin 41211f78b73SLoGin addq $0x8, %rsp // 弹出cs 41311f78b73SLoGin popq %r11 // pop rflags到r11 41411f78b73SLoGin popq %rsp // Restore rsp 41511f78b73SLoGin 41611f78b73SLoGin swapgs 41711f78b73SLoGin sysretq 418