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.

594 lines
17 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->R14 = *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. if ((TrapFrame->Dr7 & DR7_ACTIVE) != 0) {
  127. ContextRecord->Dr0 = TrapFrame->Dr0;
  128. ContextRecord->Dr1 = TrapFrame->Dr1;
  129. ContextRecord->Dr2 = TrapFrame->Dr2;
  130. ContextRecord->Dr3 = TrapFrame->Dr3;
  131. ContextRecord->Dr6 = TrapFrame->Dr6;
  132. ContextRecord->Dr7 = TrapFrame->Dr7;
  133. } else {
  134. ContextRecord->Dr0 = 0;
  135. ContextRecord->Dr1 = 0;
  136. ContextRecord->Dr2 = 0;
  137. ContextRecord->Dr3 = 0;
  138. ContextRecord->Dr6 = 0;
  139. ContextRecord->Dr7 = 0;
  140. }
  141. }
  142. return;
  143. }
  144. VOID
  145. PspSetContext (
  146. OUT PKTRAP_FRAME TrapFrame,
  147. OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  148. IN PCONTEXT ContextRecord,
  149. KPROCESSOR_MODE PreviousMode
  150. )
  151. /*++
  152. Routine Description:
  153. This function selectively moves the contents of the specified context
  154. record to the specified trap frame and nonvolatile context.
  155. Arguments:
  156. TrapFrame - Supplies the address of a trap frame.
  157. ContextPointers - Supplies the address of a context pointers record.
  158. ContextRecord - Supplies the address of a context record.
  159. ProcessorMode - Supplies the processor mode to use when sanitizing
  160. the PSR and FSR.
  161. Return Value:
  162. None.
  163. --*/
  164. {
  165. ULONG ContextFlags;
  166. PLEGACY_SAVE_AREA NpxFrame;
  167. PAGED_CODE();
  168. //
  169. // Set control information if specified.
  170. //
  171. ContextFlags = ContextRecord->ContextFlags;
  172. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  173. //
  174. // Set registers RIP, RSP, and EFlags.
  175. //
  176. TrapFrame->EFlags = SANITIZE_EFLAGS(ContextRecord->EFlags, PreviousMode);
  177. TrapFrame->Rip = ContextRecord->Rip;
  178. TrapFrame->Rsp = ContextRecord->Rsp;
  179. //
  180. // The segment registers DS, ES, FS, and GS are never restored from saved
  181. // data. However, SS and CS are restored from the trap frame. Make sure
  182. // that these segment registers have the proper values.
  183. //
  184. if (PreviousMode == UserMode) {
  185. TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
  186. if (ContextRecord->SegCs != (KGDT64_R3_CODE | RPL_MASK)) {
  187. TrapFrame->SegCs = KGDT64_R3_CMCODE | RPL_MASK;
  188. } else {
  189. TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
  190. }
  191. } else {
  192. TrapFrame->SegCs = KGDT64_R0_CODE;
  193. TrapFrame->SegSs = KGDT64_NULL;
  194. }
  195. }
  196. //
  197. // Set integer registers contents if specified.
  198. //
  199. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  200. //
  201. // Set integer registers RAX, RCX, RDX, RSI, RDI, R8, R9, R10, RBX,
  202. // RBP, R11, R12, R13, R14, and R15.
  203. //
  204. TrapFrame->Rax = ContextRecord->Rax;
  205. TrapFrame->Rcx = ContextRecord->Rcx;
  206. TrapFrame->Rdx = ContextRecord->Rdx;
  207. TrapFrame->R8 = ContextRecord->R8;
  208. TrapFrame->R9 = ContextRecord->R9;
  209. TrapFrame->R10 = ContextRecord->R10;
  210. TrapFrame->R11 = ContextRecord->R11;
  211. *ContextPointers->Rbx = ContextRecord->Rbx;
  212. *ContextPointers->Rbp = ContextRecord->Rbp;
  213. *ContextPointers->Rsi = ContextRecord->Rsi;
  214. *ContextPointers->Rdi = ContextRecord->Rdi;
  215. *ContextPointers->R12 = ContextRecord->R12;
  216. *ContextPointers->R13 = ContextRecord->R13;
  217. *ContextPointers->R14 = ContextRecord->R14;
  218. *ContextPointers->R15 = ContextRecord->R15;
  219. }
  220. //
  221. // Set floating register contents if requested.
  222. //
  223. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  224. //
  225. // Set XMM registers Xmm0-Xmm15 and the XMM CSR contents.
  226. //
  227. RtlCopyMemory(&TrapFrame->Xmm0,
  228. &ContextRecord->Xmm0,
  229. sizeof(M128) * 6);
  230. *ContextPointers->Xmm6 = ContextRecord->Xmm6;
  231. *ContextPointers->Xmm7 = ContextRecord->Xmm7;
  232. *ContextPointers->Xmm8 = ContextRecord->Xmm8;
  233. *ContextPointers->Xmm9 = ContextRecord->Xmm9;
  234. *ContextPointers->Xmm10 = ContextRecord->Xmm10;
  235. *ContextPointers->Xmm11 = ContextRecord->Xmm11;
  236. *ContextPointers->Xmm12 = ContextRecord->Xmm12;
  237. *ContextPointers->Xmm13 = ContextRecord->Xmm13;
  238. *ContextPointers->Xmm14 = ContextRecord->Xmm14;
  239. *ContextPointers->Xmm15 = ContextRecord->Xmm15;
  240. //
  241. // Clear all reserved bits in MXCSR.
  242. //
  243. TrapFrame->MxCsr = SANITIZE_MXCSR(ContextRecord->MxCsr);
  244. //
  245. // If the specified mode is user, then also set the legacy floating
  246. // point state.
  247. //
  248. if (PreviousMode == UserMode) {
  249. //
  250. // Set the floating state MM0/ST0 - MM7/ST7 and the control state.
  251. //
  252. NpxFrame = (PLEGACY_SAVE_AREA)(TrapFrame + 1);
  253. RtlCopyMemory(NpxFrame,
  254. &ContextRecord->FltSave,
  255. sizeof(LEGACY_SAVE_AREA));
  256. }
  257. }
  258. //
  259. // Set debug register state if specified.
  260. //
  261. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
  262. //
  263. // Set the debug registers DR0, DR1, DR2, DR3, DR6, and DR7.
  264. //
  265. TrapFrame->Dr0 = SANITIZE_DRADDR(ContextRecord->Dr0, PreviousMode);
  266. TrapFrame->Dr1 = SANITIZE_DRADDR(ContextRecord->Dr1, PreviousMode);
  267. TrapFrame->Dr2 = SANITIZE_DRADDR(ContextRecord->Dr2, PreviousMode);
  268. TrapFrame->Dr3 = SANITIZE_DRADDR(ContextRecord->Dr3, PreviousMode);
  269. TrapFrame->Dr6 = 0;
  270. TrapFrame->Dr7 = SANITIZE_DR7(ContextRecord->Dr7, PreviousMode);
  271. if (PreviousMode != KernelMode) {
  272. KeGetCurrentThread()->Header.DebugActive =
  273. (BOOLEAN)((TrapFrame->Dr7 & DR7_ACTIVE) != 0);
  274. }
  275. }
  276. return;
  277. }
  278. VOID
  279. PspGetSetContextSpecialApc (
  280. IN PKAPC Apc,
  281. IN PKNORMAL_ROUTINE *NormalRoutine,
  282. IN PVOID *NormalContext,
  283. IN PVOID *SystemArgument1,
  284. IN PVOID *SystemArgument2
  285. )
  286. /*++
  287. Routine Description:
  288. This function either captures the user mode state of the current thread,
  289. or sets the user mode state of the current thread. The operation type is
  290. determined by the value of SystemArgument1. A NULL value is used for get
  291. context, and a non-NULL value is used for set context.
  292. Arguments:
  293. Apc - Supplies a pointer to the APC control object that caused entry
  294. into this routine.
  295. NormalRoutine - Supplies a pointer to a pointer to the normal routine
  296. function that was specifed when the APC was initialized.
  297. NormalContext - Supplies a pointer to a pointer to an arbitrary data
  298. structure that was specified when the APC was initialized.
  299. SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
  300. arguments that contain untyped data.
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. PGETSETCONTEXT ContextBlock;
  306. PKNONVOLATILE_CONTEXT_POINTERS ContextPointers;
  307. CONTEXT ContextRecord;
  308. ULONG64 ControlPc;
  309. ULONG64 EstablisherFrame;
  310. PRUNTIME_FUNCTION FunctionEntry;
  311. PVOID HandlerData;
  312. ULONG64 ImageBase;
  313. PLEGACY_SAVE_AREA NpxFrame;
  314. ULONG64 TrapFrame;
  315. PETHREAD Thread;
  316. UNREFERENCED_PARAMETER(NormalRoutine);
  317. UNREFERENCED_PARAMETER(NormalContext);
  318. UNREFERENCED_PARAMETER(SystemArgument2);
  319. PAGED_CODE();
  320. //
  321. // Get the address of the context block and compute the address of the
  322. // system entry trap frame.
  323. //
  324. ContextBlock = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
  325. ContextPointers = &ContextBlock->NonVolatileContext;
  326. Thread = Apc->SystemArgument2;
  327. EstablisherFrame = 0;
  328. TrapFrame = 0;
  329. if (ContextBlock->Mode == KernelMode) {
  330. TrapFrame = (ULONG64)Thread->Tcb.TrapFrame;
  331. }
  332. if (TrapFrame == 0) {
  333. TrapFrame = (ULONG64)PspGetBaseTrapFrame(Thread);
  334. }
  335. //
  336. // Capture the current thread context and set the initial control PC
  337. // value.
  338. //
  339. RtlCaptureContext(&ContextRecord);
  340. //
  341. // Initialize context pointers for the nonvolatile integer and floating
  342. // registers.
  343. //
  344. #if DBG
  345. RtlZeroMemory(ContextPointers, sizeof(KNONVOLATILE_CONTEXT_POINTERS));
  346. #endif
  347. ContextPointers->Rbx = &ContextRecord.Rbx;
  348. ContextPointers->Rsp = &ContextRecord.Rsp;
  349. ContextPointers->Rbp = &ContextRecord.Rbp;
  350. ContextPointers->Rsi = &ContextRecord.Rsi;
  351. ContextPointers->Rdi = &ContextRecord.Rdi;
  352. ContextPointers->R12 = &ContextRecord.R12;
  353. ContextPointers->R13 = &ContextRecord.R13;
  354. ContextPointers->R14 = &ContextRecord.R14;
  355. ContextPointers->R15 = &ContextRecord.R15;
  356. ContextPointers->Xmm6 = &ContextRecord.Xmm6;
  357. ContextPointers->Xmm7 = &ContextRecord.Xmm7;
  358. ContextPointers->Xmm8 = &ContextRecord.Xmm8;
  359. ContextPointers->Xmm9 = &ContextRecord.Xmm9;
  360. ContextPointers->Xmm10 = &ContextRecord.Xmm10;
  361. ContextPointers->Xmm11 = &ContextRecord.Xmm11;
  362. ContextPointers->Xmm12 = &ContextRecord.Xmm12;
  363. ContextPointers->Xmm13 = &ContextRecord.Xmm13;
  364. ContextPointers->Xmm14 = &ContextRecord.Xmm14;
  365. ContextPointers->Xmm15 = &ContextRecord.Xmm15;
  366. //
  367. // Start with the frame specified by the context record and virtually
  368. // unwind call frames until the system entry trap frame is encountered.
  369. //
  370. do {
  371. //
  372. // Lookup the function table entry using the point at which control
  373. // left the function.
  374. //
  375. ControlPc = ContextRecord.Rip;
  376. FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
  377. //
  378. // If there is a function table entry for the routine, then virtually
  379. // unwind to the caller of the current routine to obtain the address
  380. // where control left the caller. Otherwise, the function is a leaf
  381. // function and the return address register contains the address of
  382. // where control left the caller.
  383. //
  384. if (FunctionEntry != NULL) {
  385. RtlVirtualUnwind(UNW_FLAG_EHANDLER,
  386. ImageBase,
  387. ControlPc,
  388. FunctionEntry,
  389. &ContextRecord,
  390. &HandlerData,
  391. &EstablisherFrame,
  392. ContextPointers);
  393. } else {
  394. ContextRecord.Rip = *(PULONG64)(ContextRecord.Rsp);
  395. ContextRecord.Rsp += 8;
  396. }
  397. } while (EstablisherFrame != TrapFrame);
  398. //
  399. // If system argument one is nonzero, then set the context of the current
  400. // thread. Otherwise, get the context of the current thread.
  401. //
  402. if (*SystemArgument1 != NULL) {
  403. //
  404. // Set context.
  405. //
  406. // If the legacy state is switch, then save the the legacy floating
  407. // state, set the context, and restore the legacy floating state.
  408. // Otherwise, set the context.
  409. //
  410. if (Thread->Tcb.NpxState == LEGACY_STATE_SWITCH) {
  411. NpxFrame = (PLEGACY_SAVE_AREA)((PKTRAP_FRAME)TrapFrame + 1);
  412. KeSaveLegacyFloatingPointState(NpxFrame);
  413. PspSetContext((PKTRAP_FRAME)TrapFrame,
  414. ContextPointers,
  415. &ContextBlock->Context,
  416. ContextBlock->Mode);
  417. KeRestoreLegacyFloatingPointState(NpxFrame);
  418. } else {
  419. PspSetContext((PKTRAP_FRAME)TrapFrame,
  420. ContextPointers,
  421. &ContextBlock->Context,
  422. ContextBlock->Mode);
  423. }
  424. } else {
  425. //
  426. // Get context.
  427. //
  428. // If the legacy state is switch, then save the legacy floating state
  429. // and get the context.
  430. //
  431. // N.B. The legacy floating state is saved and restored. The reason
  432. // this is necessary is that saving the legacy floating state
  433. // alters some of the state.
  434. //
  435. if (Thread->Tcb.NpxState == LEGACY_STATE_SWITCH) {
  436. NpxFrame = (PLEGACY_SAVE_AREA)((PKTRAP_FRAME)TrapFrame + 1);
  437. KeSaveLegacyFloatingPointState(NpxFrame);
  438. KeRestoreLegacyFloatingPointState(NpxFrame);
  439. }
  440. PspGetContext((PKTRAP_FRAME)TrapFrame,
  441. ContextPointers,
  442. &ContextBlock->Context);
  443. }
  444. KeSetEvent(&ContextBlock->OperationComplete, 0, FALSE);
  445. return;
  446. }