entry.S 7.5 KB

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