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.

543 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. psctx.c
  5. Abstract:
  6. This procedure implements Get/Set Context Thread
  7. Author:
  8. David N. Cutler (davec) 20-Oct-2000
  9. Revision History:
  10. --*/
  11. #include "psp.h"
  12. #pragma alloc_text(PAGE, PspGetContext)
  13. #pragma alloc_text(PAGE, PspGetSetContextSpecialApc)
  14. #pragma alloc_text(PAGE, PspSetContext)
  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 the contents of 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. ULONG ContextFlags;
  34. PLEGACY_SAVE_AREA NpxFrame;
  35. PAGED_CODE();
  36. //
  37. // Get control information if specified.
  38. //
  39. ContextFlags = ContextRecord->ContextFlags;
  40. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  41. //
  42. // Set registers RIP, CS, RSP, SS, and EFlags.
  43. //
  44. ContextRecord->Rip = TrapFrame->Rip;
  45. ContextRecord->SegCs = TrapFrame->SegCs;
  46. ContextRecord->SegSs = TrapFrame->SegSs;
  47. ContextRecord->Rsp = TrapFrame->Rsp;
  48. ContextRecord->EFlags = TrapFrame->EFlags;
  49. }
  50. //
  51. // Get segment register contents if specified.
  52. //
  53. if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
  54. //
  55. // Set segment registers GS, FS, ES, DS.
  56. //
  57. ContextRecord->SegDs = KGDT64_R3_DATA | RPL_MASK;
  58. ContextRecord->SegEs = KGDT64_R3_DATA | RPL_MASK;
  59. ContextRecord->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
  60. ContextRecord->SegGs = KGDT64_R3_DATA | RPL_MASK;
  61. }
  62. //
  63. // Get integer register contents if specified.
  64. //
  65. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  66. //
  67. // Set integer registers RAX, RCX, RDX, RSI, RDI, R8, R9, R10, RBX,
  68. // RBP, R11, R12, R13, R14, and R15.
  69. //
  70. ContextRecord->Rax = TrapFrame->Rax;
  71. ContextRecord->Rcx = TrapFrame->Rcx;
  72. ContextRecord->Rdx = TrapFrame->Rdx;
  73. ContextRecord->R8 = TrapFrame->R8;
  74. ContextRecord->R9 = TrapFrame->R9;
  75. ContextRecord->R10 = TrapFrame->R10;
  76. ContextRecord->R11 = TrapFrame->R11;
  77. ContextRecord->Rbx = *ContextPointers->Rbx;
  78. ContextRecord->Rbp = *ContextPointers->Rbp;
  79. ContextRecord->Rsi = *ContextPointers->Rsi;
  80. ContextRecord->Rdi = *ContextPointers->Rdi;
  81. ContextRecord->R12 = *ContextPointers->R12;
  82. ContextRecord->R13 = *ContextPointers->R13;
  83. ContextRecord->R13 = *ContextPointers->R14;
  84. ContextRecord->R15 = *ContextPointers->R15;
  85. }
  86. //
  87. // Get floating point context if specified.
  88. //
  89. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  90. //
  91. // Set XMM registers Xmm0-Xmm15 and the XMM CSR contents.
  92. //
  93. RtlCopyMemory(&ContextRecord->Xmm0,
  94. &TrapFrame->Xmm0,
  95. sizeof(M128) * 6);
  96. ContextRecord->Xmm6 = *ContextPointers->Xmm6;
  97. ContextRecord->Xmm7 = *ContextPointers->Xmm7;
  98. ContextRecord->Xmm8 = *ContextPointers->Xmm8;
  99. ContextRecord->Xmm9 = *ContextPointers->Xmm9;
  100. ContextRecord->Xmm10 = *ContextPointers->Xmm10;
  101. ContextRecord->Xmm11 = *ContextPointers->Xmm11;
  102. ContextRecord->Xmm12 = *ContextPointers->Xmm12;
  103. ContextRecord->Xmm13 = *ContextPointers->Xmm13;
  104. ContextRecord->Xmm14 = *ContextPointers->Xmm14;
  105. ContextRecord->Xmm15 = *ContextPointers->Xmm15;
  106. ContextRecord->MxCsr = TrapFrame->MxCsr;
  107. //
  108. // If the specified mode is user, then also set the legacy floating
  109. // point state.
  110. //
  111. if ((TrapFrame->SegCs & MODE_MASK) == UserMode) {
  112. NpxFrame = (PLEGACY_SAVE_AREA)(TrapFrame + 1);
  113. RtlCopyMemory(&ContextRecord->FltSave,
  114. &NpxFrame,
  115. sizeof(LEGACY_SAVE_AREA));
  116. }
  117. }
  118. //
  119. //
  120. // Get debug register contents if requested.
  121. //
  122. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
  123. //
  124. // Set the debug registers DR0, DR1, DR2, DR3, DR6, and DR7.
  125. //
  126. ContextRecord->Dr0 = TrapFrame->Dr0;
  127. ContextRecord->Dr1 = TrapFrame->Dr1;
  128. ContextRecord->Dr2 = TrapFrame->Dr2;
  129. ContextRecord->Dr3 = TrapFrame->Dr3;
  130. ContextRecord->Dr6 = TrapFrame->Dr6;
  131. ContextRecord->Dr7 = TrapFrame->Dr7;
  132. }
  133. return;
  134. }
  135. VOID
  136. PspSetContext (
  137. OUT PKTRAP_FRAME TrapFrame,
  138. OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  139. IN PCONTEXT ContextRecord,
  140. KPROCESSOR_MODE PreviousMode
  141. )
  142. /*++
  143. Routine Description:
  144. This function selectively moves the contents of the specified context
  145. record to the specified trap frame and nonvolatile context.
  146. Arguments:
  147. TrapFrame - Supplies the address of a trap frame.
  148. ContextPointers - Supplies the address of a context pointers record.
  149. ContextRecord - Supplies the address of a context record.
  150. ProcessorMode - Supplies the processor mode to use when sanitizing
  151. the PSR and FSR.
  152. Return Value:
  153. None.
  154. --*/
  155. {
  156. ULONG ContextFlags;
  157. PLEGACY_SAVE_AREA NpxFrame;
  158. PAGED_CODE();
  159. //
  160. // Set control information if specified.
  161. //
  162. ContextFlags = ContextRecord->ContextFlags;
  163. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  164. //
  165. // Set registers RIP, RSP, and EFlags.
  166. //
  167. TrapFrame->EFlags = SANITIZE_EFLAGS(ContextRecord->EFlags, PreviousMode);
  168. TrapFrame->Rip = ContextRecord->Rip;
  169. TrapFrame->Rsp = ContextRecord->Rsp;
  170. }
  171. //
  172. // The segment registers DS, ES, FS, and GS are never restored from saved
  173. // data. However, SS and CS are restored from the trap frame. Make sure
  174. // that these segment registers have the proper values.
  175. //
  176. if (PreviousMode == UserMode) {
  177. TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
  178. if (ContextRecord->SegCs != (KGDT64_R3_CODE | RPL_MASK)) {
  179. TrapFrame->SegCs = KGDT64_R3_CMCODE | RPL_MASK;
  180. } else {
  181. TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
  182. }
  183. } else {
  184. TrapFrame->SegCs = KGDT64_R0_CODE;
  185. TrapFrame->SegSs = KGDT64_NULL;
  186. }
  187. //
  188. // Set integer registers contents if specified.
  189. //
  190. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  191. //
  192. // Set integer registers RAX, RCX, RDX, RSI, RDI, R8, R9, R10, RBX,
  193. // RBP, R11, R12, R13, R14, and R15.
  194. //
  195. TrapFrame->Rax = ContextRecord->Rax;
  196. TrapFrame->Rcx = ContextRecord->Rcx;
  197. TrapFrame->Rdx = ContextRecord->Rdx;
  198. TrapFrame->R8 = ContextRecord->R8;
  199. TrapFrame->R9 = ContextRecord->R9;
  200. TrapFrame->R10 = ContextRecord->R10;
  201. TrapFrame->R11 = ContextRecord->R11;
  202. *ContextPointers->Rbx = ContextRecord->Rbx;
  203. *ContextPointers->Rbp = ContextRecord->Rbp;
  204. *ContextPointers->Rsi = ContextRecord->Rsi;
  205. *ContextPointers->Rdi = ContextRecord->Rdi;
  206. *ContextPointers->R12 = ContextRecord->R12;
  207. *ContextPointers->R13 = ContextRecord->R13;
  208. *ContextPointers->R14 = ContextRecord->R14;
  209. *ContextPointers->R15 = ContextRecord->R15;
  210. }
  211. //
  212. // Set floating register contents if requested.
  213. //
  214. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  215. //
  216. // Set XMM registers Xmm0-Xmm15 and the XMM CSR contents.
  217. //
  218. RtlCopyMemory(&TrapFrame->Xmm0,
  219. &ContextRecord->Xmm0,
  220. sizeof(M128) * 6);
  221. *ContextPointers->Xmm6 = ContextRecord->Xmm6;
  222. *ContextPointers->Xmm7 = ContextRecord->Xmm7;
  223. *ContextPointers->Xmm8 = ContextRecord->Xmm8;
  224. *ContextPointers->Xmm9 = ContextRecord->Xmm9;
  225. *ContextPointers->Xmm10 = ContextRecord->Xmm10;
  226. *ContextPointers->Xmm11 = ContextRecord->Xmm11;
  227. *ContextPointers->Xmm12 = ContextRecord->Xmm12;
  228. *ContextPointers->Xmm13 = ContextRecord->Xmm13;
  229. *ContextPointers->Xmm14 = ContextRecord->Xmm14;
  230. *ContextPointers->Xmm15 = ContextRecord->Xmm15;
  231. //
  232. // Clear all reserved bits in MXCSR.
  233. //
  234. TrapFrame->MxCsr = SANITIZE_MXCSR(ContextRecord->MxCsr);
  235. //
  236. // If the specified mode is user, then also set the legacy floating
  237. // point state.
  238. //
  239. if (PreviousMode == UserMode) {
  240. //
  241. // Set the floating state MM0/ST0 - MM7/ST7 and the control state.
  242. //
  243. NpxFrame = (PLEGACY_SAVE_AREA)(TrapFrame + 1);
  244. RtlCopyMemory(&NpxFrame,
  245. &ContextRecord->FltSave,
  246. sizeof(LEGACY_SAVE_AREA));
  247. }
  248. }
  249. //
  250. // Set debug register state if specified.
  251. //
  252. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
  253. //
  254. // Set the debug registers DR0, DR1, DR2, DR3, DR6, and DR7.
  255. //
  256. TrapFrame->Dr0 = SANITIZE_DRADDR(ContextRecord->Dr0, PreviousMode);
  257. TrapFrame->Dr1 = SANITIZE_DRADDR(ContextRecord->Dr1, PreviousMode);
  258. TrapFrame->Dr2 = SANITIZE_DRADDR(ContextRecord->Dr2, PreviousMode);
  259. TrapFrame->Dr3 = SANITIZE_DRADDR(ContextRecord->Dr3, PreviousMode);
  260. TrapFrame->Dr6 = 0;
  261. TrapFrame->Dr7 = SANITIZE_DR7(ContextRecord->Dr7, PreviousMode);
  262. }
  263. return;
  264. }
  265. VOID
  266. PspGetSetContextSpecialApc (
  267. IN PKAPC Apc,
  268. IN PKNORMAL_ROUTINE *NormalRoutine,
  269. IN PVOID *NormalContext,
  270. IN PVOID *SystemArgument1,
  271. IN PVOID *SystemArgument2
  272. )
  273. /*++
  274. Routine Description:
  275. This function either captures the user mode state of the current thread,
  276. or sets the user mode state of the current thread. The operation type is
  277. determined by the value of SystemArgument1. A NULL value is used for get
  278. context, and a non-NULL value is used for set context.
  279. Arguments:
  280. Apc - Supplies a pointer to the APC control object that caused entry
  281. into this routine.
  282. NormalRoutine - Supplies a pointer to a pointer to the normal routine
  283. function that was specifed when the APC was initialized.
  284. NormalContext - Supplies a pointer to a pointer to an arbitrary data
  285. structure that was specified when the APC was initialized.
  286. SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
  287. arguments that contain untyped data.
  288. Return Value:
  289. None.
  290. --*/
  291. {
  292. PGETSETCONTEXT ContextBlock;
  293. KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
  294. CONTEXT ContextRecord;
  295. ULONG64 ControlPc;
  296. ULONG64 EstablisherFrame;
  297. PRUNTIME_FUNCTION FunctionEntry;
  298. PVOID HandlerData;
  299. ULONG64 ImageBase;
  300. ULONG64 TrapFrame;
  301. PETHREAD Thread;
  302. UNREFERENCED_PARAMETER(NormalRoutine);
  303. UNREFERENCED_PARAMETER(NormalContext);
  304. UNREFERENCED_PARAMETER(SystemArgument2);
  305. PAGED_CODE();
  306. //
  307. // Get the address of the context block and compute the address of the
  308. // system entry trap frame.
  309. //
  310. ContextBlock = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
  311. Thread = PsGetCurrentThread();
  312. TrapFrame = 0;
  313. if (ContextBlock->Mode == KernelMode) {
  314. TrapFrame = (ULONG64)Thread->Tcb.TrapFrame;
  315. }
  316. if (TrapFrame == 0) {
  317. TrapFrame = (ULONG64)Thread->Tcb.InitialStack - KTRAP_FRAME_LENGTH;
  318. }
  319. //
  320. // Capture the current thread context and set the initial control PC
  321. // value.
  322. //
  323. RtlCaptureContext(&ContextRecord);
  324. //
  325. // Initialize context pointers for the nonvolatile integer and floating
  326. // registers.
  327. //
  328. ContextPointers.Rax = &ContextRecord.Rax;
  329. ContextPointers.Rcx = &ContextRecord.Rcx;
  330. ContextPointers.Rdx = &ContextRecord.Rdx;
  331. ContextPointers.Rbx = &ContextRecord.Rbx;
  332. ContextPointers.Rbp = &ContextRecord.Rbp;
  333. ContextPointers.Rsi = &ContextRecord.Rsi;
  334. ContextPointers.Rdi = &ContextRecord.Rdi;
  335. ContextPointers.R8 = &ContextRecord.R8;
  336. ContextPointers.R9 = &ContextRecord.R9;
  337. ContextPointers.R10 = &ContextRecord.R10;
  338. ContextPointers.R11 = &ContextRecord.R11;
  339. ContextPointers.R12 = &ContextRecord.R12;
  340. ContextPointers.R13 = &ContextRecord.R13;
  341. ContextPointers.R14 = &ContextRecord.R14;
  342. ContextPointers.R15 = &ContextRecord.R15;
  343. ContextPointers.Xmm6 = &ContextRecord.Xmm6;
  344. ContextPointers.Xmm7 = &ContextRecord.Xmm7;
  345. ContextPointers.Xmm8 = &ContextRecord.Xmm8;
  346. ContextPointers.Xmm9 = &ContextRecord.Xmm9;
  347. ContextPointers.Xmm10 = &ContextRecord.Xmm10;
  348. ContextPointers.Xmm11 = &ContextRecord.Xmm11;
  349. ContextPointers.Xmm12 = &ContextRecord.Xmm12;
  350. ContextPointers.Xmm13 = &ContextRecord.Xmm13;
  351. ContextPointers.Xmm14 = &ContextRecord.Xmm14;
  352. ContextPointers.Xmm15 = &ContextRecord.Xmm15;
  353. //
  354. // Start with the frame specified by the context record and virtually
  355. // unwind call frames until the system entry trap frame is encountered.
  356. //
  357. do {
  358. //
  359. // Lookup the function table entry using the point at which control
  360. // left the function.
  361. //
  362. ControlPc = ContextRecord.Rip;
  363. FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
  364. //
  365. // If there is a function table entry for the routine, then virtually
  366. // unwind to the caller of the current routine to obtain the address
  367. // where control left the caller. Otherwise, the function is a leaf
  368. // function and the return address register contains the address of
  369. // where control left the caller.
  370. //
  371. if (FunctionEntry != NULL) {
  372. RtlVirtualUnwind(UNW_FLAG_EHANDLER,
  373. ImageBase,
  374. ControlPc,
  375. FunctionEntry,
  376. &ContextRecord,
  377. &HandlerData,
  378. &EstablisherFrame,
  379. &ContextPointers);
  380. } else {
  381. ContextRecord.Rip = *(PULONG64)(ContextRecord.Rsp);
  382. ContextRecord.Rsp += 8;
  383. }
  384. } while (ContextRecord.Rsp != TrapFrame);
  385. //
  386. // If system argument one is nonzero, then set the context of the current
  387. // thread. Otherwise, get the context of the current thread.
  388. //
  389. if (*SystemArgument1 != NULL) {
  390. //
  391. // Set Context
  392. //
  393. PspSetContext((PKTRAP_FRAME)TrapFrame,
  394. NULL,
  395. &ContextBlock->Context,
  396. ContextBlock->Mode);
  397. } else {
  398. //
  399. // Get Context
  400. //
  401. PspGetContext((PKTRAP_FRAME)TrapFrame, NULL, &ContextBlock->Context);
  402. }
  403. KeSetEvent(&ContextBlock->OperationComplete, 0, FALSE);
  404. return;
  405. }