Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.6 KiB

  1. // TITLE("Thread Startup")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // threadbg.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements the MIPS machine dependent code necessary to
  11. // startup a thread in kernel mode.
  12. //
  13. // Author:
  14. //
  15. // Bernard Lint 19-Mar-1996
  16. //
  17. // Environment:
  18. //
  19. // Kernel mode only, IRQL APC_LEVEL.
  20. //
  21. // Revision History:
  22. //
  23. // Based on MIPS version (David N. Cutler (davec) 28-Mar-1990)
  24. //
  25. //--
  26. #include "ksia64.h"
  27. //
  28. // Globals used
  29. //
  30. PublicFunction(KeBugCheck)
  31. PublicFunction(KiRestoreExceptionFrame)
  32. PublicFunction(KiExceptionExit)
  33. SBTTL("Thread Startup")
  34. //++
  35. //
  36. // Routine Description:
  37. //
  38. // This routine is called at thread startup. Its function is to call the
  39. // initial thread procedure. If control returns from the initial thread
  40. // procedure and a user mode context was established when the thread
  41. // was initialized, then the user mode context is restored and control
  42. // is transfered to user mode. Otherwise a bug check will occur.
  43. //
  44. // When this thread was created, a switch frame for SwapContext was pushed
  45. // onto the stack and initialized such that SwapContext will return to
  46. // the first instruction of this routine when this thread is first switched to.
  47. //
  48. // Arguments:
  49. //
  50. // s0 (saved) - Supplies a boolean value that specified whether a user
  51. // mode thread context was established when the thread was initialized.
  52. //
  53. // s1 (saved) - Supplies the starting context parameter for the initial
  54. // thread procedure.
  55. //
  56. // s2 (saved) - Supplies the starting address of the initial thread routine.
  57. //
  58. // N.B. This is a function pointer.
  59. //
  60. // s3 - Supplies the starting address of the initial system routine.
  61. //
  62. // N.B. This is an entry point.
  63. //
  64. // On entry:
  65. //
  66. // Since SwapConext deallocates the switch frame sp points to either:
  67. // for system thread sp -> bottom of kernel stack;
  68. // for user thread sp -> exception frame (or higher fp savearea
  69. // if not FPLAZY)
  70. //
  71. // Return Value:
  72. //
  73. // None.
  74. //
  75. //--
  76. NESTED_ENTRY(KiThreadDispatch)
  77. //
  78. // N.B. The following code is never executed. Its purpose is to allow the
  79. // kernel debugger to walk call frames backwards through thread startup
  80. // and to support get/set user context.
  81. //
  82. .regstk 0,2,2,0
  83. .prologue 0xC, loc0
  84. .fframe ExceptionFrameLength
  85. add sp = -ExceptionFrameLength, sp
  86. ;;
  87. add t0 = ExFltS19+STACK_SCRATCH_AREA, sp
  88. add t1 = ExFltS18+STACK_SCRATCH_AREA, sp
  89. ;;
  90. .save.gf 0x0, 0xC0000
  91. stf.spill [t0] = fs19, ExFltS17-ExFltS19
  92. stf.spill [t1] = fs18, ExFltS16-ExFltS18
  93. ;;
  94. .save.gf 0x0, 0x30000
  95. stf.spill [t0] = fs17, ExFltS15-ExFltS17
  96. stf.spill [t1] = fs16, ExFltS14-ExFltS16
  97. mov t10 = bs4
  98. ;;
  99. .save.gf 0x0, 0xC000
  100. stf.spill [t0] = fs15, ExFltS13-ExFltS15
  101. stf.spill [t1] = fs14, ExFltS12-ExFltS14
  102. mov t11 = bs3
  103. ;;
  104. .save.gf 0x0, 0x3000
  105. stf.spill [t0] = fs13, ExFltS11-ExFltS13
  106. stf.spill [t1] = fs12, ExFltS10-ExFltS12
  107. mov t12 = bs2
  108. ;;
  109. .save.gf 0x0, 0xC00
  110. stf.spill [t0] = fs11, ExFltS9-ExFltS11
  111. stf.spill [t1] = fs10, ExFltS8-ExFltS10
  112. mov t13 = bs1
  113. ;;
  114. .save.gf 0x0, 0x300
  115. stf.spill [t0] = fs9, ExFltS7-ExFltS9
  116. stf.spill [t1] = fs8, ExFltS6-ExFltS8
  117. mov t14 = bs0
  118. ;;
  119. .save.gf 0x0, 0xC0
  120. stf.spill [t0] = fs7, ExFltS5-ExFltS7
  121. stf.spill [t1] = fs6, ExFltS4-ExFltS6
  122. mov t15 = ar.lc
  123. ;;
  124. .save.gf 0x0, 0x30
  125. stf.spill [t0] = fs5, ExFltS3-ExFltS5
  126. stf.spill [t1] = fs4, ExFltS2-ExFltS4
  127. ;;
  128. .save.f 0xC
  129. stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
  130. stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
  131. ;;
  132. .save.f 0x3
  133. stf.spill [t0] = fs1, ExBrS4-ExFltS1 // save fs1
  134. stf.spill [t1] = fs0, ExBrS3-ExFltS0 // save fs0
  135. ;;
  136. .save.b 0x18
  137. st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
  138. st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
  139. ;;
  140. .save.b 0x6
  141. st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
  142. st8 [t1] = t13, ExIntS2-ExBrS1 // save bs1
  143. ;;
  144. .save.b 0x1
  145. st8 [t0] = t14, ExIntS3-ExBrS0 // save bs0
  146. ;;
  147. .save.gf 0xC, 0x0
  148. .mem.offset 0,0
  149. st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
  150. .mem.offset 8,0
  151. st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
  152. ;;
  153. .save.gf 0x3, 0x0
  154. .mem.offset 0,0
  155. st8.spill [t0] = s1, ExApLC-ExIntS1 // save s1
  156. .mem.offset 8,0
  157. st8.spill [t1] = s0, ExApEC-ExIntS0 // save s0
  158. ;;
  159. .savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
  160. st8 [t1] = t16, ExIntNats-ExApEC
  161. mov t4 = ar.unat // captured Nats of s0-s3
  162. ;;
  163. .savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
  164. st8 [t0] = t15
  165. .savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
  166. st8 [t1] = t4 // save Nats of s0-s3
  167. ;;
  168. ALTERNATE_ENTRY(KiThreadStartup)
  169. alloc t0 = 0,2,2,0 // allocate call frame
  170. mov savedpfs = zero // setup bogus brp and pfs
  171. mov savedbrp = zero // to stop stack unwind
  172. // by the debugger
  173. ;;
  174. PROLOGUE_END
  175. //
  176. // restore the preserved states from the switch frame and then deallocate it
  177. //
  178. add out0 = SwExFrame+STACK_SCRATCH_AREA,sp
  179. br.call.sptk brp = KiRestoreExceptionFrame
  180. ;;
  181. //
  182. // Lower IRQL to APC_LEVEL
  183. //
  184. add sp = SwitchFrameLength, sp
  185. mov bt0 = s3 // setup call to system routine
  186. mov t0 = APC_LEVEL
  187. ;;
  188. SET_IRQL(t0)
  189. mov out0 = s2 // arg 1 = thread routine (a function pointer)
  190. mov out1 = s1 // arg 2 = thread context
  191. br.call.sptk brp = bt0 // call system routine
  192. ;;
  193. //
  194. // Finish in common exception exit code which will restore the nonvolatile
  195. // registers and exit to user mode.
  196. //
  197. // N.B. predicate register alias pUstk & pKstk must be the same as trap.s
  198. // and they must be set up correctly upon entry into KiExceptionExit.
  199. //
  200. //
  201. // If pKstk is set, an attempt was made to enter user mode for a thread
  202. // that has no user mode context. Generate a bug check.
  203. //
  204. pUstk = ps3
  205. pKstk = ps4
  206. cmp.eq pKstk, pUstk = zero, s0 // if s0 is zero, no user context (system thread)
  207. mov out0 = NO_USER_MODE_CONTEXT // set bug check code
  208. (pKstk) br.call.spnt brp = KeBugCheck
  209. //
  210. // Set up for branch to KiExceptionExit
  211. //
  212. // s0 = trap frame
  213. // s1 = exception frame
  214. //
  215. //
  216. // Interrupts must be disabled before calling KiExceptionExit
  217. // because the unwind code cannot unwind from that point.
  218. //
  219. FAST_DISABLE_INTERRUPTS
  220. add s1 = STACK_SCRATCH_AREA, sp
  221. add s0 = ExceptionFrameLength, sp
  222. br KiExceptionExit
  223. ;;
  224. NESTED_EXIT(KiThreadDispatch)