contexta.S 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*++
  2. Copyright (c) 2016 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. contexta.S
  9. Abstract:
  10. This module implements assembly functionality for working with ucontext
  11. structure.
  12. Author:
  13. Evan Green 8-Sep-2016
  14. Environment:
  15. User Mode C Library
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/x86.inc>
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ----------------------------------------------------------------------- Code
  26. //
  27. //
  28. // .text specifies that this code belongs in the executable section.
  29. //
  30. // .code32 specifies that this is 32-bit protected mode code.
  31. //
  32. .text
  33. .code32
  34. //
  35. // LIBC_API
  36. // int
  37. // getcontext (
  38. // ucontext_t *Context
  39. // )
  40. //
  41. /*++
  42. Routine Description:
  43. This routine saves the current user context into the given structure,
  44. including the machine registers, signal mask, and execution stack pointer.
  45. If restored, the returned context will appear to execute at the return from
  46. this function.
  47. Arguments:
  48. Context - Supplies a pointer where the current context is saved.
  49. Return Value:
  50. 0 on success.
  51. -1 on failure, and errno will be set to contain more information.
  52. --*/
  53. EXPORTED_FUNCTION(getcontext)
  54. movl 4(%esp), %eax # Get the context.
  55. addl $SIGNAL_CONTEXT_SIZE, %eax # Get to the TRAP_FRAME part.
  56. movl %ecx, TRAP_ECX(%eax) # Save ecx.
  57. xorl %ecx, %ecx # Clear a register.
  58. movw %cs, %cx # Get DS.
  59. movl %ecx, TRAP_CS(%eax) # Save CS.
  60. movw %ds, %cx # Get DS.
  61. movl %ecx, TRAP_DS(%eax) # Save DS.
  62. movw %es, %cx # Get ES.
  63. movl %ecx, TRAP_ES(%eax) # Save ES.
  64. movw %fs, %cx # Get FS.
  65. movl %ecx, TRAP_FS(%eax) # Save FS.
  66. movw %gs, %cx # Get GS.
  67. movl %ecx, TRAP_GS(%eax) # Save GS.
  68. movw %ss, %cx # Get SS.
  69. movl %ecx, TRAP_SS(%eax) # Save SS.
  70. xorl %ecx, %ecx # Clear a register.
  71. movl %ecx, TRAP_EAX(%eax) # Save a zeroed eax.
  72. movl %ebx, TRAP_EBX(%eax) # Save ebx.
  73. movl %edx, TRAP_EDX(%eax) # Save edx.
  74. movl %esi, TRAP_ESI(%eax) # Save esi.
  75. movl %edi, TRAP_EDI(%eax) # Save edi.
  76. movl %ebp, TRAP_EBP(%eax) # Save ebp.
  77. movl %ecx, TRAP_ERRORCODE(%eax) # Save zeroed error code.
  78. movl (%esp), %ecx # Get the return address.
  79. movl %ecx, TRAP_EIP(%eax) # Save the instruction pointer.
  80. pushfl # Push eflags.
  81. popl %ecx # Get eflags.
  82. movl %ecx, TRAP_EFLAGS(%eax) # Save eflags.
  83. leal 4(%esp), %ecx # Get the stack pointer (w/o return addr).
  84. movl %ecx, TRAP_ESP(%eax) # Save that as esp.
  85. pushl %ecx # Push stack pointer.
  86. movl 8(%esp), %eax # Get the context pointer.
  87. pushl %eax # Push it as the first argument.
  88. call ClpGetContext # Call the C helper.
  89. addl $8, %esp # Pop the arguments.
  90. ret # Return whatever the C routine returned.
  91. END_FUNCTION(getcontext)
  92. //
  93. // LIBC_API
  94. // int
  95. // setcontext (
  96. // const ucontext_t *Context
  97. // )
  98. //
  99. /*++
  100. Routine Description:
  101. This routine restores a previous execution context into the current
  102. processor.
  103. Arguments:
  104. Context - Supplies a pointer to the previously saved context to restore.
  105. Return Value:
  106. Does not return on success, as execution continues from the new context.
  107. -1 on failure, and errno will be set to contain more information.
  108. --*/
  109. EXPORTED_FUNCTION(setcontext)
  110. movl 4(%esp), %eax # Get the argument.
  111. pushl %eax
  112. call ClpSetContext # Call the C helper.
  113. movl 8(%esp), %ecx # Get the argument again.
  114. addl $SIGNAL_CONTEXT_SIZE, %ecx # Get to the TRAP_FRAME part.
  115. movl TRAP_DS(%ecx), %eax # Get DS.
  116. movw %ax, %ds # Restore DS.
  117. movl TRAP_ES(%ecx), %eax # Get ES.
  118. movw %ax, %es # Restore ES.
  119. movl TRAP_FS(%ecx), %eax # Get FS.
  120. movw %ax, %fs # Restore FS.
  121. movl TRAP_GS(%ecx), %eax # Get GS.
  122. movw %ax, %gs # Restore GS.
  123. movl TRAP_SS(%ecx), %eax # Get SS.
  124. movw %ax, %ss # Restore SS.
  125. movl TRAP_EBP(%ecx), %ebp # Restore ebp.
  126. movl TRAP_EDI(%ecx), %edi # Restore edi.
  127. movl TRAP_ESI(%ecx), %esi # Restore esi.
  128. movl TRAP_EDX(%ecx), %edx # Restore edx.
  129. movl TRAP_EBX(%ecx), %ebx # Restore ebx.
  130. movl TRAP_EFLAGS(%ecx), %eax # Get eflags.
  131. movl %eax, (%esp) # "Push" eflags into old unpopped argument.
  132. popfl # Pop eflags/old argument off the stack.
  133. movl TRAP_EAX(%ecx), %eax # Restore eax as return value.
  134. //
  135. // This last part gets a little fishy depending on where the context
  136. // structure is. If the new esp is on the same stack but greater than this
  137. // one, then this code runs the risk of taking a signal, which might
  138. // clobber the context before restoring EIP can be done. Hopefully that
  139. // doesn't happen.
  140. //
  141. movl TRAP_ESP(%ecx), %esp # Restore stack pointer.
  142. jmp *TRAP_EIP(%ecx) # Return.
  143. END_FUNCTION(setcontext)
  144. //
  145. // __NO_RETURN
  146. // void
  147. // ClpContextStart (
  148. // void (*StartFunction)(),
  149. // ...
  150. // )
  151. //
  152. /*++
  153. Routine Description:
  154. This routine is a small trampoline that calls the function specified in
  155. makecontext.
  156. Arguments:
  157. StartFunction - Supplies a pointer to the function to call.
  158. ... - Supplies the arguments the start function takes.
  159. Return Value:
  160. This routine does not return.
  161. --*/
  162. FUNCTION(ClpContextStart)
  163. popl %eax # Get the function to call.
  164. call *%eax # Make it rain.
  165. movl %esi, %esp # Pop the function and all arguments off.
  166. call ClpContextEnd # Call the C helper to switch contexts.
  167. hlt # Execution should never reach here.
  168. END_FUNCTION(ClpContextStart)
  169. //
  170. // VOID
  171. // ClpFxSave (
  172. // PFPU_CONTEXT Buffer
  173. // )
  174. //
  175. /*++
  176. Routine Description:
  177. This routine saves the current x87 FPU, MMX, XMM, and MXCSR registers to a
  178. 512 byte memory location.
  179. Arguments:
  180. Buffer - Supplies a pointer to the buffer where the information will be
  181. saved. This buffer must be 16-byte aligned.
  182. Return Value:
  183. None.
  184. --*/
  185. FUNCTION(ClpFxSave)
  186. movl 4(%esp), %eax # Get the buffer parameter.
  187. fxsave (%eax) # Save the state into there.
  188. ret
  189. END_FUNCTION(ClpFxSave)
  190. //
  191. // VOID
  192. // ClpFxRestore (
  193. // PFPU_CONTEXT Buffer
  194. // )
  195. //
  196. /*++
  197. Routine Description:
  198. This routine restores the current x87 FPU, MMX, XMM, and MXCSR registers
  199. from a 512 byte memory location.
  200. Arguments:
  201. Buffer - Supplies a pointer to the buffer where the information will be
  202. loaded from. This buffer must be 16-byte aligned.
  203. Return Value:
  204. None.
  205. --*/
  206. FUNCTION(ClpFxRestore)
  207. movl 4(%esp), %eax # Get the buffer parameter.
  208. fxrstor (%eax) # Load the state from there.
  209. ret
  210. END_FUNCTION(ClpFxRestore)
  211. //
  212. // VOID
  213. // ClpFSave (
  214. // PFPU_CONTEXT Buffer
  215. // )
  216. //
  217. /*++
  218. Routine Description:
  219. This routine saves the current x87 FPU (floating point unit) state.
  220. Arguments:
  221. Buffer - Supplies a pointer to the buffer where the information will be
  222. saved. This buffer must be 16-byte aligned.
  223. Return Value:
  224. None.
  225. --*/
  226. FUNCTION(ClpFSave)
  227. movl 4(%esp), %eax # Get the buffer parameter.
  228. fsave (%eax) # Save the state into there.
  229. ret
  230. END_FUNCTION(ClpFSave)
  231. //
  232. // VOID
  233. // ClpFRestore (
  234. // PFPU_CONTEXT Buffer
  235. // )
  236. //
  237. /*++
  238. Routine Description:
  239. This routine restores the x87 FPU (floating point unit) state.
  240. Arguments:
  241. Buffer - Supplies a pointer to the buffer where the information will be
  242. loaded from. This buffer must be 16-byte aligned.
  243. Return Value:
  244. None.
  245. --*/
  246. FUNCTION(ClpFRestore)
  247. movl 4(%esp), %eax # Get the buffer parameter.
  248. frstor (%eax) # Load the state from there.
  249. ret
  250. END_FUNCTION(ClpFRestore)