l64idt.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. * Interrupt/exception handling.
  3. */
  4. #include "amd64.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. xorq %rax, %rax
  101. /* if we came from user, stack traces end here */
  102. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 144(%rsp)
  103. cmovneq %rax, %rbp
  104. pushq %rax
  105. popfq /* clear all flags. is there something else we should clear too? */
  106. CALL _trap
  107. .globl _intrr
  108. _intrr:
  109. incq irxe
  110. POPQ %rax
  111. POPQ %rbx
  112. POPQ %rCX
  113. POPQ %rDX
  114. POPQ %rSI
  115. POPQ %rDI
  116. POPQ %rBP
  117. POPQ %r8
  118. POPQ %r9
  119. POPQ %r10
  120. POPQ %r11
  121. POPQ %r12
  122. POPQ %r13
  123. POPQ %r14
  124. POPQ %r15
  125. CMPW $SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) /* old CS */
  126. JE _iretnested
  127. SWAPGS
  128. _iretnested:
  129. // Throw away:
  130. // The %rax you pushed (error code)
  131. // EIP from the vector table.
  132. ADDQ $16, %rsp
  133. incq irx
  134. iretq
  135. .globl idthandlers
  136. idthandlers:
  137. call _intrp; .byte IdtDE /* #DE Divide-by-Zero Error */
  138. call _intrp; .byte IdtDB /* #DB Debug */
  139. call _intrp; .byte IdtNMI /* #NMI Borked */
  140. call _intrp; .byte IdtBP /* #BP Breakpoint */
  141. call _intrp; .byte IdtOF /* #OF Overflow */
  142. call _intrp; .byte IdtBR /* #BR Bound-Range */
  143. call _intrp; .byte IdtUD /* #UD Invalid-Opcode */
  144. call _intrp; .byte IdtNM /* #NM Device-Not-Available */
  145. call _intre; .byte IdtDF /* #DF Double-Fault */
  146. call _intrp; .byte Idt09 /* reserved */
  147. call _intre; .byte IdtTS /* #TS Invalid-TSS */
  148. call _intre; .byte IdtNP /* #NP Segment-Not-Present */
  149. call _intre; .byte IdtSS /* #SS Stack */
  150. call _intre; .byte IdtGP /* #GP General-Protection */
  151. call _intre; .byte IdtPF /* #PF Page-Fault */
  152. call _intrp; .byte Idt0F /* reserved */
  153. call _intrp; .byte IdtMF /* #MF x87 FPE-Pending */
  154. call _intre; .byte IdtAC /* #AC Alignment-Check */
  155. call _intrp; .byte IdtMC /* #MC Machine-Check */
  156. call _intrp; .byte IdtXF /* #XF SIMD Floating-Point */
  157. call _intrp; .byte 0x14 /* reserved */
  158. call _intrp; .byte 0x15 /* reserved */
  159. call _intrp; .byte 0x16 /* reserved */
  160. call _intrp; .byte 0x17 /* reserved */
  161. call _intrp; .byte 0x18 /* reserved */
  162. call _intrp; .byte 0x19 /* reserved */
  163. call _intrp; .byte 0x1a /* reserved */
  164. call _intrp; .byte 0x1b /* reserved */
  165. call _intrp; .byte 0x1c /* reserved */
  166. call _intrp; .byte 0x1d /* reserved */
  167. call _intrp; .byte 0x1e /* reserved */
  168. call _intrp; .byte 0x1f /* reserved */
  169. call _intrp; .byte 0x20
  170. call _intrp; .byte 0x21
  171. call _intrp; .byte 0x22
  172. call _intrp; .byte 0x23
  173. call _intrp; .byte 0x24
  174. call _intrp; .byte 0x25
  175. call _intrp; .byte 0x26
  176. call _intrp; .byte 0x27
  177. call _intrp; .byte 0x28
  178. call _intrp; .byte 0x29
  179. call _intrp; .byte 0x2a
  180. call _intrp; .byte 0x2b
  181. call _intrp; .byte 0x2c
  182. call _intrp; .byte 0x2d
  183. call _intrp; .byte 0x2e
  184. call _intrp; .byte 0x2f
  185. call _intrp; .byte 0x30
  186. call _intrp; .byte 0x31
  187. call _intrp; .byte 0x32
  188. call _intrp; .byte 0x33
  189. call _intrp; .byte 0x34
  190. call _intrp; .byte 0x35
  191. call _intrp; .byte 0x36
  192. call _intrp; .byte 0x37
  193. call _intrp; .byte 0x38
  194. call _intrp; .byte 0x39
  195. call _intrp; .byte 0x3a
  196. call _intrp; .byte 0x3b
  197. call _intrp; .byte 0x3c
  198. call _intrp; .byte 0x3d
  199. call _intrp; .byte 0x3e
  200. call _intrp; .byte 0x3f
  201. call _intrp; .byte 0x40
  202. call _intrp; .byte 0x41
  203. call _intrp; .byte 0x42
  204. call _intrp; .byte 0x43
  205. call _intrp; .byte 0x44
  206. call _intrp; .byte 0x45
  207. call _intrp; .byte 0x46
  208. call _intrp; .byte 0x47
  209. call _intrp; .byte 0x48
  210. call _intrp; .byte 0x49
  211. call _intrp; .byte 0x4a
  212. call _intrp; .byte 0x4b
  213. call _intrp; .byte 0x4c
  214. call _intrp; .byte 0x4d
  215. call _intrp; .byte 0x4e
  216. call _intrp; .byte 0x4f
  217. call _intrp; .byte 0x50
  218. call _intrp; .byte 0x51
  219. call _intrp; .byte 0x52
  220. call _intrp; .byte 0x53
  221. call _intrp; .byte 0x54
  222. call _intrp; .byte 0x55
  223. call _intrp; .byte 0x56
  224. call _intrp; .byte 0x57
  225. call _intrp; .byte 0x58
  226. call _intrp; .byte 0x59
  227. call _intrp; .byte 0x5a
  228. call _intrp; .byte 0x5b
  229. call _intrp; .byte 0x5c
  230. call _intrp; .byte 0x5d
  231. call _intrp; .byte 0x5e
  232. call _intrp; .byte 0x5f
  233. call _intrp; .byte 0x60
  234. call _intrp; .byte 0x61
  235. call _intrp; .byte 0x62
  236. call _intrp; .byte 0x63
  237. call _intrp; .byte 0x64
  238. call _intrp; .byte 0x65
  239. call _intrp; .byte 0x66
  240. call _intrp; .byte 0x67
  241. call _intrp; .byte 0x68
  242. call _intrp; .byte 0x69
  243. call _intrp; .byte 0x6a
  244. call _intrp; .byte 0x6b
  245. call _intrp; .byte 0x6c
  246. call _intrp; .byte 0x6d
  247. call _intrp; .byte 0x6e
  248. call _intrp; .byte 0x6f
  249. call _intrp; .byte 0x70
  250. call _intrp; .byte 0x71
  251. call _intrp; .byte 0x72
  252. call _intrp; .byte 0x73
  253. call _intrp; .byte 0x74
  254. call _intrp; .byte 0x75
  255. call _intrp; .byte 0x76
  256. call _intrp; .byte 0x77
  257. call _intrp; .byte 0x78
  258. call _intrp; .byte 0x79
  259. call _intrp; .byte 0x7a
  260. call _intrp; .byte 0x7b
  261. call _intrp; .byte 0x7c
  262. call _intrp; .byte 0x7d
  263. call _intrp; .byte 0x7e
  264. call _intrp; .byte 0x7f
  265. call _intrp; .byte 0x80
  266. call _intrp; .byte 0x81
  267. call _intrp; .byte 0x82
  268. call _intrp; .byte 0x83
  269. call _intrp; .byte 0x84
  270. call _intrp; .byte 0x85
  271. call _intrp; .byte 0x86
  272. call _intrp; .byte 0x87
  273. call _intrp; .byte 0x88
  274. call _intrp; .byte 0x89
  275. call _intrp; .byte 0x8a
  276. call _intrp; .byte 0x8b
  277. call _intrp; .byte 0x8c
  278. call _intrp; .byte 0x8d
  279. call _intrp; .byte 0x8e
  280. call _intrp; .byte 0x8f
  281. call _intrp; .byte 0x90
  282. call _intrp; .byte 0x91
  283. call _intrp; .byte 0x92
  284. call _intrp; .byte 0x93
  285. call _intrp; .byte 0x94
  286. call _intrp; .byte 0x95
  287. call _intrp; .byte 0x96
  288. call _intrp; .byte 0x97
  289. call _intrp; .byte 0x98
  290. call _intrp; .byte 0x99
  291. call _intrp; .byte 0x9a
  292. call _intrp; .byte 0x9b
  293. call _intrp; .byte 0x9c
  294. call _intrp; .byte 0x9d
  295. call _intrp; .byte 0x9e
  296. call _intrp; .byte 0x9f
  297. call _intrp; .byte 0xa0
  298. call _intrp; .byte 0xa1
  299. call _intrp; .byte 0xa2
  300. call _intrp; .byte 0xa3
  301. call _intrp; .byte 0xa4
  302. call _intrp; .byte 0xa5
  303. call _intrp; .byte 0xa6
  304. call _intrp; .byte 0xa7
  305. call _intrp; .byte 0xa8
  306. call _intrp; .byte 0xa9
  307. call _intrp; .byte 0xaa
  308. call _intrp; .byte 0xab
  309. call _intrp; .byte 0xac
  310. call _intrp; .byte 0xad
  311. call _intrp; .byte 0xae
  312. call _intrp; .byte 0xaf
  313. call _intrp; .byte 0xb0
  314. call _intrp; .byte 0xb1
  315. call _intrp; .byte 0xb2
  316. call _intrp; .byte 0xb3
  317. call _intrp; .byte 0xb4
  318. call _intrp; .byte 0xb5
  319. call _intrp; .byte 0xb6
  320. call _intrp; .byte 0xb7
  321. call _intrp; .byte 0xb8
  322. call _intrp; .byte 0xb9
  323. call _intrp; .byte 0xba
  324. call _intrp; .byte 0xbb
  325. call _intrp; .byte 0xbc
  326. call _intrp; .byte 0xbd
  327. call _intrp; .byte 0xbe
  328. call _intrp; .byte 0xbf
  329. call _intrp; .byte 0xc0
  330. call _intrp; .byte 0xc1
  331. call _intrp; .byte 0xc2
  332. call _intrp; .byte 0xc3
  333. call _intrp; .byte 0xc4
  334. call _intrp; .byte 0xc5
  335. call _intrp; .byte 0xc6
  336. call _intrp; .byte 0xc7
  337. call _intrp; .byte 0xc8
  338. call _intrp; .byte 0xc9
  339. call _intrp; .byte 0xca
  340. call _intrp; .byte 0xcb
  341. call _intrp; .byte 0xcc
  342. call _intrp; .byte 0xce
  343. call _intrp; .byte 0xce
  344. call _intrp; .byte 0xcf
  345. call _intrp; .byte 0xd0
  346. call _intrp; .byte 0xd1
  347. call _intrp; .byte 0xd2
  348. call _intrp; .byte 0xd3
  349. call _intrp; .byte 0xd4
  350. call _intrp; .byte 0xd5
  351. call _intrp; .byte 0xd6
  352. call _intrp; .byte 0xd7
  353. call _intrp; .byte 0xd8
  354. call _intrp; .byte 0xd9
  355. call _intrp; .byte 0xda
  356. call _intrp; .byte 0xdb
  357. call _intrp; .byte 0xdc
  358. call _intrp; .byte 0xdd
  359. call _intrp; .byte 0xde
  360. call _intrp; .byte 0xdf
  361. call _intrp; .byte 0xe0
  362. call _intrp; .byte 0xe1
  363. call _intrp; .byte 0xe2
  364. call _intrp; .byte 0xe3
  365. call _intrp; .byte 0xe4
  366. call _intrp; .byte 0xe5
  367. call _intrp; .byte 0xe6
  368. call _intrp; .byte 0xe7
  369. call _intrp; .byte 0xe8
  370. call _intrp; .byte 0xe9
  371. call _intrp; .byte 0xea
  372. call _intrp; .byte 0xeb
  373. call _intrp; .byte 0xec
  374. call _intrp; .byte 0xed
  375. call _intrp; .byte 0xee
  376. call _intrp; .byte 0xef
  377. call _intrp; .byte 0xf0
  378. call _intrp; .byte 0xf1
  379. call _intrp; .byte 0xf2
  380. call _intrp; .byte 0xf3
  381. call _intrp; .byte 0xf4
  382. call _intrp; .byte 0xf5
  383. call _intrp; .byte 0xf6
  384. call _intrp; .byte 0xf7
  385. call _intrp; .byte 0xf8
  386. call _intrp; .byte 0xf9
  387. call _intrp; .byte 0xfa
  388. call _intrp; .byte 0xfb
  389. call _intrp; .byte 0xfc
  390. call _intrp; .byte 0xfd
  391. call _intrp; .byte 0xfe
  392. call _intrp; .byte 0xff