l64idt.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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. .globl ire
  39. .globl irx
  40. .globl irxe
  41. // When we enter:
  42. // registers are NOT saved. We need to save them all.
  43. // return PC is on the stat8(%rsp). It should be left there.
  44. // @ (%rsp) is the PC from the vector table.
  45. // So indirecting on that will get us the interrupt #.
  46. // We need to get what the return PC is pointing to into %rdi.
  47. // We no longer need to make the stack look the same as in Plan 9
  48. // because the arg is in %rdi
  49. .globl _intrp
  50. _intrp:
  51. pushq %rax // bogus error code. Makes stack look like intre.
  52. // Except in this case, bogus error code is at 0(%rsp)
  53. // vno pointer is at 8(%rsp)
  54. MOVQ 8(%rsp), %rax
  55. // Now %rax points to the vector number.
  56. JMP _intrcommon
  57. // For intre, error is at top of stack on trap. But then we call here
  58. // from the interrupt vectors so error is at 8(%rsp).
  59. // I just realized I think intre means interrupt exception, e.g. page fault.
  60. .globl _intre
  61. _intre:
  62. ///jmp _intre
  63. // The error code has been pushed. How I love the x86.
  64. // So the error code is ABOVE the pointer to the vector #.
  65. XCHGQ %rax, (%rsp)
  66. // Now %rax points to the vector number.
  67. // When we get here:
  68. // %RAX points to our vector number, i.e. "return" pc from calls below.
  69. // For intrp, (%rsp) is bogus code, 8(%rsp) is pointer to vno
  70. // for intre, (%rsp) is pointer to vno, 8(%rsp) is error code.
  71. // The rest of the stack is the same.
  72. _intrcommon:
  73. // Get the vector number into %al
  74. MOVb (%rax), %al
  75. ANDQ $0xff, %rax
  76. // Put that at TOS (this is plan 9 argument style)
  77. XCHGQ %rax, 0(%rsp)
  78. // 0(%rsp) now has the vno
  79. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) /* old CS */
  80. JE _intrnested
  81. SWAPGS
  82. _intrnested:
  83. incq ire
  84. PUSHQ %r15
  85. PUSHQ %r14
  86. PUSHQ %r13
  87. PUSHQ %r12
  88. PUSHQ %r11
  89. PUSHQ %r10
  90. PUSHQ %r9
  91. PUSHQ %r8
  92. PUSHQ %rBP
  93. PUSHQ %rDI
  94. PUSHQ %rSI
  95. PUSHQ %rDX
  96. PUSHQ %rCX
  97. PUSHQ %rbx
  98. PUSHQ %rax
  99. MOVQ %rsp, %rdi // it's ok, we saved %rdi.
  100. CALL _trap
  101. .globl _intrr
  102. _intrr:
  103. incq irxe
  104. POPQ %rax
  105. POPQ %rbx
  106. POPQ %rCX
  107. POPQ %rDX
  108. POPQ %rSI
  109. POPQ %rDI
  110. POPQ %rBP
  111. POPQ %r8
  112. POPQ %r9
  113. POPQ %r10
  114. POPQ %r11
  115. POPQ %r12
  116. POPQ %r13
  117. POPQ %r14
  118. POPQ %r15
  119. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) /* old CS */
  120. JE _iretnested
  121. SWAPGS
  122. _iretnested:
  123. // Throw away:
  124. // The %rax you pushed (error code)
  125. // EIP from the vector table.
  126. ADDQ $16, %rsp
  127. incq irx
  128. iretq
  129. .globl idthandlers
  130. idthandlers:
  131. call _intrp; .byte IdtDE /* #DE Divide-by-Zero Error */
  132. call _intrp; .byte IdtDB /* #DB Debug */
  133. call _intrp; .byte IdtNMI /* #NMI Borked */
  134. call _intrp; .byte IdtBP /* #BP Breakpoint */
  135. call _intrp; .byte IdtOF /* #OF Overflow */
  136. call _intrp; .byte IdtBR /* #BR Bound-Range */
  137. call _intrp; .byte IdtUD /* #UD Invalid-Opcode */
  138. call _intrp; .byte IdtNM /* #NM Device-Not-Available */
  139. call _intre; .byte IdtDF /* #DF Double-Fault */
  140. call _intrp; .byte Idt09 /* reserved */
  141. call _intre; .byte IdtTS /* #TS Invalid-TSS */
  142. call _intre; .byte IdtNP /* #NP Segment-Not-Present */
  143. call _intre; .byte IdtSS /* #SS Stack */
  144. call _intre; .byte IdtGP /* #GP General-Protection */
  145. call _intre; .byte IdtPF /* #PF Page-Fault */
  146. call _intrp; .byte Idt0F /* reserved */
  147. call _intrp; .byte IdtMF /* #MF x87 FPE-Pending */
  148. call _intre; .byte IdtAC /* #AC Alignment-Check */
  149. call _intrp; .byte IdtMC /* #MC Machine-Check */
  150. call _intrp; .byte IdtXF /* #XF SIMD Floating-Point */
  151. call _intrp; .byte 0x14 /* reserved */
  152. call _intrp; .byte 0x15 /* reserved */
  153. call _intrp; .byte 0x16 /* reserved */
  154. call _intrp; .byte 0x17 /* reserved */
  155. call _intrp; .byte 0x18 /* reserved */
  156. call _intrp; .byte 0x19 /* reserved */
  157. call _intrp; .byte 0x1a /* reserved */
  158. call _intrp; .byte 0x1b /* reserved */
  159. call _intrp; .byte 0x1c /* reserved */
  160. call _intrp; .byte 0x1d /* reserved */
  161. call _intrp; .byte 0x1e /* reserved */
  162. call _intrp; .byte 0x1f /* reserved */
  163. call _intrp; .byte 0x20
  164. call _intrp; .byte 0x21
  165. call _intrp; .byte 0x22
  166. call _intrp; .byte 0x23
  167. call _intrp; .byte 0x24
  168. call _intrp; .byte 0x25
  169. call _intrp; .byte 0x26
  170. call _intrp; .byte 0x27
  171. call _intrp; .byte 0x28
  172. call _intrp; .byte 0x29
  173. call _intrp; .byte 0x2a
  174. call _intrp; .byte 0x2b
  175. call _intrp; .byte 0x2c
  176. call _intrp; .byte 0x2d
  177. call _intrp; .byte 0x2e
  178. call _intrp; .byte 0x2f
  179. call _intrp; .byte 0x30
  180. call _intrp; .byte 0x31
  181. call _intrp; .byte 0x32
  182. call _intrp; .byte 0x33
  183. call _intrp; .byte 0x34
  184. call _intrp; .byte 0x35
  185. call _intrp; .byte 0x36
  186. call _intrp; .byte 0x37
  187. call _intrp; .byte 0x38
  188. call _intrp; .byte 0x39
  189. call _intrp; .byte 0x3a
  190. call _intrp; .byte 0x3b
  191. call _intrp; .byte 0x3c
  192. call _intrp; .byte 0x3d
  193. call _intrp; .byte 0x3e
  194. call _intrp; .byte 0x3f
  195. call _intrp; .byte 0x40
  196. call _intrp; .byte 0x41
  197. call _intrp; .byte 0x42
  198. call _intrp; .byte 0x43
  199. call _intrp; .byte 0x44
  200. call _intrp; .byte 0x45
  201. call _intrp; .byte 0x46
  202. call _intrp; .byte 0x47
  203. call _intrp; .byte 0x48
  204. call _intrp; .byte 0x49
  205. call _intrp; .byte 0x4a
  206. call _intrp; .byte 0x4b
  207. call _intrp; .byte 0x4c
  208. call _intrp; .byte 0x4d
  209. call _intrp; .byte 0x4e
  210. call _intrp; .byte 0x4f
  211. call _intrp; .byte 0x50
  212. call _intrp; .byte 0x51
  213. call _intrp; .byte 0x52
  214. call _intrp; .byte 0x53
  215. call _intrp; .byte 0x54
  216. call _intrp; .byte 0x55
  217. call _intrp; .byte 0x56
  218. call _intrp; .byte 0x57
  219. call _intrp; .byte 0x58
  220. call _intrp; .byte 0x59
  221. call _intrp; .byte 0x5a
  222. call _intrp; .byte 0x5b
  223. call _intrp; .byte 0x5c
  224. call _intrp; .byte 0x5d
  225. call _intrp; .byte 0x5e
  226. call _intrp; .byte 0x5f
  227. call _intrp; .byte 0x60
  228. call _intrp; .byte 0x61
  229. call _intrp; .byte 0x62
  230. call _intrp; .byte 0x63
  231. call _intrp; .byte 0x64
  232. call _intrp; .byte 0x65
  233. call _intrp; .byte 0x66
  234. call _intrp; .byte 0x67
  235. call _intrp; .byte 0x68
  236. call _intrp; .byte 0x69
  237. call _intrp; .byte 0x6a
  238. call _intrp; .byte 0x6b
  239. call _intrp; .byte 0x6c
  240. call _intrp; .byte 0x6d
  241. call _intrp; .byte 0x6e
  242. call _intrp; .byte 0x6f
  243. call _intrp; .byte 0x70
  244. call _intrp; .byte 0x71
  245. call _intrp; .byte 0x72
  246. call _intrp; .byte 0x73
  247. call _intrp; .byte 0x74
  248. call _intrp; .byte 0x75
  249. call _intrp; .byte 0x76
  250. call _intrp; .byte 0x77
  251. call _intrp; .byte 0x78
  252. call _intrp; .byte 0x79
  253. call _intrp; .byte 0x7a
  254. call _intrp; .byte 0x7b
  255. call _intrp; .byte 0x7c
  256. call _intrp; .byte 0x7d
  257. call _intrp; .byte 0x7e
  258. call _intrp; .byte 0x7f
  259. call _intrp; .byte 0x80
  260. call _intrp; .byte 0x81
  261. call _intrp; .byte 0x82
  262. call _intrp; .byte 0x83
  263. call _intrp; .byte 0x84
  264. call _intrp; .byte 0x85
  265. call _intrp; .byte 0x86
  266. call _intrp; .byte 0x87
  267. call _intrp; .byte 0x88
  268. call _intrp; .byte 0x89
  269. call _intrp; .byte 0x8a
  270. call _intrp; .byte 0x8b
  271. call _intrp; .byte 0x8c
  272. call _intrp; .byte 0x8d
  273. call _intrp; .byte 0x8e
  274. call _intrp; .byte 0x8f
  275. call _intrp; .byte 0x90
  276. call _intrp; .byte 0x91
  277. call _intrp; .byte 0x92
  278. call _intrp; .byte 0x93
  279. call _intrp; .byte 0x94
  280. call _intrp; .byte 0x95
  281. call _intrp; .byte 0x96
  282. call _intrp; .byte 0x97
  283. call _intrp; .byte 0x98
  284. call _intrp; .byte 0x99
  285. call _intrp; .byte 0x9a
  286. call _intrp; .byte 0x9b
  287. call _intrp; .byte 0x9c
  288. call _intrp; .byte 0x9d
  289. call _intrp; .byte 0x9e
  290. call _intrp; .byte 0x9f
  291. call _intrp; .byte 0xa0
  292. call _intrp; .byte 0xa1
  293. call _intrp; .byte 0xa2
  294. call _intrp; .byte 0xa3
  295. call _intrp; .byte 0xa4
  296. call _intrp; .byte 0xa5
  297. call _intrp; .byte 0xa6
  298. call _intrp; .byte 0xa7
  299. call _intrp; .byte 0xa8
  300. call _intrp; .byte 0xa9
  301. call _intrp; .byte 0xaa
  302. call _intrp; .byte 0xab
  303. call _intrp; .byte 0xac
  304. call _intrp; .byte 0xad
  305. call _intrp; .byte 0xae
  306. call _intrp; .byte 0xaf
  307. call _intrp; .byte 0xb0
  308. call _intrp; .byte 0xb1
  309. call _intrp; .byte 0xb2
  310. call _intrp; .byte 0xb3
  311. call _intrp; .byte 0xb4
  312. call _intrp; .byte 0xb5
  313. call _intrp; .byte 0xb6
  314. call _intrp; .byte 0xb7
  315. call _intrp; .byte 0xb8
  316. call _intrp; .byte 0xb9
  317. call _intrp; .byte 0xba
  318. call _intrp; .byte 0xbb
  319. call _intrp; .byte 0xbc
  320. call _intrp; .byte 0xbd
  321. call _intrp; .byte 0xbe
  322. call _intrp; .byte 0xbf
  323. call _intrp; .byte 0xc0
  324. call _intrp; .byte 0xc1
  325. call _intrp; .byte 0xc2
  326. call _intrp; .byte 0xc3
  327. call _intrp; .byte 0xc4
  328. call _intrp; .byte 0xc5
  329. call _intrp; .byte 0xc6
  330. call _intrp; .byte 0xc7
  331. call _intrp; .byte 0xc8
  332. call _intrp; .byte 0xc9
  333. call _intrp; .byte 0xca
  334. call _intrp; .byte 0xcb
  335. call _intrp; .byte 0xcc
  336. call _intrp; .byte 0xce
  337. call _intrp; .byte 0xce
  338. call _intrp; .byte 0xcf
  339. call _intrp; .byte 0xd0
  340. call _intrp; .byte 0xd1
  341. call _intrp; .byte 0xd2
  342. call _intrp; .byte 0xd3
  343. call _intrp; .byte 0xd4
  344. call _intrp; .byte 0xd5
  345. call _intrp; .byte 0xd6
  346. call _intrp; .byte 0xd7
  347. call _intrp; .byte 0xd8
  348. call _intrp; .byte 0xd9
  349. call _intrp; .byte 0xda
  350. call _intrp; .byte 0xdb
  351. call _intrp; .byte 0xdc
  352. call _intrp; .byte 0xdd
  353. call _intrp; .byte 0xde
  354. call _intrp; .byte 0xdf
  355. call _intrp; .byte 0xe0
  356. call _intrp; .byte 0xe1
  357. call _intrp; .byte 0xe2
  358. call _intrp; .byte 0xe3
  359. call _intrp; .byte 0xe4
  360. call _intrp; .byte 0xe5
  361. call _intrp; .byte 0xe6
  362. call _intrp; .byte 0xe7
  363. call _intrp; .byte 0xe8
  364. call _intrp; .byte 0xe9
  365. call _intrp; .byte 0xea
  366. call _intrp; .byte 0xeb
  367. call _intrp; .byte 0xec
  368. call _intrp; .byte 0xed
  369. call _intrp; .byte 0xee
  370. call _intrp; .byte 0xef
  371. call _intrp; .byte 0xf0
  372. call _intrp; .byte 0xf1
  373. call _intrp; .byte 0xf2
  374. call _intrp; .byte 0xf3
  375. call _intrp; .byte 0xf4
  376. call _intrp; .byte 0xf5
  377. call _intrp; .byte 0xf6
  378. call _intrp; .byte 0xf7
  379. call _intrp; .byte 0xf8
  380. call _intrp; .byte 0xf9
  381. call _intrp; .byte 0xfa
  382. call _intrp; .byte 0xfb
  383. call _intrp; .byte 0xfc
  384. call _intrp; .byte 0xfd
  385. call _intrp; .byte 0xfe
  386. call _intrp; .byte 0xff