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.

525 lines
15 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1993 Digital Equipment Corporation
  4. Module Name:
  5. psctxalp.c
  6. Abstract:
  7. This module implements functions to get and set the context of a thread.
  8. Author:
  9. David N. Cutler (davec) 1-Oct-1990
  10. Revision History:
  11. Thomas Van Baak (tvb) 18-May-1992
  12. Adapted for Alpha AXP.
  13. --*/
  14. #include "psp.h"
  15. VOID
  16. PspGetContext (
  17. IN PKTRAP_FRAME TrapFrame,
  18. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  19. IN OUT PCONTEXT ContextRecord
  20. )
  21. /*++
  22. Routine Description:
  23. This function selectively moves the contents of the specified trap frame
  24. and nonvolatile context to the specified context record.
  25. Arguments:
  26. TrapFrame - Supplies a pointer to a trap frame.
  27. ContextPointers - Supplies the address of context pointers record.
  28. ContextRecord - Supplies the address of a context record.
  29. Return Value:
  30. None.
  31. --*/
  32. {
  33. //
  34. // Get control information if specified.
  35. //
  36. if ((ContextRecord->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  37. //
  38. // Get integer registers gp, ra, sp, FIR, and PSR from trap frame.
  39. //
  40. ContextRecord->IntGp = TrapFrame->IntGp;
  41. ContextRecord->IntSp = TrapFrame->IntSp;
  42. ContextRecord->IntRa = TrapFrame->IntRa;
  43. ContextRecord->Fir = TrapFrame->Fir;
  44. ContextRecord->Psr = TrapFrame->Psr;
  45. }
  46. //
  47. // Get integer register contents if specified.
  48. //
  49. if ((ContextRecord->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  50. //
  51. // Get volatile integer registers v0 and t0 - t7 from trap frame.
  52. //
  53. ContextRecord->IntV0 = TrapFrame->IntV0;
  54. ContextRecord->IntT0 = TrapFrame->IntT0;
  55. ContextRecord->IntT1 = TrapFrame->IntT1;
  56. ContextRecord->IntT2 = TrapFrame->IntT2;
  57. ContextRecord->IntT3 = TrapFrame->IntT3;
  58. ContextRecord->IntT4 = TrapFrame->IntT4;
  59. ContextRecord->IntT5 = TrapFrame->IntT5;
  60. ContextRecord->IntT6 = TrapFrame->IntT6;
  61. ContextRecord->IntT7 = TrapFrame->IntT7;
  62. //
  63. // Get nonvolatile integer registers s0 - s5 through context pointers.
  64. //
  65. ContextRecord->IntS0 = *ContextPointers->IntS0;
  66. ContextRecord->IntS1 = *ContextPointers->IntS1;
  67. ContextRecord->IntS2 = *ContextPointers->IntS2;
  68. ContextRecord->IntS3 = *ContextPointers->IntS3;
  69. ContextRecord->IntS4 = *ContextPointers->IntS4;
  70. ContextRecord->IntS5 = *ContextPointers->IntS5;
  71. //
  72. // Get volatile integer registers fp/s6, a0 - a5, and t8 - t12 from
  73. // trap frame.
  74. //
  75. ContextRecord->IntFp = TrapFrame->IntFp;
  76. ContextRecord->IntA0 = TrapFrame->IntA0;
  77. ContextRecord->IntA1 = TrapFrame->IntA1;
  78. ContextRecord->IntA2 = TrapFrame->IntA2;
  79. ContextRecord->IntA3 = TrapFrame->IntA3;
  80. ContextRecord->IntA4 = TrapFrame->IntA4;
  81. ContextRecord->IntA5 = TrapFrame->IntA5;
  82. ContextRecord->IntT8 = TrapFrame->IntT8;
  83. ContextRecord->IntT9 = TrapFrame->IntT9;
  84. ContextRecord->IntT10 = TrapFrame->IntT10;
  85. ContextRecord->IntT11 = TrapFrame->IntT11;
  86. ContextRecord->IntT12 = TrapFrame->IntT12;
  87. //
  88. // Get volatile integer register AT from trap frame.
  89. // Get integer register zero.
  90. //
  91. ContextRecord->IntAt = TrapFrame->IntAt;
  92. ContextRecord->IntZero = 0;
  93. }
  94. //
  95. // Get floating register contents if specified.
  96. //
  97. if ((ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  98. //
  99. // Get volatile floating registers f0 - f1 from trap frame.
  100. //
  101. ContextRecord->FltF0 = TrapFrame->FltF0;
  102. ContextRecord->FltF1 = TrapFrame->FltF1;
  103. //
  104. // Get volatile floating registers f10 - f30 from trap frame.
  105. // This assumes that f10 - f30 are contiguous in the trap frame.
  106. //
  107. ASSERT((&ContextRecord->FltF30 - &ContextRecord->FltF10) == 20);
  108. RtlMoveMemory(&ContextRecord->FltF10, &TrapFrame->FltF10,
  109. sizeof(ULONGLONG) * 21);
  110. ContextRecord->FltF31 = 0;
  111. //
  112. // Get nonvolatile floating registers f2 - f9 through context pointers.
  113. //
  114. ContextRecord->FltF2 = *ContextPointers->FltF2;
  115. ContextRecord->FltF3 = *ContextPointers->FltF3;
  116. ContextRecord->FltF4 = *ContextPointers->FltF4;
  117. ContextRecord->FltF5 = *ContextPointers->FltF5;
  118. ContextRecord->FltF6 = *ContextPointers->FltF6;
  119. ContextRecord->FltF7 = *ContextPointers->FltF7;
  120. ContextRecord->FltF8 = *ContextPointers->FltF8;
  121. ContextRecord->FltF9 = *ContextPointers->FltF9;
  122. //
  123. // Get floating point control register from trap frame.
  124. // Get the current software FPCR value from the TEB.
  125. //
  126. ContextRecord->Fpcr = TrapFrame->Fpcr;
  127. try {
  128. ContextRecord->SoftFpcr =
  129. (ULONGLONG)(NtCurrentTeb()->FpSoftwareStatusRegister);
  130. } except (EXCEPTION_EXECUTE_HANDLER) {
  131. ContextRecord->SoftFpcr = 0;
  132. }
  133. }
  134. return;
  135. }
  136. VOID
  137. PspSetContext (
  138. IN OUT PKTRAP_FRAME TrapFrame,
  139. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  140. IN PCONTEXT ContextRecord,
  141. IN KPROCESSOR_MODE ProcessorMode
  142. )
  143. /*++
  144. Routine Description:
  145. This function selectively moves the contents of the specified context
  146. record to the specified trap frame and nonvolatile context.
  147. Arguments:
  148. TrapFrame - Supplies the address of a trap frame.
  149. ContextPointers - Supplies the address of a context pointers record.
  150. ContextRecord - Supplies the address of a context record.
  151. ProcessorMode - Supplies the processor mode to use when sanitizing
  152. the PSR and FSR.
  153. Return Value:
  154. None.
  155. --*/
  156. {
  157. //
  158. // Set control information if specified.
  159. //
  160. if ((ContextRecord->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  161. //
  162. // Set integer registers gp, sp, ra, FIR, and PSR in trap frame.
  163. //
  164. TrapFrame->IntGp = ContextRecord->IntGp;
  165. TrapFrame->IntSp = ContextRecord->IntSp;
  166. TrapFrame->IntRa = ContextRecord->IntRa;
  167. TrapFrame->Fir = ContextRecord->Fir;
  168. TrapFrame->Psr = SANITIZE_PSR(ContextRecord->Psr, ProcessorMode);
  169. }
  170. //
  171. // Set integer register contents if specified.
  172. //
  173. if ((ContextRecord->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  174. //
  175. // Set volatile integer registers v0 and t0 - t7 in trap frame.
  176. //
  177. TrapFrame->IntV0 = ContextRecord->IntV0;
  178. TrapFrame->IntT0 = ContextRecord->IntT0;
  179. TrapFrame->IntT1 = ContextRecord->IntT1;
  180. TrapFrame->IntT2 = ContextRecord->IntT2;
  181. TrapFrame->IntT3 = ContextRecord->IntT3;
  182. TrapFrame->IntT4 = ContextRecord->IntT4;
  183. TrapFrame->IntT5 = ContextRecord->IntT5;
  184. TrapFrame->IntT6 = ContextRecord->IntT6;
  185. TrapFrame->IntT7 = ContextRecord->IntT7;
  186. //
  187. // Set nonvolatile integer registers s0 - s5 through context pointers.
  188. //
  189. *ContextPointers->IntS0 = ContextRecord->IntS0;
  190. *ContextPointers->IntS1 = ContextRecord->IntS1;
  191. *ContextPointers->IntS2 = ContextRecord->IntS2;
  192. *ContextPointers->IntS3 = ContextRecord->IntS3;
  193. *ContextPointers->IntS4 = ContextRecord->IntS4;
  194. *ContextPointers->IntS5 = ContextRecord->IntS5;
  195. //
  196. // Set volatile integer registers fp/s6, a0 - a5, t8 - t12, and AT
  197. // in trap frame.
  198. //
  199. TrapFrame->IntFp = ContextRecord->IntFp;
  200. TrapFrame->IntA0 = ContextRecord->IntA0;
  201. TrapFrame->IntA1 = ContextRecord->IntA1;
  202. TrapFrame->IntA2 = ContextRecord->IntA2;
  203. TrapFrame->IntA3 = ContextRecord->IntA3;
  204. TrapFrame->IntA4 = ContextRecord->IntA4;
  205. TrapFrame->IntA5 = ContextRecord->IntA5;
  206. TrapFrame->IntT8 = ContextRecord->IntT8;
  207. TrapFrame->IntT9 = ContextRecord->IntT9;
  208. TrapFrame->IntT10 = ContextRecord->IntT10;
  209. TrapFrame->IntT11 = ContextRecord->IntT11;
  210. TrapFrame->IntT12 = ContextRecord->IntT12;
  211. TrapFrame->IntAt = ContextRecord->IntAt;
  212. }
  213. //
  214. // Set floating register contents if specified.
  215. //
  216. if ((ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  217. //
  218. // Set volatile floating registers f0 - f1 in trap frame.
  219. //
  220. TrapFrame->FltF0 = ContextRecord->FltF0;
  221. TrapFrame->FltF1 = ContextRecord->FltF1;
  222. //
  223. // Set volatile floating registers f10 - f30 in trap frame.
  224. // This assumes that f10 - f30 are contiguous in the trap frame.
  225. //
  226. ASSERT((&ContextRecord->FltF30 - &ContextRecord->FltF10) == 20);
  227. RtlMoveMemory(&TrapFrame->FltF10, &ContextRecord->FltF10,
  228. sizeof(ULONGLONG) * 21);
  229. //
  230. // Set nonvolatile floating registers f2 - f9 through context pointers.
  231. //
  232. *ContextPointers->FltF2 = ContextRecord->FltF2;
  233. *ContextPointers->FltF3 = ContextRecord->FltF3;
  234. *ContextPointers->FltF4 = ContextRecord->FltF4;
  235. *ContextPointers->FltF5 = ContextRecord->FltF5;
  236. *ContextPointers->FltF6 = ContextRecord->FltF6;
  237. *ContextPointers->FltF7 = ContextRecord->FltF7;
  238. *ContextPointers->FltF8 = ContextRecord->FltF8;
  239. *ContextPointers->FltF9 = ContextRecord->FltF9;
  240. //
  241. // Set floating point control register in trap frame.
  242. // Set the current software FPCR value in the TEB.
  243. //
  244. TrapFrame->Fpcr = ContextRecord->Fpcr;
  245. try {
  246. NtCurrentTeb()->FpSoftwareStatusRegister =
  247. (ULONG)ContextRecord->SoftFpcr;
  248. } except (EXCEPTION_EXECUTE_HANDLER) {
  249. NOTHING;
  250. }
  251. }
  252. return;
  253. }
  254. VOID
  255. PspGetSetContextSpecialApcMain (
  256. IN PKAPC Apc,
  257. IN PKNORMAL_ROUTINE *NormalRoutine,
  258. IN PVOID *NormalContext,
  259. IN PVOID *SystemArgument1,
  260. IN PVOID *SystemArgument2
  261. )
  262. /*++
  263. Routine Description:
  264. This function either captures the user mode state of the current
  265. thread, or sets the user mode state of the current thread. The
  266. operation type is determined by the value of SystemArgument1. A
  267. zero value is used for get context, and a nonzero value is used
  268. for set context.
  269. Arguments:
  270. Apc - Supplies a pointer to the APC control object that caused entry
  271. into this routine.
  272. NormalRoutine - Supplies a pointer to the normal routine function that
  273. was specified when the APC was initialized. This parameter is not
  274. used.
  275. NormalContext - Supplies a pointer to an arbitrary data structure that
  276. was specified when the APC was initialized. This parameter is not
  277. used.
  278. SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
  279. arguments that contain untyped data. These parameters are not used.
  280. Return Value:
  281. None.
  282. --*/
  283. {
  284. PGETSETCONTEXT ContextBlock;
  285. KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
  286. CONTEXT ContextRecord;
  287. ULONG_PTR ControlPc;
  288. FRAME_POINTERS EstablisherFrame;
  289. PRUNTIME_FUNCTION FunctionEntry;
  290. BOOLEAN InFunction;
  291. PETHREAD Thread;
  292. ULONGLONG TrapFrame1;
  293. ULONGLONG TrapFrame2;
  294. //
  295. // Get the address of the context block and compute the address of the
  296. // system entry trap frame.
  297. //
  298. ContextBlock = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
  299. Thread = PsGetCurrentThread();
  300. TrapFrame1 = (ULONGLONG)(LONG_PTR)Thread->Tcb.InitialStack - KTRAP_FRAME_LENGTH;
  301. //
  302. // The lower bounds for locating the first system service trap frame on
  303. // the kernel stack is one trap frame below TrapFrame1.
  304. //
  305. TrapFrame2 = TrapFrame1 - KTRAP_FRAME_LENGTH;
  306. //
  307. // Capture the current thread context and set the initial control PC
  308. // value.
  309. //
  310. RtlCaptureContext(&ContextRecord);
  311. ControlPc = (ULONG_PTR)ContextRecord.IntRa;
  312. //
  313. // Initialize context pointers for the nonvolatile integer and floating
  314. // registers.
  315. //
  316. ContextPointers.IntS0 = &ContextRecord.IntS0;
  317. ContextPointers.IntS1 = &ContextRecord.IntS1;
  318. ContextPointers.IntS2 = &ContextRecord.IntS2;
  319. ContextPointers.IntS3 = &ContextRecord.IntS3;
  320. ContextPointers.IntS4 = &ContextRecord.IntS4;
  321. ContextPointers.IntS5 = &ContextRecord.IntS5;
  322. ContextPointers.FltF2 = &ContextRecord.FltF2;
  323. ContextPointers.FltF3 = &ContextRecord.FltF3;
  324. ContextPointers.FltF4 = &ContextRecord.FltF4;
  325. ContextPointers.FltF5 = &ContextRecord.FltF5;
  326. ContextPointers.FltF6 = &ContextRecord.FltF6;
  327. ContextPointers.FltF7 = &ContextRecord.FltF7;
  328. ContextPointers.FltF8 = &ContextRecord.FltF8;
  329. ContextPointers.FltF9 = &ContextRecord.FltF9;
  330. //
  331. // Start with the frame specified by the context record and virtually
  332. // unwind call frames until the system entry trap frame is encountered.
  333. //
  334. do {
  335. //
  336. // Lookup the function table entry using the point at which control
  337. // left the procedure.
  338. //
  339. FunctionEntry = RtlLookupFunctionEntry(ControlPc);
  340. //
  341. // If there is a function table entry for the routine, then virtually
  342. // unwind to the caller of the current routine to obtain the address
  343. // where control left the caller. Otherwise, the function is a leaf
  344. // function and the return address register contains the address of
  345. // where control left the caller.
  346. //
  347. if (FunctionEntry != NULL) {
  348. ControlPc = RtlVirtualUnwind(ControlPc,
  349. FunctionEntry,
  350. &ContextRecord,
  351. &InFunction,
  352. &EstablisherFrame,
  353. &ContextPointers);
  354. } else {
  355. ControlPc = (ULONG_PTR)ContextRecord.IntRa;
  356. }
  357. //
  358. // N.B. The virtual frame pointer of the kernel frame just below the
  359. // trap frame may not be exactly equal to TrapFrame1 since the trap
  360. // code can allocate additional stack space (for local variables or
  361. // system service arguments). Therefore we must check for a range of
  362. // values at or below TrapFrame1, but also above TrapFrame2 (so in
  363. // case there is more than one trap frame on the stack, we get the
  364. // one at the top.
  365. //
  366. } while ((ContextRecord.IntSp != TrapFrame1) &&
  367. ((ContextRecord.IntSp < TrapFrame2) ||
  368. (ControlPc < PCR->SystemServiceDispatchStart) ||
  369. (ControlPc >= PCR->SystemServiceDispatchEnd)));
  370. //
  371. // If system argument one is nonzero, then set the context of the current
  372. // thread. Otherwise, get the context of the current thread.
  373. //
  374. if (Apc->SystemArgument1 != 0) {
  375. //
  376. // Set context of current thread.
  377. //
  378. PspSetContext((PKTRAP_FRAME)TrapFrame1,
  379. &ContextPointers,
  380. &ContextBlock->Context,
  381. ContextBlock->Mode);
  382. } else {
  383. //
  384. // Get context of current thread.
  385. //
  386. PspGetContext((PKTRAP_FRAME)TrapFrame1,
  387. &ContextPointers,
  388. &ContextBlock->Context);
  389. }
  390. KeSetEvent(&ContextBlock->OperationComplete, 0, FALSE);
  391. return;
  392. }