Leaked source code of windows server 2003
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.

366 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. thredini.c
  5. Abstract:
  6. This module implements the machine dependent functions to set the initial
  7. context and data alignment handling mode for a process or thread object.
  8. Author:
  9. David N. Cutler (davec) 1-Apr-1990
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. 3-19-96 Bernard Lint (blint) Conversion to IA64 (from PPC and MIPS versions)
  14. --*/
  15. #include "ki.h"
  16. VOID
  17. KeContextToKframesSpecial (
  18. IN PKTHREAD Thread,
  19. IN OUT PKTRAP_FRAME TrapFrame,
  20. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  21. IN PCONTEXT ContextFrame,
  22. IN ULONG ContextFlags
  23. );
  24. //
  25. // The following assert macros are used to check that an input object is
  26. // really the proper type.
  27. //
  28. #define ASSERT_PROCESS(E) { \
  29. ASSERT((E)->Header.Type == ProcessObject); \
  30. }
  31. #define ASSERT_THREAD(E) { \
  32. ASSERT((E)->Header.Type == ThreadObject); \
  33. }
  34. VOID
  35. KiInitializeContextThread (
  36. IN PKTHREAD Thread,
  37. IN PKSYSTEM_ROUTINE SystemRoutine,
  38. IN PKSTART_ROUTINE StartRoutine OPTIONAL,
  39. IN PVOID StartContext OPTIONAL,
  40. IN PCONTEXT ContextRecord OPTIONAL
  41. )
  42. /*++
  43. Routine Description:
  44. This function initializes the machine dependent context of a thread object.
  45. Actually, what it does is to lay out the stack for the thread so that
  46. it contains a stack frame that will be picked up by SwapContext and
  47. returned thru, resulting in a transfer of control to KiThreadStartup.
  48. In otherwords, we lay out a stack with a stack frame that looks as if
  49. SwapContext had been called just before the first instruction in
  50. KiThreadStartup.
  51. N.B. This function does not check the accessibility of the context record.
  52. It is assumed the the caller of this routine is either prepared to
  53. handle access violations or has probed and copied the context record
  54. as appropriate.
  55. N.B. Arguments to the new thread are passed in the Swap Frame preserved registers
  56. s0 - s3 which are restored by Swap Context when thread execution begins.
  57. Arguments:
  58. Thread - Supplies a pointer to a dispatcher object of type thread.
  59. SystemRoutine - Supplies a pointer to the system function that is to be
  60. called when the thread is first scheduled for execution.
  61. N.B. This is the routine entry point, not a function pointer (plabel pointer).
  62. StartRoutine - Supplies an optional pointer to a function that is to be
  63. called after the system has finished initializing the thread. This
  64. parameter is specified if the thread is a system thread and will
  65. execute totally in kernel mode.
  66. N.B. This is the routine function pointer (plabel pointer).
  67. StartContext - Supplies an optional pointer to an arbitrary data structure
  68. which will be passed to the StartRoutine as a parameter. This
  69. parameter is specified if the thread is a system thread and will
  70. execute totally in kernel mode.
  71. ContextRecord - Supplies an optional pointer a context frame which contains
  72. the initial user mode state of the thread. This parameter is specified
  73. if the thread is a user thread and will execute in user mode. If this
  74. parameter is not specified, then the Teb parameter is ignored.
  75. Return Value:
  76. None.
  77. --*/
  78. {
  79. PKSWITCH_FRAME SwFrame;
  80. PKEXCEPTION_FRAME ExFrame;
  81. ULONG_PTR InitialStack;
  82. PKTRAP_FRAME TrFrame;
  83. //
  84. // Set up the thread backing store pointers from the initial stack pointers.
  85. //
  86. InitialStack = (ULONG_PTR)Thread->InitialStack;
  87. Thread->InitialBStore = (PVOID)InitialStack;
  88. Thread->BStoreLimit = (PVOID)(InitialStack + KERNEL_BSTORE_SIZE);
  89. //
  90. // If a context frame is specified, then initialize a trap frame and
  91. // and an exception frame with the specified user mode context. Also
  92. // allocate the switch frame.
  93. //
  94. if (ARGUMENT_PRESENT(ContextRecord)) {
  95. TrFrame = (PKTRAP_FRAME)((InitialStack)
  96. - KTHREAD_STATE_SAVEAREA_LENGTH
  97. - KTRAP_FRAME_LENGTH);
  98. RtlZeroMemory(TrFrame, KTHREAD_STATE_SAVEAREA_LENGTH + KTRAP_FRAME_LENGTH);
  99. ExFrame = (PKEXCEPTION_FRAME)(((ULONG_PTR)TrFrame +
  100. STACK_SCRATCH_AREA -
  101. sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
  102. SwFrame = (PKSWITCH_FRAME)(((ULONG_PTR)ExFrame -
  103. sizeof(KSWITCH_FRAME)) & ~((ULONG_PTR)15));
  104. //
  105. // Set the trap frame marker so get context does not think this is
  106. // a system call frame.
  107. //
  108. TrFrame->EOFMarker = (ULONGLONG)(KTRAP_FRAME_EOF | EXCEPTION_FRAME);
  109. KeContextToKframesSpecial(Thread, TrFrame, ExFrame,
  110. ContextRecord,
  111. ContextRecord->ContextFlags | CONTEXT_CONTROL);
  112. //
  113. // Set the saved previous processor mode in the trap frame and the
  114. // previous processor mode in the thread object to user mode.
  115. //
  116. TrFrame->PreviousMode = UserMode;
  117. Thread->PreviousMode = UserMode;
  118. //
  119. // Initialize the FPSR for user mode
  120. //
  121. TrFrame->StFPSR = USER_FPSR_INITIAL;
  122. //
  123. // Initialize the user TEB pointer in the trap frame
  124. //
  125. TrFrame->IntTeb = (ULONGLONG)Thread->Teb;
  126. } else {
  127. SwFrame = (PKSWITCH_FRAME)((InitialStack) - sizeof(KSWITCH_FRAME));
  128. //
  129. // Set the previous mode in thread object to kernel.
  130. //
  131. Thread->PreviousMode = KernelMode;
  132. }
  133. //
  134. // Initialize context switch frame and set thread start up parameters.
  135. // The Swap return pointer and SystemRoutine are entry points, not function pointers.
  136. //
  137. RtlZeroMemory((PVOID)SwFrame, sizeof(KSWITCH_FRAME)); // init all to 0
  138. SwFrame->SwitchRp = ((PPLABEL_DESCRIPTOR)(ULONG_PTR)KiThreadStartup)->EntryPoint;
  139. SwFrame->SwitchExceptionFrame.IntS0 = (ULONGLONG)ContextRecord;
  140. SwFrame->SwitchExceptionFrame.IntS1 = (ULONGLONG)StartContext;
  141. SwFrame->SwitchExceptionFrame.IntS2 = (ULONGLONG)StartRoutine;
  142. SwFrame->SwitchExceptionFrame.IntS3 =
  143. ((PPLABEL_DESCRIPTOR)(ULONG_PTR)SystemRoutine)->EntryPoint;
  144. SwFrame->SwitchFPSR = FPSR_FOR_KERNEL;
  145. SwFrame->SwitchBsp = (ULONGLONG)Thread->InitialBStore;
  146. Thread->KernelBStore = Thread->InitialBStore;
  147. Thread->KernelStack = (PVOID)((ULONG_PTR)SwFrame-STACK_SCRATCH_AREA);
  148. if (Thread->Teb) {
  149. PKAPPLICATION_REGISTERS AppRegs;
  150. AppRegs = GET_APPLICATION_REGISTER_SAVEAREA(Thread->StackBase);
  151. //
  152. // Zero the thread save area in the stack so that information does
  153. // does not leak out.
  154. //
  155. RtlZeroMemory(AppRegs, KTHREAD_STATE_SAVEAREA_LENGTH);
  156. // AppRegs->Ar21 = 0; ContextRecord->StFCR;
  157. //
  158. // Ar24 is EFlags. Need to set up a value that is good for iVE
  159. // Based on i386 eflags SANITIZE_FLAGS
  160. // This is simplier, though since never running i386 in kernel
  161. // mode
  162. AppRegs->Ar24 = EFLAGS_INTERRUPT_MASK | (((ULONG) ContextRecord->Eflag) & EFLAGS_USER_SANITIZE);
  163. AppRegs->Ar26 = (ULONGLONG) USER_DATA_DESCRIPTOR;
  164. AppRegs->Ar27 = (((ULONGLONG) CR4_VME | CR4_FXSR | CR4_XMMEXCPT) << 32)
  165. | (CR0_PE | CFLG_II);
  166. AppRegs->Ar28 = SANITIZE_AR28_FSR (ContextRecord->StFSR, UserMode);
  167. AppRegs->Ar29 = SANITIZE_AR29_FIR (ContextRecord->StFIR, UserMode);
  168. AppRegs->Ar30 = SANITIZE_AR30_FDR (ContextRecord->StFDR, UserMode);
  169. }
  170. return;
  171. }
  172. BOOLEAN
  173. KeSetAutoAlignmentProcess (
  174. IN PRKPROCESS Process,
  175. IN BOOLEAN Enable
  176. )
  177. /*++
  178. Routine Description:
  179. This function sets the data alignment handling mode for the specified
  180. process and returns the previous data alignment handling mode.
  181. Arguments:
  182. Process - Supplies a pointer to a dispatcher object of type process.
  183. Enable - Supplies a boolean value that determines the handling of data
  184. alignment exceptions for the process. A value of TRUE causes all
  185. data alignment exceptions to be automatically handled by the kernel.
  186. A value of FALSE causes all data alignment exceptions to be actually
  187. raised as exceptions.
  188. Return Value:
  189. A value of TRUE is returned if data alignment exceptions were
  190. previously automatically handled by the kernel. Otherwise, a value
  191. of FALSE is returned.
  192. --*/
  193. {
  194. KIRQL OldIrql;
  195. BOOLEAN Previous;
  196. ASSERT_PROCESS(Process);
  197. //
  198. // Raise IRQL to dispatcher level and lock dispatcher database.
  199. //
  200. KiLockDispatcherDatabase(&OldIrql);
  201. //
  202. // Capture the previous data alignment handling mode and set the
  203. // specified data alignment mode.
  204. //
  205. Previous = Process->AutoAlignment;
  206. Process->AutoAlignment = Enable;
  207. //
  208. // Unlock dispatcher database, lower IRQL to its previous value, and
  209. // return the previous data alignment mode.
  210. //
  211. KiUnlockDispatcherDatabase(OldIrql);
  212. return Previous;
  213. }
  214. BOOLEAN
  215. KeSetAutoAlignmentThread (
  216. IN PKTHREAD Thread,
  217. IN BOOLEAN Enable
  218. )
  219. /*++
  220. Routine Description:
  221. This function sets the data alignment handling mode for the specified
  222. thread and returns the previous data alignment handling mode.
  223. Arguments:
  224. Thread - Supplies a pointer to a dispatcher object of type thread.
  225. Enable - Supplies a boolean value that determines the handling of data
  226. alignment exceptions for the thread. A value of TRUE causes all
  227. data alignment exceptions to be automatically handled by the kernel.
  228. A value of FALSE causes all data alignment exceptions to be actually
  229. raised as exceptions.
  230. Return Value:
  231. A value of TRUE is returned if data alignment exceptions were
  232. previously automatically handled by the kernel. Otherwise, a value
  233. of FALSE is returned.
  234. --*/
  235. {
  236. KIRQL OldIrql;
  237. BOOLEAN Previous;
  238. ASSERT_THREAD(Thread);
  239. //
  240. // Raise IRQL to dispatcher level and lock dispatcher database.
  241. //
  242. KiLockDispatcherDatabase(&OldIrql);
  243. //
  244. // Capture the previous data alignment handling mode and set the
  245. // specified data alignment mode.
  246. //
  247. Previous = Thread->AutoAlignment;
  248. Thread->AutoAlignment = Enable;
  249. //
  250. // Unlock dispatcher database, lower IRQL to its previous value, and
  251. // return the previous data alignment mode.
  252. //
  253. KiUnlockDispatcherDatabase(OldIrql);
  254. return Previous;
  255. }