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.

759 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;
  67. if (ContextEM->ContextFlags & CONTEXT_EXCEPTION_REQUEST) {
  68. ContextEM->ContextFlags |= CONTEXT_EXCEPTION_REPORTING;
  69. ContextEM->ContextFlags &= ~(CONTEXT_EXCEPTION_ACTIVE | CONTEXT_SERVICE_ACTIVE);
  70. if (TRAP_FRAME_TYPE(TrapFrame) == SYSCALL_FRAME) {
  71. ContextEM->ContextFlags |= CONTEXT_SERVICE_ACTIVE;
  72. } else if (TRAP_FRAME_TYPE(TrapFrame) != INTERRUPT_FRAME) {
  73. ContextEM->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
  74. }
  75. }
  76. if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  77. ContextEM->IntGp = TrapFrame->IntGp;
  78. ContextEM->IntSp = TrapFrame->IntSp;
  79. ContextEM->ApUNAT = TrapFrame->ApUNAT;
  80. ContextEM->BrRp = TrapFrame->BrRp;
  81. ContextEM->StFPSR = TrapFrame->StFPSR;
  82. ContextEM->StIPSR = TrapFrame->StIPSR;
  83. ContextEM->StIIP = TrapFrame->StIIP;
  84. ContextEM->StIFS = TrapFrame->StIFS;
  85. if (TRAP_FRAME_TYPE(TrapFrame) != SYSCALL_FRAME) {
  86. ContextEM->ApCCV = TrapFrame->ApCCV;
  87. ContextEM->SegCSD = TrapFrame->SegCSD;
  88. }
  89. //
  90. // Get RSE control states from the trap frame.
  91. //
  92. ContextEM->RsPFS = TrapFrame->RsPFS;
  93. ContextEM->RsRSC = TrapFrame->RsRSC;
  94. ContextEM->RsRNAT = TrapFrame->RsRNAT;
  95. ContextEM->RsBSP = RtlpRseShrinkBySOF (TrapFrame->RsBSP, TrapFrame->StIFS);
  96. ContextEM->RsBSPSTORE = ContextEM->RsBSP;
  97. //
  98. // Get preserved applicaton registers
  99. //
  100. ContextEM->ApLC = *ContextPointers->ApLC;
  101. ContextEM->ApEC = (*ContextPointers->ApEC >> PFS_EC_SHIFT) & PFS_EC_MASK;
  102. //
  103. // Get iA status
  104. //
  105. ContextEM->StFCR = __getReg(CV_IA64_AR21);
  106. ContextEM->Eflag = __getReg(CV_IA64_AR24);
  107. ContextEM->SegSSD = __getReg(CV_IA64_AR26);
  108. ContextEM->Cflag = __getReg(CV_IA64_AR27);
  109. ContextEM->StFSR = __getReg(CV_IA64_AR28);
  110. ContextEM->StFIR = __getReg(CV_IA64_AR29);
  111. ContextEM->StFDR = __getReg(CV_IA64_AR30);
  112. ContextEM->ApDCR = __getReg(CV_IA64_ApDCR);
  113. }
  114. if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  115. ContextEM->Preds = TrapFrame->Preds;
  116. ContextEM->IntTeb = TrapFrame->IntTeb;
  117. ContextEM->IntV0 = TrapFrame->IntV0;
  118. ASSERT((TrapFrame->EOFMarker & ~0xffI64) == KTRAP_FRAME_EOF);
  119. if (TRAP_FRAME_TYPE(TrapFrame) != SYSCALL_FRAME) {
  120. ContextEM->IntT0 = TrapFrame->IntT0;
  121. ContextEM->IntT1 = TrapFrame->IntT1;
  122. ContextEM->IntT2 = TrapFrame->IntT2;
  123. ContextEM->IntT3 = TrapFrame->IntT3;
  124. ContextEM->IntT4 = TrapFrame->IntT4;
  125. //
  126. // t5 - t22
  127. //
  128. memcpy(&ContextEM->IntT5, &TrapFrame->IntT5, 18*sizeof(ULONGLONG));
  129. //
  130. // Get branch registers
  131. //
  132. ContextEM->BrT0 = TrapFrame->BrT0;
  133. ContextEM->BrT1 = TrapFrame->BrT1;
  134. }
  135. ContextEM->BrS0 = *ContextPointers->BrS0;
  136. ContextEM->BrS1 = *ContextPointers->BrS1;
  137. ContextEM->BrS2 = *ContextPointers->BrS2;
  138. ContextEM->BrS3 = *ContextPointers->BrS3;
  139. ContextEM->BrS4 = *ContextPointers->BrS4;
  140. //
  141. // Get integer registers s0 - s3 from exception frame.
  142. //
  143. ContextEM->IntS0 = *ContextPointers->IntS0;
  144. ContextEM->IntS1 = *ContextPointers->IntS1;
  145. ContextEM->IntS2 = *ContextPointers->IntS2;
  146. ContextEM->IntS3 = *ContextPointers->IntS3;
  147. IntNats2 |= (((*ContextPointers->IntS0Nat >> (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3)) & 0x1) << 4);
  148. IntNats2 |= (((*ContextPointers->IntS1Nat >> (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3)) & 0x1) << 5);
  149. IntNats2 |= (((*ContextPointers->IntS2Nat >> (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3)) & 0x1) << 6);
  150. IntNats2 |= (((*ContextPointers->IntS3Nat >> (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3)) & 0x1) << 7);
  151. //
  152. // Get the integer nats field in the context
  153. // *ContextPointers->IntNats has Nats for preserved regs
  154. //
  155. R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
  156. ALIGN_NATS(IntNats1, TrapFrame->IntNats, 1, R1Offset, 0xFFFFFF0E);
  157. ContextEM->IntNats = IntNats1 | IntNats2;
  158. #ifdef DEBUG
  159. DbgPrint("PspGetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, IntNats1 = 0x%I64x\n",
  160. R1Offset, TrapFrame->IntNats, IntNats1);
  161. #endif
  162. }
  163. if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
  164. ContextEM->StFPSR = TrapFrame->StFPSR;
  165. //
  166. // Get floating registers fs0 - fs19
  167. //
  168. ContextEM->FltS0 = *ContextPointers->FltS0;
  169. ContextEM->FltS1 = *ContextPointers->FltS1;
  170. ContextEM->FltS2 = *ContextPointers->FltS2;
  171. ContextEM->FltS3 = *ContextPointers->FltS3;
  172. ContextEM->FltS4 = *ContextPointers->FltS4;
  173. ContextEM->FltS5 = *ContextPointers->FltS5;
  174. ContextEM->FltS6 = *ContextPointers->FltS6;
  175. ContextEM->FltS7 = *ContextPointers->FltS7;
  176. ContextEM->FltS8 = *ContextPointers->FltS8;
  177. ContextEM->FltS9 = *ContextPointers->FltS9;
  178. ContextEM->FltS10 = *ContextPointers->FltS10;
  179. ContextEM->FltS11 = *ContextPointers->FltS11;
  180. ContextEM->FltS12 = *ContextPointers->FltS12;
  181. ContextEM->FltS13 = *ContextPointers->FltS13;
  182. ContextEM->FltS14 = *ContextPointers->FltS14;
  183. ContextEM->FltS15 = *ContextPointers->FltS15;
  184. ContextEM->FltS16 = *ContextPointers->FltS16;
  185. ContextEM->FltS17 = *ContextPointers->FltS17;
  186. ContextEM->FltS18 = *ContextPointers->FltS18;
  187. ContextEM->FltS19 = *ContextPointers->FltS19;
  188. if (TRAP_FRAME_TYPE(TrapFrame) != SYSCALL_FRAME) {
  189. //
  190. // Get floating registers ft0 - ft9 from trap frame.
  191. //
  192. RtlCopyIa64FloatRegisterContext(&ContextEM->FltT0,
  193. &TrapFrame->FltT0,
  194. sizeof(FLOAT128) * (10));
  195. }
  196. }
  197. if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
  198. ContextEM->StFPSR = TrapFrame->StFPSR;
  199. //
  200. // Get floating regs f32 - f127 from higher floating point save area
  201. //
  202. if (TrapFrame->PreviousMode == UserMode) {
  203. RtlCopyIa64FloatRegisterContext(
  204. &ContextEM->FltF32,
  205. (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase),
  206. 96*sizeof(FLOAT128)
  207. );
  208. }
  209. }
  210. //
  211. // Get h/w debug register context
  212. //
  213. if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
  214. KiGetDebugContext(TrapFrame, ContextEM);
  215. }
  216. return;
  217. }
  218. VOID
  219. PspSetContext (
  220. IN OUT PKTRAP_FRAME TrapFrame,
  221. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  222. IN PCONTEXT ContextEM,
  223. IN KPROCESSOR_MODE ProcessorMode
  224. )
  225. /*++
  226. Routine Description:
  227. This function selectively moves the contents of the specified context
  228. record to the specified trap frame and nonvolatile context.
  229. We're expecting a plabel to have been passed in the IIP (we won't have a valid
  230. Global pointer) and if we have a plabel we fill in the correct Global pointer and
  231. IIP. Technically, the GP is part of the CONTEXT_CONTROL with the EM architecture
  232. so we only need to check to see if CONTEXT_CONTROL has been specified.
  233. Arguments:
  234. TrapFrame - Supplies the address of the trap frame.
  235. ContextPointers - Supplies the address of context pointers record.
  236. ContextEM - Supplies the address of a context record.
  237. ProcessorMode - Supplies the processor mode to use when sanitizing
  238. the PSR and FSR.
  239. Return Value:
  240. None.
  241. --*/
  242. {
  243. USHORT R1Offset;
  244. ULONGLONG NewBsp;
  245. //
  246. // Indicate the trap frame has been modified by a set context.
  247. // This is used by the emulation code to detect that the trap frame
  248. // has been changed after trap has occured.
  249. //
  250. TrapFrame->EOFMarker |= MODIFIED_FRAME;
  251. if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  252. TrapFrame->IntGp = ContextEM->IntGp;
  253. TrapFrame->IntSp = ContextEM->IntSp;
  254. TrapFrame->ApUNAT = ContextEM->ApUNAT;
  255. TrapFrame->BrRp = ContextEM->BrRp;
  256. TrapFrame->ApCCV = ContextEM->ApCCV;
  257. TrapFrame->SegCSD = ContextEM->SegCSD;
  258. //
  259. // Set preserved applicaton registers.
  260. //
  261. *ContextPointers->ApLC = ContextEM->ApLC;
  262. *ContextPointers->ApEC &= ~((ULONGLONG)PFS_EC_MASK << PFS_EC_SHIFT);
  263. *ContextPointers->ApEC |= ((ContextEM->ApEC & PFS_EC_MASK) << PFS_EC_SHIFT);
  264. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  265. TrapFrame->StIIP = ContextEM->StIIP;
  266. TrapFrame->StIFS = SANITIZE_IFS(ContextEM->StIFS, ProcessorMode);
  267. TrapFrame->StIPSR = SANITIZE_PSR(ContextEM->StIPSR, ProcessorMode);
  268. TrapFrame->RsPFS = SANITIZE_PFS(ContextEM->RsPFS, ProcessorMode);
  269. //
  270. // If the BSP value is not being changed then preserve the
  271. // preload count. This is only necessary if KeFlushUserRseState
  272. // failed for some reason.
  273. //
  274. NewBsp = RtlpRseGrowBySOF (ContextEM->RsBSP, ContextEM->StIFS);
  275. if (TrapFrame->RsBSP == NewBsp) {
  276. RSC Rsc;
  277. Rsc.ull = ZERO_PRELOAD_SIZE(SANITIZE_RSC(ContextEM->RsRSC, ProcessorMode));
  278. Rsc.sb.rsc_preload = ((struct _RSC *) &(TrapFrame->RsRSC))->rsc_preload;
  279. TrapFrame->RsRSC = Rsc.ull;
  280. } else {
  281. TrapFrame->RsRSC = ZERO_PRELOAD_SIZE(SANITIZE_RSC(ContextEM->RsRSC, ProcessorMode));
  282. TrapFrame->RsBSP = NewBsp;
  283. }
  284. TrapFrame->RsBSPSTORE = TrapFrame->RsBSP;
  285. TrapFrame->RsRNAT = ContextEM->RsRNAT;
  286. #ifdef DEBUG
  287. DbgPrint ("PspSetContext CONTROL: TrapFrame->RsRNAT = 0x%I64x\n",
  288. TrapFrame->RsRNAT);
  289. #endif
  290. //
  291. // Set and sanitize iA status
  292. //
  293. __setReg(CV_IA64_AR21, SANITIZE_AR21_FCR (ContextEM->StFCR, ProcessorMode));
  294. __setReg(CV_IA64_AR24, SANITIZE_AR24_EFLAGS (ContextEM->Eflag, ProcessorMode));
  295. __setReg(CV_IA64_AR26, ContextEM->SegSSD);
  296. __setReg(CV_IA64_AR27, SANITIZE_AR27_CFLG (ContextEM->Cflag, ProcessorMode));
  297. __setReg(CV_IA64_AR28, SANITIZE_AR28_FSR (ContextEM->StFSR, ProcessorMode));
  298. __setReg(CV_IA64_AR29, SANITIZE_AR29_FIR (ContextEM->StFIR, ProcessorMode));
  299. __setReg(CV_IA64_AR30, SANITIZE_AR30_FDR (ContextEM->StFDR, ProcessorMode));
  300. }
  301. if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  302. TrapFrame->IntT0 = ContextEM->IntT0;
  303. TrapFrame->IntT1 = ContextEM->IntT1;
  304. TrapFrame->IntT2 = ContextEM->IntT2;
  305. TrapFrame->IntT3 = ContextEM->IntT3;
  306. TrapFrame->IntT4 = ContextEM->IntT4;
  307. TrapFrame->IntV0 = ContextEM->IntV0;
  308. TrapFrame->IntTeb = ContextEM->IntTeb;
  309. TrapFrame->Preds = ContextEM->Preds;
  310. //
  311. // t5 - t2
  312. //
  313. RtlCopyMemory(&TrapFrame->IntT5, &ContextEM->IntT5, 18*sizeof(ULONGLONG));
  314. //
  315. // Set the integer nats fields
  316. //
  317. R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
  318. EXTRACT_NATS(TrapFrame->IntNats, ContextEM->IntNats,
  319. 1, R1Offset, 0xFFFFFF0E);
  320. //
  321. // Set the preserved integer NAT fields
  322. //
  323. *ContextPointers->IntS0 = ContextEM->IntS0;
  324. *ContextPointers->IntS1 = ContextEM->IntS1;
  325. *ContextPointers->IntS2 = ContextEM->IntS2;
  326. *ContextPointers->IntS3 = ContextEM->IntS3;
  327. *ContextPointers->IntS0Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
  328. *ContextPointers->IntS1Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
  329. *ContextPointers->IntS2Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
  330. *ContextPointers->IntS3Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
  331. *ContextPointers->IntS0Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
  332. *ContextPointers->IntS1Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
  333. *ContextPointers->IntS2Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
  334. *ContextPointers->IntS3Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
  335. #ifdef DEBUG
  336. DbgPrint("PspSetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, Context->IntNats = 0x%I64x\n",
  337. R1Offset, TrapFrame->IntNats, ContextEM->IntNats);
  338. #endif
  339. *ContextPointers->BrS0 = ContextEM->BrS0;
  340. *ContextPointers->BrS1 = ContextEM->BrS1;
  341. *ContextPointers->BrS2 = ContextEM->BrS2;
  342. *ContextPointers->BrS3 = ContextEM->BrS3;
  343. *ContextPointers->BrS4 = ContextEM->BrS4;
  344. TrapFrame->BrT0 = ContextEM->BrT0;
  345. TrapFrame->BrT1 = ContextEM->BrT1;
  346. }
  347. if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
  348. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  349. //
  350. // Set floating registers fs0 - fs19.
  351. //
  352. *ContextPointers->FltS0 = ContextEM->FltS0;
  353. *ContextPointers->FltS1 = ContextEM->FltS1;
  354. *ContextPointers->FltS2 = ContextEM->FltS2;
  355. *ContextPointers->FltS3 = ContextEM->FltS3;
  356. *ContextPointers->FltS4 = ContextEM->FltS4;
  357. *ContextPointers->FltS5 = ContextEM->FltS5;
  358. *ContextPointers->FltS6 = ContextEM->FltS6;
  359. *ContextPointers->FltS7 = ContextEM->FltS7;
  360. *ContextPointers->FltS8 = ContextEM->FltS8;
  361. *ContextPointers->FltS9 = ContextEM->FltS9;
  362. *ContextPointers->FltS10 = ContextEM->FltS10;
  363. *ContextPointers->FltS11 = ContextEM->FltS11;
  364. *ContextPointers->FltS12 = ContextEM->FltS12;
  365. *ContextPointers->FltS13 = ContextEM->FltS13;
  366. *ContextPointers->FltS14 = ContextEM->FltS14;
  367. *ContextPointers->FltS15 = ContextEM->FltS15;
  368. *ContextPointers->FltS16 = ContextEM->FltS16;
  369. *ContextPointers->FltS17 = ContextEM->FltS17;
  370. *ContextPointers->FltS18 = ContextEM->FltS18;
  371. *ContextPointers->FltS19 = ContextEM->FltS19;
  372. //
  373. // Set floating registers ft0 - ft9.
  374. //
  375. RtlCopyIa64FloatRegisterContext(&TrapFrame->FltT0,
  376. &ContextEM->FltT0,
  377. sizeof(FLOAT128) * (10));
  378. }
  379. if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
  380. TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
  381. if (ProcessorMode == UserMode) {
  382. //
  383. // Update the higher floating point save area (f32-f127) and
  384. // set the corresponding modified bit in the PSR to 1.
  385. //
  386. RtlCopyIa64FloatRegisterContext(
  387. (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase),
  388. &ContextEM->FltF32,
  389. 96*sizeof(FLOAT128));
  390. //
  391. // set the dfh bit to force a reload of the high fp register
  392. // set on the next user access, and clear mfh to make sure
  393. // the changes are not over written.
  394. //
  395. TrapFrame->StIPSR |= (1i64 << PSR_DFH);
  396. TrapFrame->StIPSR &= ~(1i64 << PSR_MFH);
  397. }
  398. }
  399. //
  400. // Set debug register contents if specified.
  401. //
  402. if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
  403. KiSetDebugContext (TrapFrame, ContextEM, ProcessorMode);
  404. }
  405. return;
  406. }
  407. VOID
  408. PspGetSetContextSpecialApcMain (
  409. IN PKAPC Apc,
  410. IN PKNORMAL_ROUTINE *NormalRoutine,
  411. IN PVOID *NormalContext,
  412. IN PVOID *SystemArgument1,
  413. IN PVOID *SystemArgument2
  414. )
  415. /*++
  416. Routine Description:
  417. This function either captures the user mode state of the current
  418. thread, or sets the user mode state of the current thread. The
  419. operation type is determined by the value of SystemArgument1. A
  420. zero value is used for get context, and a nonzero value is used
  421. for set context.
  422. Arguments:
  423. Apc - Supplies a pointer to the APC control object that caused entry
  424. into this routine.
  425. NormalRoutine - Supplies a pointer to the normal routine function that
  426. was specified when the APC was initialized. This parameter is not
  427. used.
  428. NormalContext - Supplies a pointer to an arbitrary data structure that
  429. was specified when the APC was initialized. This parameter is not
  430. used.
  431. SystemArgument1, SystemArgument2 - Supplies a set of two pointers to two
  432. arguments that contain untyped data.
  433. The first arguement is used to distinguish between get and set requests.
  434. A value of zero signifies that GetThreadContext was requested.
  435. A non-zero value signifies that SetThreadContext was requested.
  436. The Second arguement has the thread handle. The second arguement is
  437. not used.
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. PGETSETCONTEXT ContextInfo;
  443. KNONVOLATILE_CONTEXT_POINTERS ContextPointers; // Not currently used, needed later.
  444. CONTEXT ContextRecord;
  445. ULONGLONG ControlPc;
  446. FRAME_POINTERS EstablisherFrame;
  447. PRUNTIME_FUNCTION FunctionEntry;
  448. BOOLEAN InFunction;
  449. PKTRAP_FRAME TrFrame1;
  450. ULONGLONG ImageBase;
  451. ULONGLONG TargetGp;
  452. PETHREAD Thread;
  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. Thread = Apc->SystemArgument2;
  462. TrFrame1 = NULL;
  463. if (ContextInfo->Mode == KernelMode) {
  464. TrFrame1 = Thread->Tcb.TrapFrame;
  465. }
  466. if (TrFrame1 == NULL) {
  467. TrFrame1 = PspGetBaseTrapFrame (Thread);
  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. ControlPc = ContextRecord.BrRp;
  536. ContextRecord.StIFS = ContextRecord.RsPFS;
  537. ContextRecord.RsBSP = RtlpRseShrinkBySOL (ContextRecord.RsBSP, ContextRecord.StIFS);
  538. }
  539. } while ((PVOID)ContextRecord.IntSp != TrFrame1);
  540. //
  541. // Process GetThreadContext or SetThreadContext as specified.
  542. //
  543. if (*SystemArgument1 != 0) {
  544. //
  545. // Set Context from proper Context mode
  546. //
  547. PspSetContext(TrFrame1, &ContextPointers, &ContextInfo->Context,
  548. ContextInfo->Mode);
  549. } else {
  550. //
  551. // Get Context from proper Context mode
  552. //
  553. KeFlushUserRseState(TrFrame1);
  554. PspGetContext(TrFrame1, &ContextPointers, &ContextInfo->Context);
  555. }
  556. KeSetEvent(&ContextInfo->OperationComplete, 0, FALSE);
  557. return;
  558. }