/*++ Copyright (c) 2000 Microsoft Corporation Module Name: context.c Abstract: This module converts an amd64 context record to an X86 context record and vice versa. Author: 13-Dec-2001 Samer Arafeh (samera) Revision History: --*/ #define _WOW64CPUAPI_ #ifdef _X86_ #include "amd6432.h" #else #include #include #include #include #include "wow64.h" #include "wow64cpu.h" #include "amd64cpu.h" #endif #include "cpup.h" // // Legacy FP definitions // #define NUMBER_LEGACY_FP_REGISTERS 8 #define FP_LEGACY_REGISTER_SIZE 10 ASSERTNAME; VOID Wow64CtxFromAmd64( IN ULONG X86ContextFlags, IN PCONTEXT ContextAmd64, IN OUT PCONTEXT32 ContextX86 ) /*++ Routine Description: This function builds an x86 context from the native amd64 context. Arguments: X86ContextFlags - Specifies which ia32 context to copy ContextAmd64 - Supplies an the amd64 context buffer that is the source for the copy into the ia32 context area ContextX86 - This is an X86 context which will receive the context information from the amd64 context record passed in above Return Value: None. --*/ { ULONG FpReg; // // Validate context flags // if (X86ContextFlags & CONTEXT_AMD64) { LOGPRINT((ERRORLOG, "Wow64CtxFromAmd64: Request with amd64 context flags (0x%x) FAILED\n", X86ContextFlags)); ASSERT((X86ContextFlags & CONTEXT_AMD64) == 0); } if ((X86ContextFlags & CONTEXT32_CONTROL) == CONTEXT32_CONTROL) { // // Control registers // ContextX86->Ebp = (ULONG) ContextAmd64->Rbp; ContextX86->SegCs = (KGDT64_R3_CMCODE | RPL_MASK); ContextX86->Eip = (ULONG) ContextAmd64->Rip; ContextX86->SegSs = (KGDT64_R3_DATA | RPL_MASK); ContextX86->Esp = (ULONG) ContextAmd64->Rsp; ContextX86->EFlags = ContextAmd64->EFlags; } if ((X86ContextFlags & CONTEXT32_INTEGER) == CONTEXT32_INTEGER) { // // Integer state // ContextX86->Edi = (ULONG)ContextAmd64->Rdi; ContextX86->Esi = (ULONG)ContextAmd64->Rsi; ContextX86->Ebx = (ULONG)ContextAmd64->Rbx; ContextX86->Edx = (ULONG)ContextAmd64->Rdx; ContextX86->Ecx = (ULONG)ContextAmd64->Rcx; ContextX86->Eax = (ULONG)ContextAmd64->Rax; } if ((X86ContextFlags & CONTEXT32_SEGMENTS) == CONTEXT32_SEGMENTS) { // // Segment registers... // ContextX86->SegGs = (KGDT64_R3_DATA | RPL_MASK); ContextX86->SegEs = (KGDT64_R3_DATA | RPL_MASK); ContextX86->SegDs = (KGDT64_R3_DATA | RPL_MASK); ContextX86->SegFs = (KGDT64_R3_CMTEB | RPL_MASK); } if ((X86ContextFlags & CONTEXT32_EXTENDED_REGISTERS) == CONTEXT32_EXTENDED_REGISTERS) { PFXSAVE_FORMAT_WX86 FxSaveArea = (PFXSAVE_FORMAT_WX86) ContextX86->ExtendedRegisters; LOGPRINT((TRACELOG, "Wow64CtxFromAmd64: Request to convert extended fp registers\n")); // // Initialize the FxSave part of the context. // RtlZeroMemory (FxSaveArea, sizeof (ContextX86->ExtendedRegisters)); // // Copy over control/status registers // FxSaveArea->ControlWord = ContextAmd64->FltSave.ControlWord; FxSaveArea->StatusWord = ContextAmd64->FltSave.StatusWord; FxSaveArea->TagWord = ContextAmd64->FltSave.TagWord; FxSaveArea->ErrorOpcode = ContextAmd64->FltSave.ErrorOpcode; FxSaveArea->ErrorOffset = ContextAmd64->FltSave.ErrorOffset; FxSaveArea->ErrorSelector = ContextAmd64->FltSave.ErrorSelector; FxSaveArea->DataOffset = ContextAmd64->FltSave.DataOffset; FxSaveArea->DataSelector = ContextAmd64->FltSave.DataSelector; FxSaveArea->MXCsr = ContextAmd64->MxCsr; // // Copy over the legacy FP registers (ST0-ST7) // RtlCopyMemory (FxSaveArea->RegisterArea, ContextAmd64->FltSave.FloatRegisters, sizeof (FxSaveArea->RegisterArea)); // // Copy over XMM0 - XMM7 // RtlCopyMemory (FxSaveArea->Reserved3, &ContextAmd64->Xmm0, sizeof (FxSaveArea->Reserved3)); } if ((X86ContextFlags & CONTEXT32_FLOATING_POINT) == CONTEXT32_FLOATING_POINT) { LOGPRINT((TRACELOG, "Wow64CtxFromAmd64: Request to convert fp registers\n")); // // Floating point (legacy) ST0 - ST7 // RtlCopyMemory (&ContextX86->FloatSave, &ContextAmd64->FltSave, sizeof (ContextX86->FloatSave)); } if ((X86ContextFlags & CONTEXT32_DEBUG_REGISTERS) == CONTEXT32_DEBUG_REGISTERS) { LOGPRINT((TRACELOG, "Wow64CtxFromAmd64: Request to convert debug registers\n")); // // Debug registers DR0 - DR7 // if ((ContextAmd64->Dr7 & DR7_ACTIVE) != 0) { ContextX86->Dr0 = (ULONG)ContextAmd64->Dr0; ContextX86->Dr1 = (ULONG)ContextAmd64->Dr1; ContextX86->Dr2 = (ULONG)ContextAmd64->Dr2; ContextX86->Dr3 = (ULONG)ContextAmd64->Dr3; ContextX86->Dr6 = (ULONG)ContextAmd64->Dr6; ContextX86->Dr7 = (ULONG)ContextAmd64->Dr7; } else { ContextX86->Dr0 = 0; ContextX86->Dr1 = 0; ContextX86->Dr2 = 0; ContextX86->Dr3 = 0; ContextX86->Dr6 = 0; ContextX86->Dr7 = 0; } } ContextX86->ContextFlags = X86ContextFlags; } VOID Wow64CtxToAmd64( IN ULONG X86ContextFlags, IN PCONTEXT32 ContextX86, IN OUT PCONTEXT ContextAmd64 ) /*++ Routine Description: This function builds a native Amd64 context from an x86 context record. Arguments: X86ContextFlags - Specifies which c86 context to copy ContextX86 - Supplies an the X86 context buffer that is the source for the copy into the amd64 context area ContextAmd64 - This is an amd64 context which will receive the context information from the x86 context record passed in above Return Value: None. --*/ { BOOLEAN CmMode = (ContextAmd64->SegCs == (KGDT64_R3_CMCODE | RPL_MASK)); // // Validate context flags // if (X86ContextFlags & CONTEXT_AMD64) { LOGPRINT((ERRORLOG, "Wow64CtxToAmd64: Request with amd64 context flags (0x%x) FAILED\n", X86ContextFlags)); ASSERT((X86ContextFlags & CONTEXT_AMD64) == 0); } // // if we are running in longmode, then only set the registers that won't be changed // by 64-bit code. // if (CmMode != TRUE) { X86ContextFlags = (X86ContextFlags & ~(CONTEXT32_CONTROL | CONTEXT32_INTEGER | CONTEXT32_SEGMENTS)); X86ContextFlags = (X86ContextFlags | CONTEXT_i386); } if ((X86ContextFlags & CONTEXT32_CONTROL) == CONTEXT32_CONTROL) { LOGPRINT((TRACELOG, "Wow64CtxToAmd64: Request to convert control registers\n")); // // Control registers // ContextAmd64->SegCs = (KGDT64_R3_CMCODE | RPL_MASK); ContextAmd64->SegSs = (KGDT64_R3_DATA | RPL_MASK); ContextAmd64->Rip = ContextX86->Eip; ContextAmd64->Rbp = ContextX86->Ebp; ContextAmd64->Rsp = ContextX86->Esp; ContextAmd64->EFlags = ContextX86->EFlags; } if ((X86ContextFlags & CONTEXT32_INTEGER) == CONTEXT32_INTEGER) { LOGPRINT((TRACELOG, "Wow64CtxToAmd64: Request to convert integer registers\n")); // // Integer registers... // ContextAmd64->Rdi = ContextX86->Edi; ContextAmd64->Rsi = ContextX86->Esi; ContextAmd64->Rbx = ContextX86->Ebx; ContextAmd64->Rdx = ContextX86->Edx; ContextAmd64->Rcx = ContextX86->Ecx; ContextAmd64->Rax = ContextX86->Eax; } if ((X86ContextFlags & CONTEXT32_SEGMENTS) == CONTEXT32_SEGMENTS) { LOGPRINT((TRACELOG, "Wow64CtxToAmd64: Request to convert segment registers\n")); // // Segment registers : are never touched, and are used from the native // context. // } if ((X86ContextFlags & CONTEXT32_EXTENDED_REGISTERS) == CONTEXT32_EXTENDED_REGISTERS) { PFXSAVE_FORMAT_WX86 FxSaveArea = (PFXSAVE_FORMAT_WX86) ContextX86->ExtendedRegisters; LOGPRINT((TRACELOG, "Wow64CtxToAmd64: Request to convert extended fp registers\n")); // // Control and status registers // ContextAmd64->FltSave.ControlWord = FxSaveArea->ControlWord; ContextAmd64->FltSave.StatusWord = FxSaveArea->StatusWord; ContextAmd64->FltSave.TagWord = FxSaveArea->TagWord; ContextAmd64->FltSave.ErrorOpcode = FxSaveArea->ErrorOpcode; ContextAmd64->FltSave.ErrorOffset = FxSaveArea->ErrorOffset; ContextAmd64->FltSave.ErrorSelector = (USHORT)FxSaveArea->ErrorSelector; ContextAmd64->FltSave.DataOffset = FxSaveArea->DataOffset; ContextAmd64->FltSave.DataSelector = (USHORT)FxSaveArea->DataSelector; ContextAmd64->MxCsr = FxSaveArea->MXCsr; // // Legacy FP registers (ST0-ST7) // RtlCopyMemory (ContextAmd64->FltSave.FloatRegisters, FxSaveArea->RegisterArea, sizeof (ContextAmd64->FltSave.FloatRegisters)); // // Extended floating point registers (XMM0-XMM7) // RtlCopyMemory (&ContextAmd64->Xmm0, FxSaveArea->Reserved3, sizeof (FxSaveArea->Reserved3)); } if ((X86ContextFlags & CONTEXT32_FLOATING_POINT) == CONTEXT32_FLOATING_POINT) { LOGPRINT((TRACELOG, "Wow64CtxToAmd64: Request to convert fp registers\n")); // // Floating point (legacy) registers (ST0-ST7) // RtlCopyMemory (&ContextAmd64->FltSave, &ContextX86->FloatSave, sizeof (ContextAmd64->FltSave)); } if ((X86ContextFlags & CONTEXT32_DEBUG_REGISTERS) == CONTEXT32_DEBUG_REGISTERS) { // // Debug registers (Dr0-Dr7) // ContextAmd64->Dr0 = ContextX86->Dr0; ContextAmd64->Dr1 = ContextX86->Dr1; ContextAmd64->Dr2 = ContextX86->Dr2; ContextAmd64->Dr3 = ContextX86->Dr3; ContextAmd64->Dr6 = ContextX86->Dr6; ContextAmd64->Dr7 = ContextX86->Dr7; } }