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.

407 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. context.c
  5. Abstract:
  6. Context conversion routines for ia64 hardware to ia32 context records
  7. Author:
  8. 03-Feb-2000 Charles Spriakis - Intel (v-cspira)
  9. Revision History:
  10. --*/
  11. #define _WOW64CPUAPI_
  12. #ifdef _X86_
  13. #include "ia6432.h"
  14. #else
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include "wow64.h"
  19. #include "wow64cpu.h"
  20. #include "amd64cpu.h"
  21. #endif
  22. //
  23. // This is to prevent this library from linking to wow64 to use wow64!Wow64LogPrint
  24. //
  25. #if defined(LOGPRINT)
  26. #undef LOGPRINT
  27. #endif
  28. #define LOGPRINT(_x_) CpupDebugPrint _x_
  29. VOID
  30. CpupDebugPrint(
  31. IN ULONG_PTR Flags,
  32. IN PCHAR Format,
  33. ...);
  34. ASSERTNAME;
  35. VOID
  36. Wow64CtxFromIa64(
  37. IN ULONG Ia32ContextFlags,
  38. IN PCONTEXT ContextIa64,
  39. IN OUT PCONTEXT32 ContextX86
  40. )
  41. /*++
  42. Routine Description:
  43. This function copies the context from an ia64 context record into
  44. the context of an ia32 record (based on the hardware iVE register
  45. mappings). This function is ment to be easily usabale by various
  46. get/set context routines (such as those exported by wow64cpu.dll).
  47. Arguments:
  48. Ia32ContextFlags - Specifies which ia32 context to copy
  49. ContextIa64 - Supplies an the ia64 context buffer that is the source
  50. for the copy into the ia32 context area
  51. ContextX86 - This is an X86 context which will receive the context
  52. information from the ia64 context record passed in above
  53. Return Value:
  54. None.
  55. --*/
  56. {
  57. #if 0
  58. FLOAT128 tmpFloat[NUMBER_OF_387REGS];
  59. if (Ia32ContextFlags & CONTEXT_IA64) {
  60. LOGPRINT((ERRORLOG, "Wow64CtxFromIa64: Request with ia64 context flags (0x%x) FAILED\n", Ia32ContextFlags));
  61. ASSERT((Ia32ContextFlags & CONTEXT_IA64) == 0);
  62. }
  63. if ((Ia32ContextFlags & CONTEXT32_CONTROL) == CONTEXT32_CONTROL) {
  64. //
  65. // And the control stuff
  66. //
  67. ContextX86->Ebp = (ULONG)ContextIa64->IntTeb;
  68. ContextX86->SegCs = KGDT_R3_CODE|3;
  69. ContextX86->Eip = (ULONG)ContextIa64->StIIP;
  70. ContextX86->SegSs = KGDT_R3_DATA|3;
  71. ContextX86->Esp = (ULONG)ContextIa64->IntSp;
  72. ContextX86->EFlags = (ULONG)ContextIa64->Eflag;
  73. }
  74. if ((Ia32ContextFlags & CONTEXT32_INTEGER) == CONTEXT32_INTEGER) {
  75. //
  76. // Now for the integer state...
  77. //
  78. ContextX86->Edi = (ULONG)ContextIa64->IntT6;
  79. ContextX86->Esi = (ULONG)ContextIa64->IntT5;
  80. ContextX86->Ebx = (ULONG)ContextIa64->IntT4;
  81. ContextX86->Edx = (ULONG)ContextIa64->IntT3;
  82. ContextX86->Ecx = (ULONG)ContextIa64->IntT2;
  83. ContextX86->Eax = (ULONG)ContextIa64->IntV0;
  84. }
  85. if ((Ia32ContextFlags & CONTEXT32_SEGMENTS) == CONTEXT32_SEGMENTS) {
  86. //
  87. // These are constants (and constants are used on ia32->ia64
  88. // transition, not saved values) so make our life easy...
  89. //
  90. ContextX86->SegGs = KGDT_R3_DATA|3;
  91. ContextX86->SegEs = KGDT_R3_DATA|3;
  92. ContextX86->SegDs = KGDT_R3_DATA|3;
  93. ContextX86->SegSs = KGDT_R3_DATA|3;
  94. ContextX86->SegFs = KGDT_R3_TEB|3;
  95. ContextX86->SegCs = KGDT_R3_CODE|3;
  96. }
  97. if ((Ia32ContextFlags & CONTEXT32_EXTENDED_REGISTERS) == CONTEXT32_EXTENDED_REGISTERS) {
  98. PFXSAVE_FORMAT_WX86 xmmi = (PFXSAVE_FORMAT_WX86) ContextX86->ExtendedRegisters;
  99. LOGPRINT((TRACELOG, "Wow64CtxFromIa64: Request to convert extended fp registers\n"));
  100. xmmi->ControlWord = (USHORT)(ContextIa64->StFCR & 0xffff);
  101. xmmi->StatusWord = (USHORT)(ContextIa64->StFSR & 0xffff);
  102. xmmi->TagWord = (USHORT)(ContextIa64->StFSR >> 16) & 0xffff;
  103. xmmi->ErrorOpcode = (USHORT)(ContextIa64->StFIR >> 48);
  104. xmmi->ErrorOffset = (ULONG) (ContextIa64->StFIR & 0xffffffff);
  105. xmmi->ErrorSelector = (ULONG) (ContextIa64->StFIR >> 32);
  106. xmmi->DataOffset = (ULONG) (ContextIa64->StFDR & 0xffffffff);
  107. xmmi->DataSelector = (ULONG) (ContextIa64->StFDR >> 32);
  108. xmmi->MXCsr = (ULONG) (ContextIa64->StFCR >> 32) & 0xffff;
  109. //
  110. // Copy over the FP registers. Even though this is the new
  111. // FXSAVE format with 16-bytes for each register, need to
  112. // convert from spill/fill format to 80-byte double extended format
  113. //
  114. Wow64CopyIa64FromSpill((PFLOAT128) &(ContextIa64->FltT2),
  115. (PFLOAT128) xmmi->RegisterArea,
  116. NUMBER_OF_387REGS);
  117. //
  118. // Rotate the registers appropriately
  119. //
  120. Wow64RotateFpTop(ContextIa64->StFSR, (PFLOAT128) xmmi->RegisterArea);
  121. //
  122. // Finally copy the xmmi registers
  123. //
  124. Wow64CopyXMMIFromIa64Byte16(&(ContextIa64->FltS4),
  125. xmmi->Reserved3,
  126. NUMBER_OF_XMMI_REGS);
  127. }
  128. if ((Ia32ContextFlags & CONTEXT32_FLOATING_POINT) == CONTEXT32_FLOATING_POINT) {
  129. LOGPRINT((TRACELOG, "Wow64CtxFromIa64: Request to convert fp registers\n"));
  130. //
  131. // Copy over the floating point status/control stuff
  132. //
  133. ContextX86->FloatSave.ControlWord = (ULONG)(ContextIa64->StFCR & 0xffff);
  134. ContextX86->FloatSave.StatusWord = (ULONG)(ContextIa64->StFSR & 0xffff);
  135. ContextX86->FloatSave.TagWord = (ULONG)(ContextIa64->StFSR >> 16) & 0xffff;
  136. ContextX86->FloatSave.ErrorOffset = (ULONG)(ContextIa64->StFIR & 0xffffffff);
  137. ContextX86->FloatSave.ErrorSelector = (ULONG)(ContextIa64->StFIR >> 32);
  138. ContextX86->FloatSave.DataOffset = (ULONG)(ContextIa64->StFDR & 0xffffffff);
  139. ContextX86->FloatSave.DataSelector = (ULONG)(ContextIa64->StFDR >> 32);
  140. //
  141. // Copy over the FP registers into temporary space
  142. // Even though this is the new
  143. // FXSAVE format with 16-bytes for each register, need to
  144. // convert from spill/fill format to 80-byte double extended format
  145. //
  146. Wow64CopyIa64FromSpill((PFLOAT128) &(ContextIa64->FltT2),
  147. (PFLOAT128) tmpFloat,
  148. NUMBER_OF_387REGS);
  149. //
  150. // Rotate the registers appropriately
  151. //
  152. Wow64RotateFpTop(ContextIa64->StFSR, tmpFloat);
  153. //
  154. // And put them in the older FNSAVE format (packed 10 byte values)
  155. //
  156. Wow64CopyFpFromIa64Byte16(tmpFloat,
  157. ContextX86->FloatSave.RegisterArea,
  158. NUMBER_OF_387REGS);
  159. }
  160. if ((Ia32ContextFlags & CONTEXT32_DEBUG_REGISTERS) == CONTEXT32_DEBUG_REGISTERS) {
  161. LOGPRINT((TRACELOG, "Wow64CtxFromIa64: Request to convert debug registers\n"));
  162. }
  163. ContextX86->ContextFlags = Ia32ContextFlags;
  164. #endif
  165. }
  166. VOID
  167. Wow64CtxToIa64(
  168. IN ULONG Ia32ContextFlags,
  169. IN PCONTEXT32 ContextX86,
  170. IN OUT PCONTEXT ContextIa64
  171. )
  172. /*++
  173. Routine Description:
  174. This function copies the context from an ia32 context record into
  175. the context of an ia64 record (based on the hardware iVE register
  176. mappings). This function is ment to be easily usabale by various
  177. get/set context routines (such as those exported by wow64cpu.dll).
  178. Arguments:
  179. Ia32ContextFlags - Specifies which ia32 context to copy
  180. ContextX86 - Supplies an the X86 context buffer that is the source
  181. for the copy into the ia64 context area
  182. ContextIa64 - This is an ia64 context which will receive the context
  183. information from the x86 context record passed in above
  184. Return Value:
  185. None.
  186. --*/
  187. {
  188. #if 0
  189. FLOAT128 tmpFloat[NUMBER_OF_387REGS];
  190. if (Ia32ContextFlags & CONTEXT_IA64) {
  191. LOGPRINT((ERRORLOG, "Wow64CtxToIa64: Request with ia64 context flags (0x%x) FAILED\n", Ia32ContextFlags));
  192. ASSERT((Ia32ContextFlags & CONTEXT_IA64) == 0);
  193. }
  194. if ((Ia32ContextFlags & CONTEXT32_CONTROL) == CONTEXT32_CONTROL) {
  195. //
  196. // And the control stuff
  197. //
  198. ContextIa64->IntTeb = ContextX86->Ebp;
  199. ContextIa64->StIIP = ContextX86->Eip;
  200. ContextIa64->IntSp = ContextX86->Esp;
  201. ContextIa64->Eflag = ContextX86->EFlags;
  202. //
  203. // The segments (cs and ds) are a constant, so reset them.
  204. // gr17 has LDT and TSS, so might as well reset
  205. // all of them while we're at it...
  206. // These values are forced in during a transition (see simulate.s)
  207. // so there is no point to trying to get cute and actually
  208. // pass in the values from the X86 context record
  209. //
  210. ContextIa64->IntT8 = ((KGDT_LDT|3) << 32)
  211. | ((KGDT_R3_DATA|3) << 16)
  212. | (KGDT_R3_CODE|3);
  213. }
  214. if ((Ia32ContextFlags & CONTEXT32_INTEGER) == CONTEXT32_INTEGER) {
  215. //
  216. // Now for the integer state...
  217. //
  218. ContextIa64->IntT6 = ContextX86->Edi;
  219. ContextIa64->IntT5 = ContextX86->Esi;
  220. ContextIa64->IntT4 = ContextX86->Ebx;
  221. ContextIa64->IntT3 = ContextX86->Edx;
  222. ContextIa64->IntT2 = ContextX86->Ecx;
  223. ContextIa64->IntV0 = ContextX86->Eax;
  224. }
  225. if ((Ia32ContextFlags & CONTEXT32_SEGMENTS) == CONTEXT32_SEGMENTS) {
  226. //
  227. // These are constants (and constants are used on ia32->ia64
  228. // transition, not saved values) so make our life easy...
  229. // These values are forced in during a transition (see simulate.s)
  230. // so there is no point to trying to get cute and actually
  231. // pass in the values from the X86 context record
  232. //
  233. ContextIa64->IntT7 = ((KGDT_R3_DATA|3) << 48)
  234. | ((KGDT_R3_TEB|3) << 32)
  235. | ((KGDT_R3_DATA|3) << 16)
  236. | (KGDT_R3_DATA|3);
  237. }
  238. if ((Ia32ContextFlags & CONTEXT32_EXTENDED_REGISTERS) == CONTEXT32_EXTENDED_REGISTERS) {
  239. PFXSAVE_FORMAT_WX86 xmmi = (PFXSAVE_FORMAT_WX86) ContextX86->ExtendedRegisters;
  240. LOGPRINT((TRACELOG, "Wow64CtxToIa64: Request to convert extended fp registers\n"));
  241. //
  242. // And copy over the floating point status/control stuff
  243. //
  244. ContextIa64->StFCR = (ContextIa64->StFCR & 0xffffffffffffe040i64) |
  245. (xmmi->ControlWord & 0xffff) |
  246. ((xmmi->MXCsr & 0xffff) << 32);
  247. ContextIa64->StFSR = (ContextIa64->StFSR & 0xffffffff00000000i64) |
  248. (xmmi->StatusWord & 0xffff) |
  249. ((xmmi->TagWord & 0xffff) << 16);
  250. ContextIa64->StFIR = (xmmi->ErrorOffset & 0xffffffff) |
  251. (xmmi->ErrorSelector << 32);
  252. ContextIa64->StFDR = (xmmi->DataOffset & 0xffffffff) |
  253. (xmmi->DataSelector << 32);
  254. //
  255. // Rotate registers back
  256. //
  257. {
  258. ULONGLONG RotateFSR = (NUMBER_OF_387REGS -
  259. ((ContextIa64->StFSR >> 11) & 0x7)) << 11;
  260. Wow64RotateFpTop(RotateFSR, (PFLOAT128) xmmi->RegisterArea);
  261. }
  262. // Copy over the FP registers. Even though this is the new
  263. // FXSAVE format with 16-bytes for each register, need to
  264. // convert to spill/fill format from 80-byte double extended format
  265. //
  266. Wow64CopyIa64ToFill((PFLOAT128) xmmi->RegisterArea,
  267. (PFLOAT128) &(ContextIa64->FltT2),
  268. NUMBER_OF_387REGS);
  269. //
  270. // Copy over the xmmi registers and convert them into a format
  271. // that spill/fill can use
  272. //
  273. Wow64CopyXMMIToIa64Byte16(xmmi->Reserved3,
  274. &(ContextIa64->FltS4),
  275. NUMBER_OF_XMMI_REGS);
  276. }
  277. if ((Ia32ContextFlags & CONTEXT32_FLOATING_POINT) == CONTEXT32_FLOATING_POINT) {
  278. LOGPRINT((TRACELOG, "Wow64CtxToIa64: Request to convert fp registers\n"));
  279. //
  280. // Copy over the floating point status/control stuff
  281. // Leave the MXCSR stuff alone
  282. //
  283. ContextIa64->StFCR = (ContextIa64->StFCR & 0xffffffffffffe040i64) |
  284. (ContextX86->FloatSave.ControlWord & 0xffff);
  285. ContextIa64->StFSR = (ContextIa64->StFSR & 0xffffffff00000000i64) |
  286. (ContextX86->FloatSave.StatusWord & 0xffff) |
  287. ((ContextX86->FloatSave.TagWord & 0xffff) << 16);
  288. ContextIa64->StFIR = (ContextX86->FloatSave.ErrorOffset & 0xffffffff) |
  289. (ContextX86->FloatSave.ErrorSelector << 32);
  290. ContextIa64->StFDR = (ContextX86->FloatSave.DataOffset & 0xffffffff) |
  291. (ContextX86->FloatSave.DataSelector << 32);
  292. //
  293. // Copy over the FP registers from packed 10-byte format
  294. // to 16-byte format
  295. //
  296. Wow64CopyFpToIa64Byte16(ContextX86->FloatSave.RegisterArea,
  297. tmpFloat,
  298. NUMBER_OF_387REGS);
  299. //
  300. // Rotate registers back
  301. //
  302. {
  303. ULONGLONG RotateFSR = (NUMBER_OF_387REGS -
  304. ((ContextIa64->StFSR >> 11) & 0x7)) << 11;
  305. Wow64RotateFpTop(RotateFSR, tmpFloat);
  306. }
  307. //
  308. // Now convert from 80 byte extended format to fill/spill format
  309. //
  310. Wow64CopyIa64ToFill((PFLOAT128) tmpFloat,
  311. (PFLOAT128) &(ContextIa64->FltT2),
  312. NUMBER_OF_387REGS);
  313. }
  314. if ((Ia32ContextFlags & CONTEXT32_DEBUG_REGISTERS) == CONTEXT32_DEBUG_REGISTERS) {
  315. LOGPRINT((TRACELOG, "Wow64CtxToIa64: Request to convert debug registers\n"));
  316. }
  317. #endif
  318. }