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.
524 lines
14 KiB
524 lines
14 KiB
/*++
|
|
|
|
Module Name:
|
|
|
|
iA32DEF.H
|
|
|
|
Abstract:
|
|
|
|
This file defines iA32 macros for iA32Trap.c and Opcode Emulation use
|
|
|
|
Author:
|
|
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define KERNELONLY 1
|
|
// #include ks386.inc
|
|
// #include callconv.inc // calling convention macros
|
|
// #include i386\kimacro.inc
|
|
// #include mac386.inc
|
|
// #include i386\mi.inc
|
|
|
|
|
|
//
|
|
// Equates for exceptions which cause system fatal error
|
|
//
|
|
|
|
#define EXCEPTION_DIVIDED_BY_ZERO 0
|
|
#define EXCEPTION_DEBUG 1
|
|
#define EXCEPTION_NMI 2
|
|
#define EXCEPTION_INT3 3
|
|
#define EXCEPTION_BOUND_CHECK 5
|
|
#define EXCEPTION_INVALID_OPCODE 6
|
|
#define EXCEPTION_NPX_NOT_AVAILABLE 7
|
|
#define EXCEPTION_DOUBLE_FAULT 8
|
|
#define EXCEPTION_NPX_OVERRUN 9
|
|
#define EXCEPTION_INVALID_TSS 0x0A
|
|
#define EXCEPTION_SEGMENT_NOT_PRESENT 0x0B
|
|
#define EXCEPTION_STACK_FAULT 0x0C
|
|
#define EXCEPTION_GP_FAULT 0x0D
|
|
#define EXCEPTION_RESERVED_TRAP 0x0F
|
|
#define EXCEPTION_NPX_ERROR 0x010
|
|
#define EXCEPTION_ALIGNMENT_CHECK 0x011
|
|
|
|
//
|
|
// Exception flags
|
|
//
|
|
|
|
#define EXCEPT_UNKNOWN_ACCESS 0
|
|
#define EXCEPT_LIMIT_ACCESS 0x10
|
|
|
|
//
|
|
// page fault read/write mask
|
|
//
|
|
|
|
#define ERR_0E_STORE 2
|
|
|
|
//
|
|
// Debug register 6 (dr6) BS (single step) bit mask
|
|
//
|
|
|
|
#define DR6_BS_MASK 0x4000
|
|
|
|
//
|
|
// EFLAGS single step bit
|
|
//
|
|
|
|
#define EFLAGS_TF_BIT 0x100
|
|
#define EFLAGS_OF_BIT 0x4000
|
|
|
|
//
|
|
// The mask of selecot's table indicator (ldt or gdt)
|
|
//
|
|
|
|
#define TABLE_INDICATOR_MASK 4
|
|
|
|
//
|
|
// Opcode for Pop SegReg and iret instructions
|
|
//
|
|
|
|
#define POP_DS 0x01F
|
|
#define POP_ES 0x07
|
|
#define POP_FS 0x0A10F
|
|
#define POP_GS 0x0A90F
|
|
#define IRET_OP 0x0CF
|
|
#define CLI_OP 0x0FA
|
|
#define STI_OP 0x0FB
|
|
#define PUSHF_OP 0x09C
|
|
#define POPF_OP 0x09D
|
|
#define INTNN_OP 0x00CD
|
|
#define FRSTOR_ECX 0x0021DD9B
|
|
#define FWAIT_OP 0x009b
|
|
|
|
|
|
#define GATE_TYPE_386INT 0x0E00
|
|
#define GATE_TYPE_386TRAP 0x0F00
|
|
#define GATE_TYPE_TASK 0x0500
|
|
#define D_GATE 0
|
|
#define D_PRESENT 0x08000
|
|
#define D_DPL_3 0x06000
|
|
#define D_DPL_0 0
|
|
|
|
//
|
|
// Definitions for present 386 trap and interrupt gate attributes
|
|
//
|
|
|
|
#define D_TRAP032 D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_386TRAP
|
|
#define D_TRAP332 D_PRESENT+D_DPL_3+D_GATE+GATE_TYPE_386TRAP
|
|
#define D_INT032 D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_386INT
|
|
#define D_INT332 D_PRESENT+D_DPL_3+D_GATE+GATE_TYPE_386INT
|
|
#define D_TASK D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_TASK
|
|
|
|
//
|
|
// Bit patterns for Intercept_Code or Trap_Code,
|
|
// patterns used in IIM on IA32 trap
|
|
//
|
|
#define TRAPCODE_TB 0x0004 // taken branch trap
|
|
#define TRAPCODE_SS 0x0008 // single step trap
|
|
#define TRAPCODE_B0 0x0010 // Data breakpoint trap
|
|
#define TRAPCODE_B1 0x0020
|
|
#define TRAPCODE_B2 0x0040
|
|
#define TRAPCODE_B3 0x0080
|
|
|
|
#define INTERCEPT_OS 0x0002 // Operand size
|
|
#define INTERCEPT_AS 0x0004 // Address size
|
|
#define INTERCEPT_LP 0x0008 // Lock Prefix
|
|
#define INTERCEPT_RP 0x0010 // REP prefix
|
|
#define INTERCEPT_NP 0x0020 // REPNE prefix
|
|
#define INTERCEPT_SP 0x0040 // Segment prefix
|
|
#define INTERCEPT_SEG 0x0380 // Segment valuse
|
|
#define INTERCEPT_0F 0x0400 // 0F opcode series
|
|
|
|
#define HARDWARE_VM 0x0800 // VM86 mode
|
|
#define HARDWARE_RM 0x1000 // Real Mode
|
|
#define HARDWARE_PM 0x2000 // Protect Mode
|
|
#define HARDWARE_SS 0x4000 // Stack size, 32 or 16 bits
|
|
#define HARDWARE_UR 0x8000 // User or privileged mode
|
|
|
|
|
|
#define MI_SMSW 0x01
|
|
#define MI_SMSW_REGOP 0x20
|
|
//
|
|
// Following MI_*** definitions are created from MI386.INC
|
|
//
|
|
#define MAX_INSTRUCTION_LENGTH 15
|
|
#define MAX_INSTRUCTION_PREFIX_LENGTH 4
|
|
#define MI_LOCK_PREFIX 0x0F0
|
|
#define MI_REPNE_PREFIX 0x0F2
|
|
#define MI_REP_PREFIX 0x0F3
|
|
#define MI_SEGCS_PREFIX 0x02E
|
|
#define MI_SEGSS_PREFIX 0x036
|
|
#define MI_SEGDS_PREFIX 0x03E
|
|
#define MI_SEGES_PREFIX 0x026
|
|
#define MI_SEGFS_PREFIX 0x064
|
|
#define MI_SEGGS_PREFIX 0x065
|
|
#define MI_OPERANDSIZE_PREFIX 0x066
|
|
#define MI_ADDRESSOVERRIDE_PREFIX 0x067
|
|
#define MI_TWO_BYTE 0x0F
|
|
#define MI_HLT 0x0F4
|
|
#define MI_LTR_LLDT 0
|
|
#define MI_LGDT_LIDT_LMSW 0x01
|
|
#define MI_MODRM_MASK 0x38
|
|
#define MI_LLDT_MASK 0x10
|
|
#define MI_LTR_MASK 0x18
|
|
#define MI_LGDT_MASK 0x10
|
|
#define MI_LIDT_MASK 0x18
|
|
#define MI_LMSW_MASK 0x30
|
|
#define MI_SPECIAL_MOV_MASK 0x20
|
|
#define MI_REP_INS_OUTS 0x0F3
|
|
#define MI_MIN_INS_OUTS 0x06C
|
|
#define MI_MAX_INS_OUTS 0x06F
|
|
#define MI_LMSW_OPCODE 0x001 // second byte of lmsw
|
|
#define MI_CLTS_OPCODE 0x006 // second byte of clts
|
|
#define MI_GET_CRx_OPCODE 0x020 // mov r32,CRx
|
|
#define MI_SET_CRx_OPCODE 0x022 // mov CRx,r32
|
|
#define MI_GET_TRx_OPCODE 0x024 // mov r32,TRx
|
|
#define MI_SET_TRx_OPCODE 0x026 // mov TRx,r32
|
|
#define MI_REGMASK 0x038 // REG field mask
|
|
#define MI_REGSHIFT 0x3 // REG field shift
|
|
#define MI_REGLMSW 0x030 // REG field for lmsw
|
|
#define MI_MODMASK 0x0C0 // MOD field mask
|
|
#define MI_MODSHIFT 0x6 // MOD field shift
|
|
#define MI_MODMOVSPEC 0x0C0 // MOD field for mov to/from special
|
|
#define MI_MODNONE 0
|
|
#define MI_RMMASK 0x007 // RM field mask
|
|
#define MI_RMBP 0x006 // RM value for bp reg
|
|
#define MI_RMSIB 0x004 // RM value for sib
|
|
|
|
#define MI_SIB_BASEMASK 0x007 // SIB BASE field mask
|
|
#define MI_SIB_BASENONE 0x005
|
|
#define MI_SIB_BASESHIFT 0
|
|
|
|
#define MI_SIB_INDEXMASK 0x038
|
|
#define MI_SIB_INDEXSHIFT 3
|
|
#define MI_SIB_INDEXNONE 0x020
|
|
|
|
#define MI_SIB_SSMASK 0x0c0
|
|
#define MI_SIB_SSSHIFT 0x6
|
|
|
|
|
|
//
|
|
// definition for floating status word error mask
|
|
//
|
|
|
|
#define FSW_INVALID_OPERATION 0x0001
|
|
#define FSW_DENORMAL 0x0002
|
|
#define FSW_ZERO_DIVIDE 0x0004
|
|
#define FSW_OVERFLOW 0x0008
|
|
#define FSW_UNDERFLOW 0x0010
|
|
#define FSW_PRECISION 0x0020
|
|
#define FSW_STACK_FAULT 0x0040
|
|
#define FSW_ERROR_SUMMARY 0x0080
|
|
#define FSW_CONDITION_CODE_0 0x0100
|
|
#define FSW_CONDITION_CODE_1 0x0200
|
|
#define FSW_CONDITION_CODE_2 0x0400
|
|
#define FSW_CONDITION_CODE_3 0x4000
|
|
|
|
#define FSW_ERR_MASK (FSW_INVALID_OPERATION | FSW_DENORMAL | FSW_ZERO_DIVIDE | FSW_OVERFLOW | FSW_UNDERFLOW | FSW_PRECISION | FSW_STACK_FAULT)
|
|
|
|
//
|
|
// Definitions of the shifts to get to the katmai status and control
|
|
// Once the bits are shifted, they are in the same place as the
|
|
// 387 status and control, so the masks above work as well
|
|
// See the IA64 Application Architecture (Vol 1) for where the
|
|
// bit shift values come from
|
|
//
|
|
#define KATMAI_SHIFT_CONTROL 39
|
|
#define KATMAI_SHIFT_STATUS 32
|
|
|
|
|
|
#define CPL_STATE(SegCs) (SegCs & RPL_MASK)
|
|
|
|
// Use the IIPA since that points to the start of the ia32 instruction
|
|
#define EIP(frame) ((ULONG) (frame)->StIIPA & 0xffffffff)
|
|
#define ESP(frame) ((ULONG) (frame)->IntSp & 0xffffffff)
|
|
#define ECX(frame) ((ULONG) (frame)->IntT2 & 0xffffffff)
|
|
#define EDX(frame) ((ULONG) (frame)->IntT3 & 0xffffffff)
|
|
|
|
#define ISRCode(frame) ((USHORT) ((frame)->StISR) & 0xffff)
|
|
#define ISRVector(frame) ((UCHAR) ((frame)->StISR >> 16) & 0xff)
|
|
|
|
|
|
//
|
|
// Helpers for instruction decoding
|
|
//
|
|
|
|
BOOLEAN
|
|
KiIa32Compute32BitEffectiveAddress (
|
|
IN PKTRAP_FRAME Frame,
|
|
IN OUT PUCHAR *InstAddr,
|
|
OUT PUINT_PTR Addr,
|
|
OUT PBOOLEAN RegisterMode
|
|
);
|
|
|
|
NTSTATUS
|
|
KiIa32InterceptUnalignedLock (
|
|
IN PKTRAP_FRAME TrapFrame
|
|
);
|
|
|
|
NTSTATUS
|
|
KiIa32ValidateInstruction (
|
|
IN PKTRAP_FRAME TrapFrame
|
|
);
|
|
|
|
|
|
//
|
|
// The following register indices are valid only if called through
|
|
// GetX86Reg (...)
|
|
//
|
|
|
|
#define IA32_REG_EAX 0
|
|
#define IA32_REG_ECX 1
|
|
#define IA32_REG_EDX 2
|
|
#define IA32_REG_EBX 3
|
|
#define IA32_REG_ESP 4
|
|
#define IA32_REG_EBP 5
|
|
#define IA32_REG_ESI 6
|
|
#define IA32_REG_EDI 7
|
|
|
|
#define IA32_DISP_NONE 0x00
|
|
#define IA32_DISP8 0x01
|
|
#define IA32_DISP16 0x02
|
|
|
|
//
|
|
// x86 Eflags register layout
|
|
//
|
|
|
|
typedef union _IA32_EFLAGS
|
|
{
|
|
|
|
ULONGLONG Value;
|
|
|
|
struct
|
|
{
|
|
ULONGLONG cf : 1;
|
|
ULONGLONG v1 : 1;
|
|
ULONGLONG pf : 1;
|
|
ULONGLONG v2 : 1;
|
|
ULONGLONG af : 1;
|
|
ULONGLONG v3 : 1;
|
|
ULONGLONG zf : 1;
|
|
ULONGLONG sf : 1;
|
|
ULONGLONG tf : 1;
|
|
ULONGLONG ifl : 1;
|
|
ULONGLONG df : 1;
|
|
ULONGLONG of : 1;
|
|
ULONGLONG iopl : 2;
|
|
ULONGLONG nt : 1;
|
|
ULONGLONG v4 : 1;
|
|
ULONGLONG rf : 1;
|
|
ULONGLONG vm : 1;
|
|
ULONGLONG ac : 1;
|
|
ULONGLONG vif : 1;
|
|
ULONGLONG vip : 1;
|
|
ULONGLONG id : 1;
|
|
} u;
|
|
|
|
} IA32_EFLAGS, *PIA32_EFLAGS;
|
|
|
|
|
|
//
|
|
// Eflags bits to update
|
|
//
|
|
|
|
#define IA32_EFLAGS_CF 0x0001
|
|
#define IA32_EFLAGS_SF 0x0002
|
|
#define IA32_EFLAGS_OF 0x0004
|
|
#define IA32_EFLAGS_PF 0x0008
|
|
#define IA32_EFLAGS_ZF 0x0010
|
|
#define IA32_EFLAGS_AF 0x0020
|
|
|
|
|
|
//
|
|
// Operand size
|
|
//
|
|
|
|
typedef enum _IA32_OPERAND_SIZE
|
|
{
|
|
OPERANDSIZE_NONE,
|
|
OPERANDSIZE_ONEBYTE,
|
|
OPERANDSIZE_TWOBYTES,
|
|
OPERANDSIZE_FOURBYTES
|
|
|
|
} IA32_OPERAND_SIZE;
|
|
|
|
typedef enum _IA32_OPCODE_PARAMETERS
|
|
{
|
|
IA32_PARAM_RM8_IMM8,
|
|
IA32_PARAM_RM_IMM,
|
|
IA32_PARAM_RM_IMM8SIGN,
|
|
IA32_PARAM_RM8_R,
|
|
IA32_PARAM_RM_R,
|
|
IA32_PARAM_R_RM8,
|
|
IA32_PARAM_R_RM,
|
|
IA32_PARAM_RM8,
|
|
IA32_PARAM_RM,
|
|
IA32_PARAM_SEGREG_RM8,
|
|
IA32_PARAM_SEGREG_RM
|
|
|
|
} IA32_OPCODE_PARAMETERS;
|
|
|
|
|
|
//
|
|
// Opcode decription
|
|
//
|
|
typedef struct _IA32_OPCODE_DESCRIPTION
|
|
{
|
|
|
|
//
|
|
// 1st, 2nd and 3rd byte. The 3rd byte is actually the /Reg bits
|
|
//
|
|
|
|
UCHAR Byte1;
|
|
UCHAR Byte2;
|
|
UCHAR Byte3;
|
|
union
|
|
{
|
|
UCHAR Value;
|
|
struct
|
|
{
|
|
UCHAR Bytes : 4;
|
|
UCHAR RegOpcode : 4;
|
|
} m;
|
|
} Count;
|
|
|
|
//
|
|
// Parameter of this opcode
|
|
//
|
|
|
|
UCHAR Type;
|
|
|
|
//
|
|
// Opcode
|
|
//
|
|
|
|
UCHAR Opcode;
|
|
|
|
} IA32_OPCODE_DESCRIPTION, *PIA32_OPCODE_DESCRIPTION;
|
|
|
|
//
|
|
// Specific data structure to represent the lock-prefixed instruction
|
|
// operands and immediates.
|
|
//
|
|
|
|
typedef struct _IA32_OPERAND
|
|
{
|
|
ULONG_PTR v;
|
|
BOOLEAN RegisterMode;
|
|
} IA32_OPERAND, *PIA32_OPERAND;
|
|
|
|
typedef union _IA32_PREFIX
|
|
{
|
|
ULONG Value;
|
|
|
|
struct _IA32_PREFIX_BITS
|
|
{
|
|
ULONG Lock : 1;
|
|
ULONG RepNe : 1;
|
|
ULONG Rep : 1;
|
|
ULONG CsOverride : 1;
|
|
ULONG SsOverride : 1;
|
|
ULONG DsOverride : 1;
|
|
ULONG EsOverride : 1;
|
|
ULONG FsOverride : 1;
|
|
ULONG GsOverride : 1;
|
|
ULONG SizeOverride : 1;
|
|
ULONG AddressOverride : 1;
|
|
} b;
|
|
|
|
} IA32_PREFIX, *PIA32_PREFIX;
|
|
|
|
typedef struct _IA32_INSTRUCTION
|
|
{
|
|
|
|
//
|
|
// Instruction EIP
|
|
//
|
|
|
|
PCHAR Eip;
|
|
|
|
//
|
|
// Instruction description
|
|
//
|
|
|
|
PIA32_OPCODE_DESCRIPTION Description;
|
|
|
|
//
|
|
// Eflags
|
|
//
|
|
|
|
IA32_EFLAGS Eflags;
|
|
|
|
|
|
//
|
|
// Instruction opcode
|
|
//
|
|
|
|
UCHAR Opcode;
|
|
|
|
//
|
|
// Operands size and mask
|
|
//
|
|
|
|
UCHAR OperandSize;
|
|
ULONG OperandMask;
|
|
|
|
//
|
|
// Instruction operands
|
|
//
|
|
|
|
IA32_OPERAND Operand1;
|
|
IA32_OPERAND Operand2;
|
|
|
|
//
|
|
// Instruction prefixes
|
|
//
|
|
|
|
IA32_PREFIX Prefix;
|
|
|
|
|
|
} IA32_INSTRUCTION, *PIA32_INSTRUCTION;
|
|
|
|
|
|
#if defined(IADBG)
|
|
ULONG IA32Debug = 0x000fffff;
|
|
|
|
#define IA32_DEBUG_INTERCEPTION 0x00000001
|
|
#define IA32_DEBUG_EXCEPTION 0x00000002
|
|
#define IA32_DEBUG_INTERRUPT 0x00000004
|
|
|
|
#define IA32_DEBUG_DIVIDE 0x00000010
|
|
#define IA32_DEBUG_DEBUG 0x00000020
|
|
#define IA32_DEBUG_OVERFLOW 0x00000040
|
|
#define IA32_DEBUG_BOUND 0x00000080
|
|
#define IA32_DEBUG_INSTRUCTION 0x00000100
|
|
#define IA32_DEBUG_NODEVICE 0x00000200
|
|
#define IA32_DEBUG_NOTPRESENT 0x00000400
|
|
#define IA32_DEBUG_STACK 0x00000800
|
|
#define IA32_DEBUG_GPFAULT 0x00001000
|
|
#define IA32_DEBUG_FPFAULT 0x00002000
|
|
#define IA32_DEBUG_ALIGNMENT 0x00004000
|
|
#define IA32_DEBUG_GATE 0x00008000
|
|
#define IA32_DEBUG_BREAK 0x00010000
|
|
#define IA32_DEBUG_INTNN 0x00020000
|
|
#define IA32_DEBUG_FLAG 0x00040000
|
|
#define IA32_DEBUG_LOCK 0x00080000
|
|
//
|
|
// define debug macro
|
|
//
|
|
#define IF_IA32TRAP_DEBUG( ComponentFlag ) \
|
|
if (IA32Debug & (IA32_DEBUG_ ## ComponentFlag))
|
|
|
|
|
|
#else // IADBG
|
|
|
|
#define IF_IA32TRAP_DEBUG( ComponentFlag ) if (FALSE)
|
|
|
|
#endif // IADBG
|