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.
380 lines
11 KiB
380 lines
11 KiB
/*++
|
|
|
|
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 <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntos.h>
|
|
#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;
|
|
}
|
|
}
|