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.

327 lines
9.0 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. Joe Notarangelo 21-Apr-1992
  14. very minor changes for ALPHA
  15. 1. psr definition
  16. 2. pte and mask (from 3ffffc to 1ffffc), mips page size is 4k
  17. our first alpha page size is 8k
  18. mips code shifts right 10 (12-2) and then turns off the
  19. upper 10 bits, alpha shifts right 11 (13-2) and so must
  20. turn off upper 11 bits
  21. 3. Insert register values into context structure as quadwords
  22. to insure that the written values are in canonical form
  23. Thomas Van Baak (tvb) 9-Oct-1992
  24. Adapted for Alpha AXP.
  25. --*/
  26. #include "ki.h"
  27. //
  28. // The following assert macros are used to check that an input object is
  29. // really the proper type.
  30. //
  31. #define ASSERT_PROCESS(E) { \
  32. ASSERT((E)->Header.Type == ProcessObject); \
  33. }
  34. #define ASSERT_THREAD(E) { \
  35. ASSERT((E)->Header.Type == ThreadObject); \
  36. }
  37. VOID
  38. KiInitializeContextThread (
  39. IN PKTHREAD Thread,
  40. IN PKSYSTEM_ROUTINE SystemRoutine,
  41. IN PKSTART_ROUTINE StartRoutine OPTIONAL,
  42. IN PVOID StartContext OPTIONAL,
  43. IN PCONTEXT ContextRecord OPTIONAL
  44. )
  45. /*++
  46. Routine Description:
  47. This function initializes the machine dependent context of a thread object.
  48. N.B. This function does not check the accessibility of the context record.
  49. It is assumed the the caller of this routine is either prepared to
  50. handle access violations or has probed and copied the context record
  51. as appropriate.
  52. Arguments:
  53. Thread - Supplies a pointer to a dispatcher object of type thread.
  54. SystemRoutine - Supplies a pointer to the system function that is to be
  55. called when the thread is first scheduled for execution.
  56. StartRoutine - Supplies an optional pointer to a function that is to be
  57. called after the system has finished initializing the thread. This
  58. parameter is specified if the thread is a system thread and will
  59. execute totally in kernel mode.
  60. StartContext - Supplies an optional pointer to an arbitrary data structure
  61. which will be passed to the StartRoutine as a parameter. This
  62. parameter is specified if the thread is a system thread and will
  63. execute totally in kernel mode.
  64. ContextRecord - Supplies an optional pointer a context frame which contains
  65. the initial user mode state of the thread. This parameter is specified
  66. if the thread is a user thread and will execute in user mode. If this
  67. parameter is not specified, then the Teb parameter is ignored.
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. PKEXCEPTION_FRAME CxFrame;
  73. PKEXCEPTION_FRAME ExFrame;
  74. ULONG_PTR InitialStack;
  75. PKTRAP_FRAME TrFrame;
  76. //
  77. // If a context frame is specified, then initialize a trap frame and
  78. // and an exception frame with the specified user mode context.
  79. //
  80. InitialStack = (ULONG_PTR)Thread->InitialStack;
  81. if (ARGUMENT_PRESENT(ContextRecord)) {
  82. TrFrame = (PKTRAP_FRAME)(((InitialStack) -
  83. sizeof(KTRAP_FRAME)) & ~((ULONG_PTR)15));
  84. ExFrame = (PKEXCEPTION_FRAME)(((ULONG_PTR)TrFrame -
  85. sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
  86. CxFrame = (PKEXCEPTION_FRAME)(((ULONG_PTR)ExFrame -
  87. sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
  88. //
  89. // Zero the exception and trap frames and copy information from the
  90. // specified context frame to the trap and exception frames.
  91. //
  92. RtlZeroMemory((PVOID)ExFrame, sizeof(KEXCEPTION_FRAME));
  93. RtlZeroMemory((PVOID)TrFrame, sizeof(KTRAP_FRAME));
  94. KeContextToKframes(TrFrame, ExFrame,
  95. ContextRecord,
  96. ContextRecord->ContextFlags | CONTEXT_CONTROL,
  97. UserMode);
  98. //
  99. // If the FPCR quadword in the specified context record is zero,
  100. // then assume it is a default value and force floating point round
  101. // to nearest mode (the hardware default mode is chopped rounding
  102. // which is not desirable for NT). It would be nice to initialize
  103. // the SoftFpcr here also but not all threads have a Teb.
  104. //
  105. if (TrFrame->Fpcr == 0) {
  106. ((PFPCR)(&TrFrame->Fpcr))->DynamicRoundingMode = ROUND_TO_NEAREST;
  107. }
  108. //
  109. // Set the saved previous processor mode in the trap frame and the
  110. // previous processor mode in the thread object to user mode.
  111. //
  112. TrFrame->PreviousMode = UserMode;
  113. Thread->PreviousMode = UserMode;
  114. //
  115. // Initialize the return address in the exception frame.
  116. //
  117. ExFrame->IntRa = 0;
  118. } else {
  119. ExFrame = NULL;
  120. CxFrame = (PKEXCEPTION_FRAME)(((InitialStack) -
  121. sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
  122. //
  123. // Set the previous mode in thread object to kernel.
  124. //
  125. Thread->PreviousMode = KernelMode;
  126. }
  127. //
  128. // Initialize context switch frame and set thread start up parameters.
  129. //
  130. // N.B. ULONG becomes canonical longword with (ULONGLONG)(LONG) cast.
  131. //
  132. CxFrame->SwapReturn = (ULONGLONG)(LONG_PTR)KiThreadStartup;
  133. if (ExFrame == NULL) {
  134. CxFrame->IntFp = (ULONGLONG)(LONG_PTR)ExFrame;
  135. } else {
  136. CxFrame->IntFp = (ULONGLONG)(LONG_PTR)TrFrame;
  137. }
  138. CxFrame->IntS0 = (ULONGLONG)(LONG_PTR)ContextRecord;
  139. CxFrame->IntS1 = (ULONGLONG)(LONG_PTR)StartContext;
  140. CxFrame->IntS2 = (ULONGLONG)(LONG_PTR)StartRoutine;
  141. CxFrame->IntS3 = (ULONGLONG)(LONG_PTR)SystemRoutine;
  142. CxFrame->Psr = 0; // clear everything
  143. ((PSR *)(&CxFrame->Psr))->INTERRUPT_ENABLE = 1;
  144. ((PSR *)(&CxFrame->Psr))->IRQL = DISPATCH_LEVEL;
  145. ((PSR *)(&CxFrame->Psr))->MODE = 0;
  146. //
  147. // Set the initial kernel stack pointer.
  148. //
  149. Thread->KernelStack = (PVOID)(ULONGLONG)(LONG_PTR)CxFrame;
  150. return;
  151. }
  152. BOOLEAN
  153. KeSetAutoAlignmentProcess (
  154. IN PKPROCESS Process,
  155. IN BOOLEAN Enable
  156. )
  157. /*++
  158. Routine Description:
  159. This function sets the data alignment handling mode for the specified
  160. process and returns the previous data alignment handling mode.
  161. Arguments:
  162. Process - Supplies a pointer to a dispatcher object of type process.
  163. Enable - Supplies a boolean value that determines the handling of data
  164. alignment exceptions for the process. A value of TRUE causes all
  165. data alignment exceptions to be automatically handled by the kernel.
  166. A value of FALSE causes all data alignment exceptions to be actually
  167. raised as exceptions.
  168. Return Value:
  169. A value of TRUE is returned if data alignment exceptions were
  170. previously automatically handled by the kernel. Otherwise, a value
  171. of FALSE is returned.
  172. --*/
  173. {
  174. KIRQL OldIrql;
  175. BOOLEAN Previous;
  176. ASSERT_PROCESS(Process);
  177. //
  178. // Raise IRQL to dispatcher level and lock dispatcher database.
  179. //
  180. KiLockDispatcherDatabase(&OldIrql);
  181. //
  182. // Capture the previous data alignment handling mode and set the
  183. // specified data alignment mode.
  184. //
  185. Previous = Process->AutoAlignment;
  186. Process->AutoAlignment = Enable;
  187. //
  188. // Unlock dispatcher database, lower IRQL to its previous value, and
  189. // return the previous data alignment mode.
  190. //
  191. KiUnlockDispatcherDatabase(OldIrql);
  192. return Previous;
  193. }
  194. BOOLEAN
  195. KeSetAutoAlignmentThread (
  196. IN PKTHREAD Thread,
  197. IN BOOLEAN Enable
  198. )
  199. /*++
  200. Routine Description:
  201. This function sets the data alignment handling mode for the specified
  202. thread and returns the previous data alignment handling mode.
  203. Arguments:
  204. Thread - Supplies a pointer to a dispatcher object of type thread.
  205. Enable - Supplies a boolean value that determines the handling of data
  206. alignment exceptions for the thread. A value of TRUE causes all
  207. data alignment exceptions to be automatically handled by the kernel.
  208. A value of FALSE causes all data alignment exceptions to be actually
  209. raised as exceptions.
  210. Return Value:
  211. A value of TRUE is returned if data alignment exceptions were
  212. previously automatically handled by the kernel. Otherwise, a value
  213. of FALSE is returned.
  214. --*/
  215. {
  216. KIRQL OldIrql;
  217. BOOLEAN Previous;
  218. ASSERT_THREAD(Thread);
  219. //
  220. // Raise IRQL to dispatcher level and lock dispatcher database.
  221. //
  222. KiLockDispatcherDatabase(&OldIrql);
  223. //
  224. // Capture the previous data alignment handling mode and set the
  225. // specified data alignment mode.
  226. //
  227. Previous = Thread->AutoAlignment;
  228. Thread->AutoAlignment = Enable;
  229. //
  230. // Unlock dispatcher database, lower IRQL to its previous value, and
  231. // return the previous data alignment mode.
  232. //
  233. KiUnlockDispatcherDatabase(OldIrql);
  234. return Previous;
  235. }