entry.S 6.2 KB

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