l64idt.S 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * Interrupt/exception handling.
  3. */
  4. #include "amd64l.h"
  5. .code64
  6. /* Interrupts. * Let's just talk about hardware
  7. * interrupts. What has to happen is that we save enough state to
  8. * return to where we were, and that's all we do. Hardware needs a stack,
  9. * so it pushes SS and %rsp. Hardware has to
  10. * clear If, which means we have to save the flags. We might be
  11. * in user mode, so we need to change CS, so we need to save
  12. * CS. Finally, we have to know where we were, so we need to save
  13. * the RIP. And that's all get saved.
  14. * Further, if you look at idthandlers below, you see a call to intrp.
  15. * So on entry to intrp, the stack looks like this:
  16. * EFLAGS 24(%rsp)
  17. * CS 16(%rsp)
  18. * EIP of interrupted code 8(%rsp)
  19. * EIP from the call from the idthandlers. (%rsp)
  20. * We, finally, need to push the error code and type.,
  21. * then the registers.
  22. * Why the call from IDThandlers? So we can get a way to point
  23. * to the type. We don't need to save 0(%rsp), we just need
  24. * it to get the type. We can pop it and throw it away when
  25. * needed.
  26. * What does the C level function need?
  27. * It needs a pointer to the Uregs, as defined in ureg.h
  28. * The other problem: all the regs have to be saved, so
  29. * Plan 9 code can see them all.
  30. * Finally, if it's a nested interrupt, we need to know that
  31. * so we don't swapgs at the wrong time.
  32. * Finally, this is utterly different from how Plan 9 does it, because
  33. * all args are on the stack in Plan 9. We need %rdi for the pointer.
  34. * And, the final x86 mess: for some things, the error code pointer
  35. * is on the stack. For others, it's not. To make the stacks
  36. * look identical for the common code and exit we save %rax and line things up.
  37. */
  38. // When we enter:
  39. // registers are NOT saved. We need to save them all.
  40. // return PC is on the stat8(%rsp). It should be left there.
  41. // @ (%rsp) is the PC from the vector table.
  42. // So indirecting on that will get us the interrupt #.
  43. // We need to get what the return PC is pointing to into %rdi.
  44. // We no longer need to make the stack look the same as in Plan 9
  45. // because the arg is in %rdi
  46. .globl _intrp
  47. _intrp:
  48. pushq %rax // bogus error code. Makes stack look like intre.
  49. MOVQ 8(%rsp), %rax
  50. JMP _intrcommon
  51. // or intre, I guess %rax has an interrupt number. I'm a little unsure on this
  52. // part.
  53. .globl _intre
  54. _intre:
  55. // The error code has been pushed. How I love the x86.
  56. XCHGQ %rax, (%rsp)
  57. // At this point, %rax is at TOS and all is well.
  58. // If this is nested we need to not do a swapgs.
  59. _intrcommon:
  60. MOVQ (%rax), %rax
  61. // restore the rax you saved earlier.
  62. XCHGQ %rax, 0(%rsp)
  63. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) /* old CS */
  64. JE _intrnested
  65. SWAPGS
  66. _intrnested:
  67. PUSHQ %r15
  68. PUSHQ %r14
  69. PUSHQ %r13
  70. PUSHQ %r12
  71. PUSHQ %r11
  72. PUSHQ %r10
  73. PUSHQ %r9
  74. PUSHQ %r8
  75. PUSHQ %rBP
  76. PUSHQ %rDI
  77. PUSHQ %rdi
  78. PUSHQ %rSI
  79. PUSHQ %rDX
  80. PUSHQ %rCX
  81. PUSHQ %rbx
  82. PUSHQ %rax
  83. MOVQ %rsp, %rdi // it's ok, we saved %rdi.
  84. CALL _trap
  85. .globl _intrr
  86. _intrr:
  87. POPQ %rax
  88. POPQ %rbx
  89. POPQ %rCX
  90. POPQ %rDX
  91. POPQ %rSI
  92. POPQ %rDI
  93. POPQ %rBP
  94. POPQ %r8
  95. POPQ %r9
  96. POPQ %r10
  97. POPQ %r11
  98. POPQ %r12
  99. POPQ %r13
  100. POPQ %r14
  101. POPQ %r15
  102. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) /* old CS */
  103. JE _iretnested
  104. SWAPGS
  105. _iretnested:
  106. // Throw away:
  107. // The %rax you pushed (error code)
  108. // EIP from the vector table.
  109. ADDQ $16, %rsp
  110. retq
  111. .globl idthandlers
  112. idthandlers:
  113. call _intrp; .byte IdtDE /* #DE Divide-by-Zero Error */
  114. call _intrp; .byte IdtDB /* #DB Debug */
  115. call _intrp; .byte IdtNMI /* #NMI Borked */
  116. call _intrp; .byte IdtBP /* #BP Breakpoint */
  117. call _intrp; .byte IdtOF /* #OF Overflow */
  118. call _intrp; .byte IdtBR /* #BR Bound-Range */
  119. call _intrp; .byte IdtUD /* #UD Invalid-Opcode */
  120. call _intrp; .byte IdtNM /* #NM Device-Not-Available */
  121. call _intre; .byte IdtDF /* #DF Double-Fault */
  122. call _intrp; .byte Idt09 /* reserved */
  123. call _intre; .byte IdtTS /* #TS Invalid-TSS */
  124. call _intre; .byte IdtNP /* #NP Segment-Not-Present */
  125. call _intre; .byte IdtSS /* #SS Stack */
  126. call _intre; .byte IdtGP /* #GP General-Protection */
  127. call _intre; .byte IdtPF /* #PF Page-Fault */
  128. call _intrp; .byte Idt0F /* reserved */
  129. call _intrp; .byte IdtMF /* #MF x87 FPE-Pending */
  130. call _intre; .byte IdtAC /* #AC Alignment-Check */
  131. call _intrp; .byte IdtMC /* #MC Machine-Check */
  132. call _intrp; .byte IdtXF /* #XF SIMD Floating-Point */
  133. call _intrp; .byte 0x14 /* reserved */
  134. call _intrp; .byte 0x15 /* reserved */
  135. call _intrp; .byte 0x16 /* reserved */
  136. call _intrp; .byte 0x17 /* reserved */
  137. call _intrp; .byte 0x18 /* reserved */
  138. call _intrp; .byte 0x19 /* reserved */
  139. call _intrp; .byte 0x1a /* reserved */
  140. call _intrp; .byte 0x1b /* reserved */
  141. call _intrp; .byte 0x1c /* reserved */
  142. call _intrp; .byte 0x1d /* reserved */
  143. call _intrp; .byte 0x1e /* reserved */
  144. call _intrp; .byte 0x1f /* reserved */
  145. call _intrp; .byte 0x20
  146. call _intrp; .byte 0x21
  147. call _intrp; .byte 0x22
  148. call _intrp; .byte 0x23
  149. call _intrp; .byte 0x24
  150. call _intrp; .byte 0x25
  151. call _intrp; .byte 0x26
  152. call _intrp; .byte 0x27
  153. call _intrp; .byte 0x28
  154. call _intrp; .byte 0x29
  155. call _intrp; .byte 0x2a
  156. call _intrp; .byte 0x2b
  157. call _intrp; .byte 0x2c
  158. call _intrp; .byte 0x2d
  159. call _intrp; .byte 0x2e
  160. call _intrp; .byte 0x2f
  161. call _intrp; .byte 0x30
  162. call _intrp; .byte 0x31
  163. call _intrp; .byte 0x32
  164. call _intrp; .byte 0x33
  165. call _intrp; .byte 0x34
  166. call _intrp; .byte 0x35
  167. call _intrp; .byte 0x36
  168. call _intrp; .byte 0x37
  169. call _intrp; .byte 0x38
  170. call _intrp; .byte 0x39
  171. call _intrp; .byte 0x3a
  172. call _intrp; .byte 0x3b
  173. call _intrp; .byte 0x3c
  174. call _intrp; .byte 0x3d
  175. call _intrp; .byte 0x3e
  176. call _intrp; .byte 0x3f
  177. call _intrp; .byte 0x40
  178. call _intrp; .byte 0x41
  179. call _intrp; .byte 0x42
  180. call _intrp; .byte 0x43
  181. call _intrp; .byte 0x44
  182. call _intrp; .byte 0x45
  183. call _intrp; .byte 0x46
  184. call _intrp; .byte 0x47
  185. call _intrp; .byte 0x48
  186. call _intrp; .byte 0x49
  187. call _intrp; .byte 0x4a
  188. call _intrp; .byte 0x4b
  189. call _intrp; .byte 0x4c
  190. call _intrp; .byte 0x4d
  191. call _intrp; .byte 0x4e
  192. call _intrp; .byte 0x4f
  193. call _intrp; .byte 0x50
  194. call _intrp; .byte 0x51
  195. call _intrp; .byte 0x52
  196. call _intrp; .byte 0x53
  197. call _intrp; .byte 0x54
  198. call _intrp; .byte 0x55
  199. call _intrp; .byte 0x56
  200. call _intrp; .byte 0x57
  201. call _intrp; .byte 0x58
  202. call _intrp; .byte 0x59
  203. call _intrp; .byte 0x5a
  204. call _intrp; .byte 0x5b
  205. call _intrp; .byte 0x5c
  206. call _intrp; .byte 0x5d
  207. call _intrp; .byte 0x5e
  208. call _intrp; .byte 0x5f
  209. call _intrp; .byte 0x60
  210. call _intrp; .byte 0x61
  211. call _intrp; .byte 0x62
  212. call _intrp; .byte 0x63
  213. call _intrp; .byte 0x64
  214. call _intrp; .byte 0x65
  215. call _intrp; .byte 0x66
  216. call _intrp; .byte 0x67
  217. call _intrp; .byte 0x68
  218. call _intrp; .byte 0x69
  219. call _intrp; .byte 0x6a
  220. call _intrp; .byte 0x6b
  221. call _intrp; .byte 0x6c
  222. call _intrp; .byte 0x6d
  223. call _intrp; .byte 0x6e
  224. call _intrp; .byte 0x6f
  225. call _intrp; .byte 0x70
  226. call _intrp; .byte 0x71
  227. call _intrp; .byte 0x72
  228. call _intrp; .byte 0x73
  229. call _intrp; .byte 0x74
  230. call _intrp; .byte 0x75
  231. call _intrp; .byte 0x76
  232. call _intrp; .byte 0x77
  233. call _intrp; .byte 0x78
  234. call _intrp; .byte 0x79
  235. call _intrp; .byte 0x7a
  236. call _intrp; .byte 0x7b
  237. call _intrp; .byte 0x7c
  238. call _intrp; .byte 0x7d
  239. call _intrp; .byte 0x7e
  240. call _intrp; .byte 0x7f
  241. call _intrp; .byte 0x80
  242. call _intrp; .byte 0x81
  243. call _intrp; .byte 0x82
  244. call _intrp; .byte 0x83
  245. call _intrp; .byte 0x84
  246. call _intrp; .byte 0x85
  247. call _intrp; .byte 0x86
  248. call _intrp; .byte 0x87
  249. call _intrp; .byte 0x88
  250. call _intrp; .byte 0x89
  251. call _intrp; .byte 0x8a
  252. call _intrp; .byte 0x8b
  253. call _intrp; .byte 0x8c
  254. call _intrp; .byte 0x8d
  255. call _intrp; .byte 0x8e
  256. call _intrp; .byte 0x8f
  257. call _intrp; .byte 0x90
  258. call _intrp; .byte 0x91
  259. call _intrp; .byte 0x92
  260. call _intrp; .byte 0x93
  261. call _intrp; .byte 0x94
  262. call _intrp; .byte 0x95
  263. call _intrp; .byte 0x96
  264. call _intrp; .byte 0x97
  265. call _intrp; .byte 0x98
  266. call _intrp; .byte 0x99
  267. call _intrp; .byte 0x9a
  268. call _intrp; .byte 0x9b
  269. call _intrp; .byte 0x9c
  270. call _intrp; .byte 0x9d
  271. call _intrp; .byte 0x9e
  272. call _intrp; .byte 0x9f
  273. call _intrp; .byte 0xa0
  274. call _intrp; .byte 0xa1
  275. call _intrp; .byte 0xa2
  276. call _intrp; .byte 0xa3
  277. call _intrp; .byte 0xa4
  278. call _intrp; .byte 0xa5
  279. call _intrp; .byte 0xa6
  280. call _intrp; .byte 0xa7
  281. call _intrp; .byte 0xa8
  282. call _intrp; .byte 0xa9
  283. call _intrp; .byte 0xaa
  284. call _intrp; .byte 0xab
  285. call _intrp; .byte 0xac
  286. call _intrp; .byte 0xad
  287. call _intrp; .byte 0xae
  288. call _intrp; .byte 0xaf
  289. call _intrp; .byte 0xb0
  290. call _intrp; .byte 0xb1
  291. call _intrp; .byte 0xb2
  292. call _intrp; .byte 0xb3
  293. call _intrp; .byte 0xb4
  294. call _intrp; .byte 0xb5
  295. call _intrp; .byte 0xb6
  296. call _intrp; .byte 0xb7
  297. call _intrp; .byte 0xb8
  298. call _intrp; .byte 0xb9
  299. call _intrp; .byte 0xba
  300. call _intrp; .byte 0xbb
  301. call _intrp; .byte 0xbc
  302. call _intrp; .byte 0xbd
  303. call _intrp; .byte 0xbe
  304. call _intrp; .byte 0xbf
  305. call _intrp; .byte 0xc0
  306. call _intrp; .byte 0xc1
  307. call _intrp; .byte 0xc2
  308. call _intrp; .byte 0xc3
  309. call _intrp; .byte 0xc4
  310. call _intrp; .byte 0xc5
  311. call _intrp; .byte 0xc6
  312. call _intrp; .byte 0xc7
  313. call _intrp; .byte 0xc8
  314. call _intrp; .byte 0xc9
  315. call _intrp; .byte 0xca
  316. call _intrp; .byte 0xcb
  317. call _intrp; .byte 0xcc
  318. call _intrp; .byte 0xce
  319. call _intrp; .byte 0xce
  320. call _intrp; .byte 0xcf
  321. call _intrp; .byte 0xd0
  322. call _intrp; .byte 0xd1
  323. call _intrp; .byte 0xd2
  324. call _intrp; .byte 0xd3
  325. call _intrp; .byte 0xd4
  326. call _intrp; .byte 0xd5
  327. call _intrp; .byte 0xd6
  328. call _intrp; .byte 0xd7
  329. call _intrp; .byte 0xd8
  330. call _intrp; .byte 0xd9
  331. call _intrp; .byte 0xda
  332. call _intrp; .byte 0xdb
  333. call _intrp; .byte 0xdc
  334. call _intrp; .byte 0xdd
  335. call _intrp; .byte 0xde
  336. call _intrp; .byte 0xdf
  337. call _intrp; .byte 0xe0
  338. call _intrp; .byte 0xe1
  339. call _intrp; .byte 0xe2
  340. call _intrp; .byte 0xe3
  341. call _intrp; .byte 0xe4
  342. call _intrp; .byte 0xe5
  343. call _intrp; .byte 0xe6
  344. call _intrp; .byte 0xe7
  345. call _intrp; .byte 0xe8
  346. call _intrp; .byte 0xe9
  347. call _intrp; .byte 0xea
  348. call _intrp; .byte 0xeb
  349. call _intrp; .byte 0xec
  350. call _intrp; .byte 0xed
  351. call _intrp; .byte 0xee
  352. call _intrp; .byte 0xef
  353. call _intrp; .byte 0xf0
  354. call _intrp; .byte 0xf1
  355. call _intrp; .byte 0xf2
  356. call _intrp; .byte 0xf3
  357. call _intrp; .byte 0xf4
  358. call _intrp; .byte 0xf5
  359. call _intrp; .byte 0xf6
  360. call _intrp; .byte 0xf7
  361. call _intrp; .byte 0xf8
  362. call _intrp; .byte 0xf9
  363. call _intrp; .byte 0xfa
  364. call _intrp; .byte 0xfb
  365. call _intrp; .byte 0xfc
  366. call _intrp; .byte 0xfd
  367. call _intrp; .byte 0xfe
  368. call _intrp; .byte 0xff