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.

754 lines
25 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Copyright (c) 1990 Microsoft Corporation
  4. Module Name:
  5. psctxi64.c
  6. Abstract:
  7. This module implements function to get and set the context of a thread.
  8. Author:
  9. David N. Cutler (davec) 1-Oct-1990
  10. Revision History:
  11. --*/
  12. #include "psp.h"
  13. #include <ia64.h>
  14. #define ALIGN_NATS(Result, Source, Start, AddressOffset, Mask) \
  15. if (AddressOffset == Start) { \
  16. Result = (ULONGLONG)Source; \
  17. } else if (AddressOffset < Start) { \
  18. Result = (ULONGLONG)(Source << (Start - AddressOffset)); \
  19. } else { \
  20. Result = (ULONGLONG)((Source >> (AddressOffset - Start)) | \
  21. (Source << (64 + Start - AddressOffset))); \
  22. } \
  23. Result = Result & (ULONGLONG)Mask
  24. #define EXTRACT_NATS(Result, Source, Start, AddressOffset, Mask) \
  25. Result = (ULONGLONG)(Source & (ULONGLONG)Mask); \
  26. if (AddressOffset < Start) { \
  27. Result = Result >> (Start - AddressOffset); \
  28. } else if (AddressOffset > Start) { \
  29. Result = ((Result << (AddressOffset - Start)) | \
  30. (Result >> (64 + Start - AddressOffset))); \
  31. }
  32. VOID
  33. KiGetDebugContext (
  34. IN PKTRAP_FRAME TrapFrame,
  35. IN OUT PCONTEXT ContextFrame
  36. );
  37. VOID
  38. KiSetDebugContext (
  39. IN OUT PKTRAP_FRAME TrapFrame,
  40. IN PCONTEXT ContextFrame,
  41. IN KPROCESSOR_MODE ProcessorMode
  42. );
  43. VOID
  44. PspGetContext (
  45. IN PKTRAP_FRAME TrapFrame,
  46. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  47. IN OUT PCONTEXT ContextEM
  48. )
  49. /*++
  50. Routine Description:
  51. This function selectively moves the contents of the specified trap frame
  52. and nonvolatile context to the specified context record.
  53. Arguments:
  54. TrapFrame - Supplies a pointer to a trap frame.
  55. ContextPointers - Supplies the address of context pointers record.
  56. ContextEM - Supplies the address of a context record.
  57. Return Value:
  58. None.
  59. N.B. The side effect of this routine is that the dirty user stacked
  60. registers that were flushed into the kernel backing store are
  61. copied backed into the user backing store and the trap frame
  62. will be modified as a result of that.
  63. --*/
  64. {
  65. ULONGLONG IntNats1, IntNats2 = 0;
  66. USHORT R1Offset, R4Offset;
  67. SHORT Temp, BsFrameSize;
  68. if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  69. ContextEM->IntGp = TrapFrame->IntGp;
  70. ContextEM->IntSp = TrapFrame->IntSp;
  71. ContextEM->ApUNAT = TrapFrame->ApUNAT;
  72. ContextEM->BrRp = TrapFrame->BrRp;
  73. ContextEM->ApCCV = TrapFrame->ApCCV;
  74. ContextEM->ApDCR = TrapFrame->ApDCR;
  75. ContextEM->StFPSR = TrapFrame->StFPSR;
  76. ContextEM->StIPSR = TrapFrame->StIPSR;
  77. ContextEM->StIIP = TrapFrame->StIIP;
  78. ContextEM->StIFS = TrapFrame->StIFS;
  79. //
  80. // Get RSE control states from the trap frame.
  81. //
  82. ContextEM->RsPFS = TrapFrame->RsPFS;
  83. ContextEM->RsRSC = TrapFrame->RsRSC;
  84. ContextEM->RsRNAT = TrapFrame->RsRNAT;
  85. BsFrameSize = (SHORT) TrapFrame->StIFS & PFS_SIZE_MASK;
  86. Temp = BsFrameSize - (SHORT)((TrapFrame->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
  87. while (Temp > 0) {
  88. BsFrameSize++;
  89. Temp -= NAT_BITS_PER_RNAT_REG;
  90. }
  91. ContextEM->RsBSP = TrapFrame->RsBSP - (BsFrameSize * 8);
  92. ContextEM->RsBSPSTORE = ContextEM->RsBSP;
  93. //
  94. // Get preserved applicaton registers
  95. //
  96. ContextEM->ApLC = *ContextPointers->ApLC;
  97. ContextEM->ApEC = (*ContextPointers->ApEC >> PFS_EC_SHIFT) & PFS_EC_MASK;
  98. //
  99. // Get iA status
  100. //
  101. ContextEM->StFCR = __getReg(CV_IA64_AR21);
  102. ContextEM->Eflag = __getReg(CV_IA64_AR24);
  103. ContextEM->SegCSD = __getReg(CV_IA64_AR25);
  104. ContextEM->SegSSD = __getReg(CV_IA64_AR26);
  105. ContextEM->Cflag = __getReg(CV_IA64_AR27);
  106. ContextEM->StFSR = __getReg(CV_IA64_AR28);
  107. ContextEM->StFIR = __getReg(CV_IA64_AR29);
  108. ContextEM->StFDR = __getReg(CV_IA64_AR30);
  109. }
  110. if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  111. ContextEM->IntT0 = TrapFrame->IntT0;
  112. ContextEM->IntT1 = TrapFrame->IntT1;
  113. ContextEM->IntT2 = TrapFrame->IntT2;
  114. ContextEM->IntT3 = TrapFrame->IntT3;
  115. ContextEM->IntT4 = TrapFrame->IntT4;
  116. ContextEM->IntV0 = TrapFrame->IntV0;
  117. ContextEM->IntTeb = TrapFrame->IntTeb;
  118. ContextEM->Preds = TrapFrame->Preds;
  119. //
  120. // t5 - t22
  121. //
  122. memcpy(&ContextEM->IntT5, &TrapFrame->IntT5, 18*sizeof(ULONGLONG));
  123. //
  124. // Get branch registers
  125. //
  126. ContextEM->BrT0 = TrapFrame->BrT0;
  127. ContextEM->BrT1 = TrapFrame->BrT1;
  128. ContextEM->BrS0 = *ContextPointers->BrS0;
  129. ContextEM->BrS1 = *ContextPointers->BrS1;
  130. ContextEM->BrS2 = *ContextPointers->BrS2;
  131. ContextEM->BrS3 = *ContextPointers->BrS3;
  132. ContextEM->BrS4 = *ContextPointers->BrS4;
  133. //
  134. // Get integer registers s0 - s3 from exception frame.
  135. //
  136. ContextEM->IntS0 = *ContextPointers->IntS0;
  137. ContextEM->IntS1 = *ContextPointers->IntS1;
  138. ContextEM->IntS2 = *ContextPointers->IntS2;
  139. ContextEM->IntS3 = *ContextPointers->IntS3;
  140. IntNats2 |= (((*ContextPointers->IntS0Nat >> (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3)) & 0x1) << 4);
  141. IntNats2 |= (((*ContextPointers->IntS1Nat >> (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3)) & 0x1) << 5);
  142. IntNats2 |= (((*ContextPointers->IntS2Nat >> (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3)) & 0x1) << 6);
  143. IntNats2 |= (((*ContextPointers->IntS3Nat >> (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3)) & 0x1) << 7);
  144. //
  145. // Get the integer nats field in the context
  146. // *ContextPointers->IntNats has Nats for preserved regs
  147. //
  148. R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
  149. R4Offset = (USHORT)((ULONG_PTR)(ContextPointers->IntS0) >> 3) & 0x3f;
  150. ALIGN_NATS(IntNats1, TrapFrame->IntNats, 1, R1Offset, 0xFFFFFF0E);
  151. ContextEM->IntNats = IntNats1 | IntNats2;
  152. #ifdef DEBUG
  153. DbgPrint("PspGetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, IntNats1 = 0x%I64x\n",
  154. R1Offset, TrapFrame->IntNats, IntNats1);
  155. #endif
  156. }
  157. if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
  158. ContextEM->StFPSR = TrapFrame->StFPSR;
  159. //
  160. // Get floating registers fs0 - fs19
  161. //
  162. ContextEM->FltS0 = *ContextPointers->FltS0;
  163. ContextEM->FltS1 = *ContextPointers->FltS1;
  164. ContextEM->FltS2 = *ContextPointers->FltS2;
  165. ContextEM->FltS3 = *ContextPointers->FltS3;
  166. ContextEM->FltS4 = *ContextPointers->FltS4;
  167. ContextEM->FltS5 = *ContextPointers->FltS5;
  168. ContextEM->FltS6 = *ContextPointers->FltS6;
  169. ContextEM->FltS7 = *ContextPointers->FltS7;
  170. ContextEM->FltS8 = *ContextPointers->FltS8;
  171. ContextEM->FltS9 = *ContextPointers->FltS9;
  172. ContextEM->FltS10 = *ContextPointers->FltS10;
  173. ContextEM->FltS11 = *ContextPointers->FltS11;
  174. ContextEM->FltS12 = *ContextPointers->FltS12;
  175. ContextEM->FltS13 = *ContextPointers->FltS13;
  176. ContextEM->FltS14 = *ContextPointers->FltS14;
  177. ContextEM->FltS15 = *ContextPointers->FltS15;
  178. ContextEM->FltS16 = *ContextPointers->FltS16;
  179. ContextEM->FltS17 = *ContextPointers->FltS17;
  180. ContextEM->FltS18 = *ContextPointers->FltS18;
  181. ContextEM->FltS19 = *ContextPointers->FltS19;
  182. //
  183. // Get floating registers ft0 - ft9 from trap frame.
  184. //
  185. RtlCopyIa64FloatRegisterContext(&ContextEM->FltT0,
  186. &TrapFrame->FltT0,
  187. sizeof(FLOAT128) * (10));
  188. }
  189. if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
  190. ContextEM->StFPSR = TrapFrame->StFPSR;
  191. //
  192. // Get floating regs f32 - f127 from higher floating point save area
  193. //
  194. if (TrapFrame->PreviousMode == UserMode) {
  195. RtlCopyIa64FloatRegisterContext(
  196. &ContextEM->FltF32,
  197. (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase),
  198. 96*sizeof(FLOAT128)
  199. );
  200. }
  201. }
  202. //
  203. // Get h/w debug register context
  204. //
  205. if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
  206. KiGetDebugContext(TrapFrame, ContextEM);
  207. }
  208. return;
  209. }
  210. VOID
  211. PspSetContext (
  212. IN OUT PKTRAP_FRAME TrapFrame,
  213. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  214. IN PCONTEXT ContextEM,
  215. IN KPROCESSOR_MODE ProcessorMode
  216. )
  217. /*++
  218. Routine Description:
  219. This function selectively moves the contents of the specified context
  220. record to the specified trap frame and nonvolatile context.
  221. We're expecting a plabel to have been passed in the IIP (we won't have a valid
  222. Global pointer) and if we have a plabel we fill in the correct Global pointer and
  223. IIP. Technically, the GP is part of the CONTEXT_CONTROL with the EM architecture
  224. so we only need to check to see if CONTEXT_CONTROL has been specified.
  225. Arguments:
  226. TrapFrame - Supplies the address of the trap frame.
  227. ContextPointers - Supplies the address of context pointers record.
  228. ContextEM - Supplies the address of a context record.
  229. ProcessorMode - Supplies the processor mode to use when sanitizing
  230. the PSR and FSR.
  231. Return Value:
  232. None.
  233. --*/
  234. {
  235. SHORT BsFrameSize;
  236. SHORT TempFrameSize;
  237. USHORT R1Offset, R4Offset;
  238. USHORT RNatSaveIndex;
  239. if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  240. TrapFrame->IntGp = ContextEM->IntGp;
  241. TrapFrame->IntSp = ContextEM->IntSp;
  242. TrapFrame->ApUNAT = ContextEM->ApUNAT;
  243. TrapFrame->BrRp = ContextEM->BrRp;
  244. TrapFrame->ApCCV = ContextEM->ApCCV;
  245. TrapFrame->ApDCR = SANITIZE_DCR(ContextEM->ApDCR, ProcessorMode);
  246. //
  247. // Set preserved applicaton registers.
  248. //
  249. *ContextPointers->ApLC = ContextEM->ApLC;
  250. *ContextPointers->ApEC &= ~((ULONGLONG)PFS_EC_MASK << PFS_EC_SHIFT);
  251. *ContextPointers->ApEC |= ((ContextEM->ApEC & PFS_EC_MASK) << PFS_EC_SHIFT);
  252. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  253. TrapFrame->StIIP = ContextEM->StIIP;
  254. TrapFrame->StIFS = SANITIZE_IFS(ContextEM->StIFS, ProcessorMode);
  255. TrapFrame->StIPSR = SANITIZE_PSR(ContextEM->StIPSR, ProcessorMode);
  256. TrapFrame->RsPFS = SANITIZE_PFS(ContextEM->RsPFS, ProcessorMode);
  257. BsFrameSize = (SHORT) ContextEM->StIFS & PFS_SIZE_MASK;
  258. RNatSaveIndex = (USHORT)((ContextEM->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
  259. TempFrameSize = RNatSaveIndex + BsFrameSize - NAT_BITS_PER_RNAT_REG;
  260. while (TempFrameSize >= 0) {
  261. BsFrameSize++;
  262. TempFrameSize -= NAT_BITS_PER_RNAT_REG;
  263. }
  264. //
  265. // If the BSP value is not being changed then preserve the
  266. // preload count. This is only necessary if KeFlushUserRseState
  267. // failed for some reason.
  268. //
  269. if (TrapFrame->RsBSP == ContextEM->RsBSP + BsFrameSize * 8) {
  270. RSC Rsc;
  271. Rsc.ull = ZERO_PRELOAD_SIZE(ContextEM->RsRSC);
  272. Rsc.sb.rsc_preload = ((struct _RSC *) &(TrapFrame->RsRSC))->rsc_preload;
  273. TrapFrame->RsRSC = Rsc.ull;
  274. } else {
  275. TrapFrame->RsRSC = ZERO_PRELOAD_SIZE(ContextEM->RsRSC);
  276. }
  277. TrapFrame->RsBSP = ContextEM->RsBSP + BsFrameSize * 8;
  278. TrapFrame->RsBSPSTORE = TrapFrame->RsBSP;
  279. TrapFrame->RsRNAT = ContextEM->RsRNAT;
  280. #ifdef DEBUG
  281. DbgPrint ("PspSetContext CONTROL: TrapFrame->RsRNAT = 0x%I64x\n",
  282. TrapFrame->RsRNAT);
  283. #endif
  284. //
  285. // DebugActive controls h/w debug registers. Set if new psr.db = 1
  286. //
  287. PCR->DebugActive = KeGetCurrentThread()->DebugActive = (BOOLEAN)((TrapFrame->StIPSR & (1I64 << PSR_DB)) != 0);
  288. //
  289. // Set and sanitize iA status
  290. //
  291. __setReg(CV_IA64_AR21, SANITIZE_AR21_FCR (ContextEM->StFCR, ProcessorMode));
  292. __setReg(CV_IA64_AR24, SANITIZE_AR24_EFLAGS (ContextEM->Eflag, ProcessorMode));
  293. __setReg(CV_IA64_AR25, ContextEM->SegCSD);
  294. __setReg(CV_IA64_AR26, ContextEM->SegSSD);
  295. __setReg(CV_IA64_AR27, SANITIZE_AR27_CFLG (ContextEM->Cflag, ProcessorMode));
  296. __setReg(CV_IA64_AR28, SANITIZE_AR28_FSR (ContextEM->StFSR, ProcessorMode));
  297. __setReg(CV_IA64_AR29, SANITIZE_AR29_FIR (ContextEM->StFIR, ProcessorMode));
  298. __setReg(CV_IA64_AR30, SANITIZE_AR30_FDR (ContextEM->StFDR, ProcessorMode));
  299. }
  300. if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  301. TrapFrame->IntT0 = ContextEM->IntT0;
  302. TrapFrame->IntT1 = ContextEM->IntT1;
  303. TrapFrame->IntT2 = ContextEM->IntT2;
  304. TrapFrame->IntT3 = ContextEM->IntT3;
  305. TrapFrame->IntT4 = ContextEM->IntT4;
  306. TrapFrame->IntV0 = ContextEM->IntV0;
  307. TrapFrame->IntTeb = ContextEM->IntTeb;
  308. TrapFrame->Preds = ContextEM->Preds;
  309. //
  310. // t5 - t2
  311. //
  312. RtlCopyMemory(&TrapFrame->IntT5, &ContextEM->IntT5, 18*sizeof(ULONGLONG));
  313. //
  314. // Set the integer nats fields
  315. //
  316. R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
  317. EXTRACT_NATS(TrapFrame->IntNats, ContextEM->IntNats,
  318. 1, R1Offset, 0xFFFFFF0E);
  319. //
  320. // Set the preserved integer NAT fields
  321. //
  322. R4Offset = (USHORT)((ULONG_PTR)(ContextPointers->IntS0) >> 3) & 0x3f;
  323. //
  324. // EXTRACT_NATS(*ContextPointers->IntNats, ContextEM->IntNats,
  325. // 4, R4Offset, 0xF0);
  326. *ContextPointers->IntS0 = ContextEM->IntS0;
  327. *ContextPointers->IntS1 = ContextEM->IntS1;
  328. *ContextPointers->IntS2 = ContextEM->IntS2;
  329. *ContextPointers->IntS3 = ContextEM->IntS3;
  330. *ContextPointers->IntS0Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
  331. *ContextPointers->IntS1Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
  332. *ContextPointers->IntS2Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
  333. *ContextPointers->IntS3Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
  334. *ContextPointers->IntS0Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
  335. *ContextPointers->IntS1Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
  336. *ContextPointers->IntS2Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
  337. *ContextPointers->IntS3Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
  338. #ifdef DEBUG
  339. DbgPrint("PspSetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, Context->IntNats = 0x%I64x\n",
  340. R1Offset, TrapFrame->IntNats, ContextEM->IntNats);
  341. #endif
  342. *ContextPointers->BrS0 = ContextEM->BrS0;
  343. *ContextPointers->BrS1 = ContextEM->BrS1;
  344. *ContextPointers->BrS2 = ContextEM->BrS2;
  345. *ContextPointers->BrS3 = ContextEM->BrS3;
  346. *ContextPointers->BrS4 = ContextEM->BrS4;
  347. TrapFrame->BrT0 = ContextEM->BrT0;
  348. TrapFrame->BrT1 = ContextEM->BrT1;
  349. }
  350. if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
  351. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  352. //
  353. // Set floating registers fs0 - fs19.
  354. //
  355. *ContextPointers->FltS0 = ContextEM->FltS0;
  356. *ContextPointers->FltS1 = ContextEM->FltS1;
  357. *ContextPointers->FltS2 = ContextEM->FltS2;
  358. *ContextPointers->FltS3 = ContextEM->FltS3;
  359. *ContextPointers->FltS4 = ContextEM->FltS4;
  360. *ContextPointers->FltS5 = ContextEM->FltS5;
  361. *ContextPointers->FltS6 = ContextEM->FltS6;
  362. *ContextPointers->FltS7 = ContextEM->FltS7;
  363. *ContextPointers->FltS8 = ContextEM->FltS8;
  364. *ContextPointers->FltS9 = ContextEM->FltS9;
  365. *ContextPointers->FltS10 = ContextEM->FltS10;
  366. *ContextPointers->FltS11 = ContextEM->FltS11;
  367. *ContextPointers->FltS12 = ContextEM->FltS12;
  368. *ContextPointers->FltS13 = ContextEM->FltS13;
  369. *ContextPointers->FltS14 = ContextEM->FltS14;
  370. *ContextPointers->FltS15 = ContextEM->FltS15;
  371. *ContextPointers->FltS16 = ContextEM->FltS16;
  372. *ContextPointers->FltS17 = ContextEM->FltS17;
  373. *ContextPointers->FltS18 = ContextEM->FltS18;
  374. *ContextPointers->FltS19 = ContextEM->FltS19;
  375. //
  376. // Set floating registers ft0 - ft9.
  377. //
  378. RtlCopyIa64FloatRegisterContext(&TrapFrame->FltT0,
  379. &ContextEM->FltT0,
  380. sizeof(FLOAT128) * (10));
  381. }
  382. if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
  383. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  384. if (ProcessorMode == UserMode) {
  385. //
  386. // Update the higher floating point save area (f32-f127) and
  387. // set the corresponding modified bit in the PSR to 1.
  388. //
  389. RtlCopyIa64FloatRegisterContext(
  390. (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase),
  391. &ContextEM->FltF32,
  392. 96*sizeof(FLOAT128));
  393. //
  394. // set the dfh bit to force a reload of the high fp register
  395. // set on the next user access
  396. //
  397. TrapFrame->StIPSR |= (1i64 << PSR_DFH);
  398. }
  399. }
  400. //
  401. // Set debug register contents if specified.
  402. //
  403. if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
  404. KiSetDebugContext (TrapFrame, ContextEM, ProcessorMode);
  405. }
  406. return;
  407. }
  408. VOID
  409. PspGetSetContextSpecialApcMain (
  410. IN PKAPC Apc,
  411. IN PKNORMAL_ROUTINE *NormalRoutine,
  412. IN PVOID *NormalContext,
  413. IN PVOID *SystemArgument1,
  414. IN PVOID *SystemArgument2
  415. )
  416. /*++
  417. Routine Description:
  418. This function either captures the user mode state of the current
  419. thread, or sets the user mode state of the current thread. The
  420. operation type is determined by the value of SystemArgument1. A
  421. zero value is used for get context, and a nonzero value is used
  422. for set context.
  423. Arguments:
  424. Apc - Supplies a pointer to the APC control object that caused entry
  425. into this routine.
  426. NormalRoutine - Supplies a pointer to the normal routine function that
  427. was specified when the APC was initialized. This parameter is not
  428. used.
  429. NormalContext - Supplies a pointer to an arbitrary data structure that
  430. was specified when the APC was initialized. This parameter is not
  431. used.
  432. SystemArgument1, SystemArgument2 - Supplies a set of two pointers to two
  433. arguments that contain untyped data.
  434. The first arguement is used to distinguish between get and set requests.
  435. A value of zero signifies that GetThreadContext was requested.
  436. A non-zero value signifies that SetThreadContext was requested.
  437. The Second arguement has the thread handle. The second arguement is
  438. not used.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. PGETSETCONTEXT ContextInfo;
  444. KNONVOLATILE_CONTEXT_POINTERS ContextPointers; // Not currently used, needed later.
  445. CONTEXT ContextRecord;
  446. ULONGLONG ControlPc;
  447. FRAME_POINTERS EstablisherFrame;
  448. PRUNTIME_FUNCTION FunctionEntry;
  449. BOOLEAN InFunction;
  450. PKTRAP_FRAME TrFrame1;
  451. ULONGLONG ImageBase;
  452. ULONGLONG TargetGp;
  453. UNREFERENCED_PARAMETER (NormalRoutine);
  454. UNREFERENCED_PARAMETER (NormalContext);
  455. UNREFERENCED_PARAMETER (SystemArgument2);
  456. //
  457. // Get the address of the context frame and compute the address of the
  458. // system entry trap frame.
  459. //
  460. ContextInfo = CONTAINING_RECORD (Apc, GETSETCONTEXT, Apc);
  461. TrFrame1 = NULL;
  462. if (ContextInfo->Mode == KernelMode) {
  463. TrFrame1 = PsGetCurrentThread()->Tcb.TrapFrame;
  464. }
  465. if (TrFrame1 == NULL) {
  466. TrFrame1 = (PKTRAP_FRAME)(((ULONG_PTR)PsGetCurrentThread()->Tcb.InitialStack
  467. - KTHREAD_STATE_SAVEAREA_LENGTH - KTRAP_FRAME_LENGTH));
  468. }
  469. //
  470. // Capture the current thread context and set the initial control PC
  471. // value.
  472. //
  473. RtlCaptureContext(&ContextRecord);
  474. ControlPc = ContextRecord.BrRp;
  475. //
  476. // Initialize context pointers for the nonvolatile integer and floating
  477. // registers.
  478. //
  479. ContextPointers.FltS0 = &ContextRecord.FltS0;
  480. ContextPointers.FltS1 = &ContextRecord.FltS1;
  481. ContextPointers.FltS2 = &ContextRecord.FltS2;
  482. ContextPointers.FltS3 = &ContextRecord.FltS3;
  483. ContextPointers.FltS4 = &ContextRecord.FltS4;
  484. ContextPointers.FltS5 = &ContextRecord.FltS5;
  485. ContextPointers.FltS6 = &ContextRecord.FltS6;
  486. ContextPointers.FltS7 = &ContextRecord.FltS7;
  487. ContextPointers.FltS8 = &ContextRecord.FltS8;
  488. ContextPointers.FltS9 = &ContextRecord.FltS9;
  489. ContextPointers.FltS10 = &ContextRecord.FltS10;
  490. ContextPointers.FltS11 = &ContextRecord.FltS11;
  491. ContextPointers.FltS12 = &ContextRecord.FltS12;
  492. ContextPointers.FltS13 = &ContextRecord.FltS13;
  493. ContextPointers.FltS14 = &ContextRecord.FltS14;
  494. ContextPointers.FltS15 = &ContextRecord.FltS15;
  495. ContextPointers.FltS16 = &ContextRecord.FltS16;
  496. ContextPointers.FltS17 = &ContextRecord.FltS17;
  497. ContextPointers.FltS18 = &ContextRecord.FltS18;
  498. ContextPointers.FltS19 = &ContextRecord.FltS19;
  499. ContextPointers.IntS0 = &ContextRecord.IntS0;
  500. ContextPointers.IntS1 = &ContextRecord.IntS1;
  501. ContextPointers.IntS2 = &ContextRecord.IntS2;
  502. ContextPointers.IntS3 = &ContextRecord.IntS3;
  503. ContextPointers.IntSp = &ContextRecord.IntSp;
  504. ContextPointers.BrS0 = &ContextRecord.BrS0;
  505. ContextPointers.BrS1 = &ContextRecord.BrS1;
  506. ContextPointers.BrS2 = &ContextRecord.BrS2;
  507. ContextPointers.BrS3 = &ContextRecord.BrS3;
  508. ContextPointers.BrS4 = &ContextRecord.BrS4;
  509. ContextPointers.ApLC = &ContextRecord.ApLC;
  510. ContextPointers.ApEC = &ContextRecord.ApEC;
  511. //
  512. // Start with the frame specified by the context record and virtually
  513. // unwind call frames until the system entry trap frame is encountered.
  514. //
  515. do {
  516. //
  517. // Lookup the function table entry using the point at which control
  518. // left the procedure.
  519. //
  520. FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
  521. //
  522. // If there is a function table entry for the routine, then virtually
  523. // unwind to the caller of the current routine to obtain the address
  524. // where control left the caller.
  525. //
  526. if (FunctionEntry != NULL) {
  527. ControlPc = RtlVirtualUnwind(ImageBase,
  528. ControlPc,
  529. FunctionEntry,
  530. &ContextRecord,
  531. &InFunction,
  532. &EstablisherFrame,
  533. &ContextPointers);
  534. } else {
  535. SHORT BsFrameSize, TempFrameSize;
  536. ControlPc = ContextRecord.BrRp;
  537. ContextRecord.StIFS = ContextRecord.RsPFS;
  538. BsFrameSize = (SHORT)(ContextRecord.StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
  539. TempFrameSize = BsFrameSize - (SHORT)((ContextRecord.RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
  540. while (TempFrameSize > 0) {
  541. BsFrameSize++;
  542. TempFrameSize -= NAT_BITS_PER_RNAT_REG;
  543. }
  544. ContextRecord.RsBSP -= BsFrameSize * sizeof(ULONGLONG);
  545. }
  546. } while ((PVOID)ContextRecord.IntSp != TrFrame1);
  547. //
  548. // Process GetThreadContext or SetThreadContext as specified.
  549. //
  550. if (*SystemArgument1 != 0) {
  551. //
  552. // Set Context from proper Context mode
  553. //
  554. PspSetContext(TrFrame1, &ContextPointers, &ContextInfo->Context,
  555. ContextInfo->Mode);
  556. } else {
  557. //
  558. // Get Context from proper Context mode
  559. //
  560. KeFlushUserRseState(TrFrame1);
  561. PspGetContext(TrFrame1, &ContextPointers, &ContextInfo->Context);
  562. }
  563. KeSetEvent(&ContextInfo->OperationComplete, 0, FALSE);
  564. return;
  565. }