123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- #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
- iretq
- ret_from_exception:
- // === 从中断中返回 ===
- .code64
- 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
- // 系统调用入口
- // 保存寄存器
- ENTRY(system_call)
- // 由于sysenter指令会禁用中断,因此要在这里手动开启中断
- sti;
-
- subq $0x38, %rsp
-
- cld;
- pushq %rax
- movq %es, %rax
- pushq %rax
- movq %ds, %rax
- pushq %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
- movq $0x10, %rdx
- movq %rdx, %ds
- movq %rdx, %es
- // 将rsp作为参数传递给system_call_function
- movq %rsp, %rdi
- callq system_call_function
- // 从系统调用中返回
- ENTRY(ret_from_system_call)
- movq %rax, 0x80(%rsp) // 将当前rax的值先存到栈中rax的位置
- 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 $0x38, %rsp
- .byte 0x48
- sysexit
- // 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
- ENTRY(_stack_start)
- .quad initial_proc_union + 32768
|