/** @file\r
Contains code that implements the virtual machine.\r
\r
-Copyright (c) 2006 - 2010, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "EbcInt.h"\r
#include "EbcExecute.h"\r
+#include "EbcDebuggerHook.h"\r
\r
\r
//\r
{ ExecuteMOVIn }, // opcode 0x38 - mov immediate natural\r
{ ExecuteMOVREL }, // opcode 0x39 - move data relative to PC\r
{ NULL }, // opcode 0x3a\r
- { NULL }, // opcode 0x3b \r
- { NULL }, // opcode 0x3c \r
- { NULL }, // opcode 0x3d \r
- { NULL }, // opcode 0x3e \r
- { NULL } // opcode 0x3f \r
+ { NULL }, // opcode 0x3b\r
+ { NULL }, // opcode 0x3c\r
+ { NULL }, // opcode 0x3d\r
+ { NULL }, // opcode 0x3e\r
+ { NULL } // opcode 0x3f\r
};\r
\r
//\r
//\r
CONST UINT8 mJMPLen[] = { 2, 2, 6, 10 };\r
\r
-//\r
-// Simple Debugger Protocol GUID\r
-//\r
-EFI_GUID mEbcSimpleDebuggerProtocolGuid = EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL_GUID;\r
-\r
-\r
/**\r
Given a pointer to a new VM context, execute one or more instructions. This\r
function is only used for test purposes via the EBC VM test protocol.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
EbcExecuteInstructions (\r
IN EFI_EBC_VM_TEST_PROTOCOL *This,\r
IN VM_CONTEXT *VmPtr,\r
//\r
DEBUG_CODE_BEGIN ();\r
Status = gBS->LocateProtocol (\r
- &mEbcSimpleDebuggerProtocolGuid,\r
+ &gEfiEbcSimpleDebuggerProtocolGuid,\r
NULL,\r
(VOID **) &EbcSimpleDebugger\r
);\r
Status = EFI_UNSUPPORTED;\r
goto Done;\r
}\r
+\r
+ EbcDebuggerHookExecuteStart (VmPtr);\r
+\r
//\r
// The EBC VM is a strongly ordered processor, so perform a fence operation before\r
// and after each instruction is executed.\r
\r
MemoryFence ();\r
\r
+ EbcDebuggerHookExecuteEnd (VmPtr);\r
+\r
//\r
// If the step flag is set, signal an exception and continue. We don't\r
// clear it here. Assuming the debugger is responsible for clearing it.\r
//\r
// Not indirect source: MOVxx {@}Rx, Ry [Index]\r
//\r
- Data64 = VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index64Op2;\r
+ Data64 = (UINT64) (VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index64Op2);\r
//\r
// Did Operand2 have an index? If so, treat as two signed values since\r
// indexes are signed values.\r
UINT64 U64EbcEntryPoint;\r
INT32 Offset;\r
\r
+ Thunk = NULL;\r
Operands = GETOPERANDS (VmPtr);\r
switch (Operands) {\r
//\r
ConditionFlag = (UINT8) VMFLAG_ISSET (VmPtr, VMFLAGS_CC);\r
if ((Operand & CONDITION_M_CONDITIONAL) != 0) {\r
if (CompareSet != ConditionFlag) {\r
+ EbcDebuggerHookJMPStart (VmPtr);\r
VmPtr->Ip += Size;\r
+ EbcDebuggerHookJMPEnd (VmPtr);\r
return EFI_SUCCESS;\r
}\r
}\r
// 64-bit immediate data is full address. Read the immediate data,\r
// check for alignment, and jump absolute.\r
//\r
- Data64 = VmReadImmed64 (VmPtr, 2);\r
+ Data64 = (UINT64) VmReadImmed64 (VmPtr, 2);\r
if (!IS_ALIGNED ((UINTN) Data64, sizeof (UINT16))) {\r
EbcDebugSignalException (\r
EXCEPT_EBC_ALIGNMENT_CHECK,\r
//\r
// Take jump -- relative or absolute\r
//\r
+ EbcDebuggerHookJMPStart (VmPtr);\r
if ((Operand & JMP_M_RELATIVE) != 0) {\r
VmPtr->Ip += (UINTN) Data64 + Size;\r
} else {\r
VmPtr->Ip = (VMIP) (UINTN) Data64;\r
}\r
+ EbcDebuggerHookJMPEnd (VmPtr);\r
\r
return EFI_SUCCESS;\r
}\r
if (OPERAND1_REGNUM (Operand) == 0) {\r
Data64 = 0;\r
} else {\r
- Data64 = OPERAND1_REGDATA (VmPtr, Operand);\r
+ Data64 = (UINT64) OPERAND1_REGDATA (VmPtr, Operand);\r
}\r
//\r
// Decode the forms\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ EbcDebuggerHookJMPStart (VmPtr);\r
if ((Operand & JMP_M_RELATIVE) != 0) {\r
VmPtr->Ip += (UINTN) Addr + Size;\r
} else {\r
VmPtr->Ip = (VMIP) Addr;\r
}\r
+ EbcDebuggerHookJMPEnd (VmPtr);\r
+\r
} else {\r
//\r
// Form: JMP32 Rx {Immed32}\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ EbcDebuggerHookJMPStart (VmPtr);\r
if ((Operand & JMP_M_RELATIVE) != 0) {\r
VmPtr->Ip += (UINTN) Addr + Size;\r
} else {\r
VmPtr->Ip = (VMIP) Addr;\r
}\r
+ EbcDebuggerHookJMPEnd (VmPtr);\r
+\r
}\r
\r
return EFI_SUCCESS;\r
//\r
if ((Opcode & CONDITION_M_CONDITIONAL) != 0) {\r
if (CompareSet != ConditionFlag) {\r
+ EbcDebuggerHookJMP8Start (VmPtr);\r
VmPtr->Ip += 2;\r
+ EbcDebuggerHookJMP8End (VmPtr);\r
return EFI_SUCCESS;\r
}\r
}\r
//\r
// Want to check for offset == -2 and then raise an exception?\r
//\r
+ EbcDebuggerHookJMP8Start (VmPtr);\r
VmPtr->Ip += (Offset * 2) + 2;\r
+ EbcDebuggerHookJMP8End (VmPtr);\r
return EFI_SUCCESS;\r
}\r
\r
} else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH32) {\r
VmWriteMem32 (VmPtr, (UINTN) Op1, (UINT32) ImmData64);\r
} else {\r
- VmWriteMem64 (VmPtr, (UINTN) Op1, ImmData64);\r
+ VmWriteMem64 (VmPtr, (UINTN) Op1, (UINT64) ImmData64);\r
}\r
}\r
//\r
// Get the address\r
//\r
Op1 = (UINT64) VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;\r
- VmWriteMemN (VmPtr, (UINTN) Op1, (INTN) ImmedIndex64);\r
+ VmWriteMemN (VmPtr, (UINTN) Op1, (UINTN)(INTN) ImmedIndex64);\r
}\r
//\r
// Advance the instruction pointer\r
//\r
// Get the data from the source.\r
//\r
- Op2 = (INT64) ((INTN) (VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index));\r
+ Op2 = (UINT64)(INT64)(INTN)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index);\r
if (OPERAND2_INDIRECT (Operands)) {\r
- Op2 = (INT64) (INTN) VmReadMemN (VmPtr, (UINTN) Op2);\r
+ Op2 = (UINT64)(INT64)(INTN)VmReadMemN (VmPtr, (UINTN) Op2);\r
}\r
//\r
// Now write back the result.\r
//\r
// Get the data from the source.\r
//\r
- Op2 = (INT64) ((INTN) (VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index));\r
+ Op2 = (UINT64)(INT64)(INTN)(INT64)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index);\r
if (OPERAND2_INDIRECT (Operands)) {\r
- Op2 = (INT64) (INTN) VmReadMemN (VmPtr, (UINTN) Op2);\r
+ Op2 = (UINT64)(INT64)(INTN)(INT64)VmReadMemN (VmPtr, (UINTN) Op2);\r
}\r
//\r
// Now write back the result.\r
if (OPERAND1_INDIRECT (Operands)) {\r
VmWriteMemN (VmPtr, (UINTN) (VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16), DataN);\r
} else {\r
- VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (INT64) (UINT64) ((UINTN) DataN + Index16);\r
+ VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (INT64) (UINT64) (UINTN) (DataN + Index16);\r
}\r
\r
return EFI_SUCCESS;\r
//\r
Opcode = GETOPCODE (VmPtr);\r
Operands = GETOPERANDS (VmPtr);\r
+\r
+ if ((Operands & OPERAND_M_NATIVE_CALL) != 0) {\r
+ EbcDebuggerHookCALLEXStart (VmPtr);\r
+ } else {\r
+ EbcDebuggerHookCALLStart (VmPtr);\r
+ }\r
+\r
//\r
// Assign these as well to avoid compiler warnings\r
//\r
}\r
}\r
\r
+ if ((Operands & OPERAND_M_NATIVE_CALL) != 0) {\r
+ EbcDebuggerHookCALLEXEnd (VmPtr);\r
+ } else {\r
+ EbcDebuggerHookCALLEnd (VmPtr);\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
IN VM_CONTEXT *VmPtr\r
)\r
{\r
+\r
+ EbcDebuggerHookRETStart (VmPtr);\r
+\r
//\r
// If we're at the top of the stack, then simply set the done\r
// flag and return\r
VmPtr->Gpr[0] += 8;\r
}\r
\r
+\r
+ EbcDebuggerHookRETEnd (VmPtr);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
if (Flag != 0) {\r
VMFLAG_SET (VmPtr, VMFLAGS_CC);\r
} else {\r
- VMFLAG_CLEAR (VmPtr, VMFLAGS_CC);\r
+ VMFLAG_CLEAR (VmPtr, (UINT64)VMFLAGS_CC);\r
}\r
//\r
// Advance the IP\r
if (Flag != 0) {\r
VMFLAG_SET (VmPtr, VMFLAGS_CC);\r
} else {\r
- VMFLAG_CLEAR (VmPtr, VMFLAGS_CC);\r
+ VMFLAG_CLEAR (VmPtr, (UINT64)VMFLAGS_CC);\r
}\r
//\r
// Advance the IP\r
if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {\r
return (UINT64) ((INT64) ((INT64) Op1 - (INT64) Op2));\r
} else {\r
- return (UINT64) ((INT64) ((INT32) Op1 - (INT32) Op2));\r
+ return (UINT64) ((INT64) ((INT32) ((INT32) Op1 - (INT32) Op2)));\r
}\r
}\r
\r
if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {\r
return MultS64x64 ((INT64)Op1, (INT64)Op2);\r
} else {\r
- return (UINT64) ((INT64) ((INT32) Op1 * (INT32) Op2));\r
+ return (UINT64) ((INT64) ((INT32) ((INT32) Op1 * (INT32) Op2)));\r
}\r
}\r
\r
if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {\r
return MultU64x64 (Op1, Op2);\r
} else {\r
- return (UINT64) ((UINT32) Op1 * (UINT32) Op2);\r
+ return (UINT64) ((UINT32) ((UINT32) Op1 * (UINT32) Op2));\r
}\r
}\r
\r
// Get the destination register\r
//\r
if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {\r
- return (UINT64) (DivU64x64Remainder ((INT64)Op1, (INT64)Op2, &Remainder));\r
+ return (UINT64) (DivU64x64Remainder (Op1, Op2, &Remainder));\r
} else {\r
return (UINT64) ((UINT32) Op1 / (UINT32) Op2);\r
}\r
// Get operand1 (destination and sometimes also an actual operand)\r
// of form {@}R1\r
//\r
- Op1 = VmPtr->Gpr[OPERAND1_REGNUM (Operands)];\r
+ Op1 = (UINT64) VmPtr->Gpr[OPERAND1_REGNUM (Operands)];\r
if (OPERAND1_INDIRECT (Operands)) {\r
if ((Opcode & DATAMANIP_M_64) != 0) {\r
Op1 = VmReadMem64 (VmPtr, (UINTN) Op1);\r
//\r
DataManipDispatchTableIndex = (Opcode & OPCODE_M_OPCODE) - OPCODE_NOT;\r
if ((DataManipDispatchTableIndex < 0) ||\r
- (DataManipDispatchTableIndex >= sizeof (mDataManipDispatchTable) / sizeof (mDataManipDispatchTable[0]))) {\r
+ (DataManipDispatchTableIndex >= ARRAY_SIZE (mDataManipDispatchTable))) {\r
EbcDebugSignalException (\r
EXCEPT_EBC_INVALID_OPCODE,\r
EXCEPTION_FLAG_ERROR,\r
// Write back the result.\r
//\r
if (OPERAND1_INDIRECT (Operands)) {\r
- Op1 = VmPtr->Gpr[OPERAND1_REGNUM (Operands)];\r
+ Op1 = (UINT64) VmPtr->Gpr[OPERAND1_REGNUM (Operands)];\r
if ((Opcode & DATAMANIP_M_64) != 0) {\r
VmWriteMem64 (VmPtr, (UINTN) Op1, Op2);\r
} else {\r
//\r
ConstUnits = ARShiftU64 (((Index &~0xF000000000000000ULL) & Mask), (UINTN)NBits);\r
\r
- Offset = MultU64x64 (NaturalUnits, sizeof (UINTN)) + ConstUnits;\r
+ Offset = MultU64x64 ((UINT64) NaturalUnits, sizeof (UINTN)) + ConstUnits;\r
\r
//\r
// Now set the sign\r
)\r
{\r
EFI_STATUS Status;\r
- UINT32 Data32;\r
\r
//\r
// Convert the address if it's in the stack gap\r
}\r
\r
MemoryFence ();\r
- Data32 = (UINT32) (((UINT32 *) &Data)[1]);\r
- if ((Status = VmWriteMem32 (VmPtr, Addr + sizeof (UINT32), Data32)) != EFI_SUCCESS) {\r
+ if ((Status = VmWriteMem32 (VmPtr, Addr + sizeof (UINT32), (UINT32) RShiftU64(Data, 32))) != EFI_SUCCESS) {\r
return Status;\r
}\r
\r
//\r
// Return unaligned data. Assume little endian.\r
//\r
- Data = (UINT64) VmReadMem32 (VmPtr, Addr);\r
- Data32 = VmReadMem32 (VmPtr, Addr + sizeof (UINT32));\r
- *(UINT32 *) ((UINT32 *) &Data + 1) = Data32;\r
+ Data32 = VmReadMem32 (VmPtr, Addr);\r
+ Data = (UINT64) VmReadMem32 (VmPtr, Addr + sizeof (UINT32));\r
+ Data = LShiftU64 (Data, 32) | Data32;\r
return Data;\r
}\r
\r