#include <Library/BaseMemoryLib.h>\r
#include <IndustryStandard/Tdx.h>\r
#include <IndustryStandard/InstructionParsing.h>\r
+#include "CcInstruction.h"\r
+\r
+#define TDX_MMIO_READ 0\r
+#define TDX_MMIO_WRITE 1\r
\r
typedef union {\r
struct {\r
VOID\r
EFIAPI\r
TdxDecodeInstruction (\r
- IN UINT8 *Rip\r
+ IN UINT8 *Rip,\r
+ IN UINT32 Length\r
)\r
{\r
UINTN i;\r
\r
DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));\r
- for (i = 0; i < 15; i++) {\r
- DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));\r
+ for (i = 0; i < MIN (15, Length); i++) {\r
+ DEBUG ((DEBUG_INFO, "%02x ", Rip[i]));\r
}\r
\r
DEBUG ((DEBUG_INFO, "\n"));\r
if ((x)) { \\r
TdxDecodeInstruction(Rip); \\r
TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \\r
+ CpuDeadLoop (); \\r
}\r
\r
+/**\r
+ * Tdx MMIO access via TdVmcall.\r
+ *\r
+ * @param MmioSize Size of the MMIO access\r
+ * @param ReadOrWrite Read or write operation\r
+ * @param GuestPA Guest physical address\r
+ * @param Val Pointer to the value which is read or written\r
+\r
+ * @retval EFI_SUCCESS Successfully access the mmio\r
+ * @retval Others Other errors as indicated\r
+ */\r
STATIC\r
-UINT64 *\r
-EFIAPI\r
-GetRegFromContext (\r
- IN EFI_SYSTEM_CONTEXT_X64 *Regs,\r
- IN UINTN RegIndex\r
+EFI_STATUS\r
+TdxMmioReadWrite (\r
+ IN UINT32 MmioSize,\r
+ IN UINT32 ReadOrWrite,\r
+ IN UINT64 GuestPA,\r
+ IN UINT64 *Val\r
)\r
{\r
- switch (RegIndex) {\r
- case 0: return &Regs->Rax;\r
- break;\r
- case 1: return &Regs->Rcx;\r
- break;\r
- case 2: return &Regs->Rdx;\r
- break;\r
- case 3: return &Regs->Rbx;\r
- break;\r
- case 4: return &Regs->Rsp;\r
- break;\r
- case 5: return &Regs->Rbp;\r
- break;\r
- case 6: return &Regs->Rsi;\r
- break;\r
- case 7: return &Regs->Rdi;\r
- break;\r
- case 8: return &Regs->R8;\r
- break;\r
- case 9: return &Regs->R9;\r
+ UINT64 TdStatus;\r
+\r
+ if ((MmioSize != 1) && (MmioSize != 2) && (MmioSize != 4) && (MmioSize != 8)) {\r
+ DEBUG ((DEBUG_ERROR, "%a: Invalid MmioSize - %d\n", __FUNCTION__, MmioSize));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Val == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TdStatus = 0;\r
+ if (ReadOrWrite == TDX_MMIO_READ) {\r
+ TdStatus = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_READ, GuestPA, 0, Val);\r
+ } else if (ReadOrWrite == TDX_MMIO_WRITE) {\r
+ TdStatus = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_WRITE, GuestPA, *Val, 0);\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (TdStatus != 0) {\r
+ DEBUG ((DEBUG_ERROR, "%a: TdVmcall failed with %llx\n", __FUNCTION__, TdStatus));\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+typedef struct {\r
+ UINT8 OpCode;\r
+ UINT32 Bytes;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ UINT64 Val;\r
+ UINT64 *Register;\r
+ UINT32 ReadOrWrite;\r
+} MMIO_EXIT_PARSED_INSTRUCTION;\r
+\r
+/**\r
+ * Parse the MMIO instructions.\r
+ *\r
+ * @param Regs Pointer to the EFI_SYSTEM_CONTEXT_X64 which includes the instructions\r
+ * @param InstructionData Pointer to the CC_INSTRUCTION_DATA\r
+ * @param ParsedInstruction Pointer to the parsed instruction data\r
+ *\r
+ * @retval EFI_SUCCESS Successfully parsed the instructions\r
+ * @retval Others Other error as indicated\r
+ */\r
+STATIC\r
+EFI_STATUS\r
+ParseMmioExitInstructions (\r
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,\r
+ IN OUT CC_INSTRUCTION_DATA *InstructionData,\r
+ OUT MMIO_EXIT_PARSED_INSTRUCTION *ParsedInstruction\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 OpCode;\r
+ UINT8 SignByte;\r
+ UINT32 Bytes;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ UINT64 Val;\r
+ UINT64 *Register;\r
+ UINT32 ReadOrWrite;\r
+\r
+ Address = 0;\r
+ Bytes = 0;\r
+ Register = NULL;\r
+ Status = EFI_SUCCESS;\r
+ Val = 0;\r
+\r
+ Status = CcInitInstructionData (InstructionData, NULL, Regs);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a: Initialize InstructionData failed! (%r)\n", __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+\r
+ OpCode = *(InstructionData->OpCodes);\r
+ if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {\r
+ OpCode = *(InstructionData->OpCodes + 1);\r
+ }\r
+\r
+ switch (OpCode) {\r
+ //\r
+ // MMIO write (MOV reg/memX, regX)\r
+ //\r
+ case 0x88:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0x89:\r
+ CcDecodeModRm (Regs, InstructionData);\r
+ Bytes = ((Bytes != 0) ? Bytes :\r
+ (InstructionData->DataSize == Size16Bits) ? 2 :\r
+ (InstructionData->DataSize == Size32Bits) ? 4 :\r
+ (InstructionData->DataSize == Size64Bits) ? 8 :\r
+ 0);\r
+\r
+ if (InstructionData->Ext.ModRm.Mod == 3) {\r
+ DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __FUNCTION__, OpCode));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Address = InstructionData->Ext.RmData;\r
+ Val = InstructionData->Ext.RegData;\r
+ ReadOrWrite = TDX_MMIO_WRITE;\r
+\r
break;\r
- case 10: return &Regs->R10;\r
+\r
+ //\r
+ // MMIO write (MOV moffsetX, aX)\r
+ //\r
+ case 0xA2:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0xA3:\r
+ Bytes = ((Bytes != 0) ? Bytes :\r
+ (InstructionData->DataSize == Size16Bits) ? 2 :\r
+ (InstructionData->DataSize == Size32Bits) ? 4 :\r
+ (InstructionData->DataSize == Size64Bits) ? 8 :\r
+ 0);\r
+\r
+ InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
+ InstructionData->End += InstructionData->ImmediateSize;\r
+ CopyMem (&Address, InstructionData->Immediate, InstructionData->ImmediateSize);\r
+\r
+ Val = Regs->Rax;\r
+ ReadOrWrite = TDX_MMIO_WRITE;\r
break;\r
- case 11: return &Regs->R11;\r
+\r
+ //\r
+ // MMIO write (MOV reg/memX, immX)\r
+ //\r
+ case 0xC6:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0xC7:\r
+ CcDecodeModRm (Regs, InstructionData);\r
+ Bytes = ((Bytes != 0) ? Bytes :\r
+ (InstructionData->DataSize == Size16Bits) ? 2 :\r
+ (InstructionData->DataSize == Size32Bits) ? 4 :\r
+ (InstructionData->DataSize == Size64Bits) ? 8 :\r
+ 0);\r
+\r
+ InstructionData->ImmediateSize = Bytes;\r
+ InstructionData->End += Bytes;\r
+\r
+ Val = 0;\r
+ CopyMem (&Val, InstructionData->Immediate, InstructionData->ImmediateSize);\r
+\r
+ Address = InstructionData->Ext.RmData;\r
+ ReadOrWrite = TDX_MMIO_WRITE;\r
+\r
break;\r
- case 12: return &Regs->R12;\r
+\r
+ //\r
+ // MMIO read (MOV regX, reg/memX)\r
+ //\r
+ case 0x8A:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0x8B:\r
+ CcDecodeModRm (Regs, InstructionData);\r
+ Bytes = ((Bytes != 0) ? Bytes :\r
+ (InstructionData->DataSize == Size16Bits) ? 2 :\r
+ (InstructionData->DataSize == Size32Bits) ? 4 :\r
+ (InstructionData->DataSize == Size64Bits) ? 8 :\r
+ 0);\r
+ if (InstructionData->Ext.ModRm.Mod == 3) {\r
+ //\r
+ // NPF on two register operands???\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __FUNCTION__, OpCode));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Address = InstructionData->Ext.RmData;\r
+ ReadOrWrite = TDX_MMIO_READ;\r
+\r
+ Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+ if (Register == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (Bytes == 4) {\r
+ //\r
+ // Zero-extend for 32-bit operation\r
+ //\r
+ *Register = 0;\r
+ }\r
+\r
break;\r
- case 13: return &Regs->R13;\r
+\r
+ //\r
+ // MMIO read (MOV aX, moffsetX)\r
+ //\r
+ case 0xA0:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0xA1:\r
+ Bytes = ((Bytes != 0) ? Bytes :\r
+ (InstructionData->DataSize == Size16Bits) ? 2 :\r
+ (InstructionData->DataSize == Size32Bits) ? 4 :\r
+ (InstructionData->DataSize == Size64Bits) ? 8 :\r
+ 0);\r
+\r
+ InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
+ InstructionData->End += InstructionData->ImmediateSize;\r
+\r
+ Address = 0;\r
+ CopyMem (\r
+ &Address,\r
+ InstructionData->Immediate,\r
+ InstructionData->ImmediateSize\r
+ );\r
+\r
+ if (Bytes == 4) {\r
+ //\r
+ // Zero-extend for 32-bit operation\r
+ //\r
+ Regs->Rax = 0;\r
+ }\r
+\r
+ Register = &Regs->Rax;\r
+ ReadOrWrite = TDX_MMIO_READ;\r
+\r
break;\r
- case 14: return &Regs->R14;\r
+\r
+ //\r
+ // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)\r
+ //\r
+ case 0xB6:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0xB7:\r
+ CcDecodeModRm (Regs, InstructionData);\r
+ Bytes = (Bytes != 0) ? Bytes : 2;\r
+ Address = InstructionData->Ext.RmData;\r
+\r
+ Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+ if (Register == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);\r
+\r
+ ReadOrWrite = TDX_MMIO_READ;\r
+\r
break;\r
- case 15: return &Regs->R15;\r
+\r
+ //\r
+ // MMIO read w/ sign-extension (MOVSX regX, reg/memX)\r
+ //\r
+ case 0xBE:\r
+ Bytes = 1;\r
+ //\r
+ // fall through\r
+ //\r
+ case 0xBF:\r
+ CcDecodeModRm (Regs, InstructionData);\r
+ Bytes = (Bytes != 0) ? Bytes : 2;\r
+\r
+ Address = InstructionData->Ext.RmData;\r
+\r
+ if (Bytes == 1) {\r
+ UINT8 *Data;\r
+ Data = (UINT8 *)&Val;\r
+ SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;\r
+ } else {\r
+ UINT16 *Data;\r
+ Data = (UINT16 *)&Val;\r
+ SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;\r
+ }\r
+\r
+ Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+ if (Register == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);\r
+\r
+ ReadOrWrite = TDX_MMIO_READ;\r
+\r
break;\r
+\r
+ default:\r
+ DEBUG ((DEBUG_ERROR, "%a: Invalid MMIO opcode (%x)\n", __FUNCTION__, OpCode));\r
+ Status = EFI_UNSUPPORTED;\r
}\r
\r
- return NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ ParsedInstruction->OpCode = OpCode;\r
+ ParsedInstruction->Address = Address;\r
+ ParsedInstruction->Bytes = Bytes;\r
+ ParsedInstruction->Register = Register;\r
+ ParsedInstruction->Val = Val;\r
+ ParsedInstruction->ReadOrWrite = ReadOrWrite;\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
@param[in] Veinfo VE Info\r
\r
@retval 0 Event handled successfully\r
- @return New exception value to propagate\r
**/\r
STATIC\r
-INTN\r
+UINT64\r
EFIAPI\r
MmioExit (\r
IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,\r
IN TDCALL_VEINFO_RETURN_DATA *Veinfo\r
)\r
{\r
- UINT64 Status;\r
- UINT32 MmioSize;\r
- UINT32 RegSize;\r
- UINT8 OpCode;\r
- BOOLEAN SeenRex;\r
- UINT64 *Reg;\r
- UINT8 *Rip;\r
- UINT64 Val;\r
- UINT32 OpSize;\r
- MODRM ModRm;\r
- REX Rex;\r
- TD_RETURN_DATA TdReturnData;\r
- UINT8 Gpaw;\r
- UINT64 TdSharedPageMask;\r
-\r
- Rip = (UINT8 *)Regs->Rip;\r
- Val = 0;\r
- Rex.Val = 0;\r
- SeenRex = FALSE;\r
-\r
- Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r
- if (Status == TDX_EXIT_REASON_SUCCESS) {\r
+ UINT64 TdStatus;\r
+ EFI_STATUS Status;\r
+ TD_RETURN_DATA TdReturnData;\r
+ UINT8 Gpaw;\r
+ UINT64 Val;\r
+ UINT64 TdSharedPageMask;\r
+ CC_INSTRUCTION_DATA InstructionData;\r
+ MMIO_EXIT_PARSED_INSTRUCTION ParsedInstruction;\r
+\r
+ TdStatus = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r
+ if (TdStatus == TDX_EXIT_REASON_SUCCESS) {\r
Gpaw = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);\r
TdSharedPageMask = 1ULL << (Gpaw - 1);\r
} else {\r
- DEBUG ((DEBUG_ERROR, "TDCALL failed with status=%llx\n", Status));\r
- return Status;\r
+ DEBUG ((DEBUG_ERROR, "%a: TDCALL failed with status=%llx\n", __FUNCTION__, TdStatus));\r
+ goto FatalError;\r
}\r
\r
if ((Veinfo->GuestPA & TdSharedPageMask) == 0) {\r
- DEBUG ((DEBUG_ERROR, "EPT-violation #VE on private memory is not allowed!"));\r
- TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
- CpuDeadLoop ();\r
+ DEBUG ((DEBUG_ERROR, "%a: EPT-violation #VE on private memory is not allowed!", __FUNCTION__));\r
+ goto FatalError;\r
}\r
\r
- //\r
- // Default to 32bit transfer\r
- //\r
- OpSize = 4;\r
-\r
- do {\r
- OpCode = *Rip++;\r
- if (OpCode == 0x66) {\r
- OpSize = 2;\r
- } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {\r
- continue;\r
- } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {\r
- SeenRex = TRUE;\r
- Rex.Val = OpCode;\r
- } else {\r
- break;\r
- }\r
- } while (TRUE);\r
-\r
- //\r
- // We need to have at least 2 more bytes for this instruction\r
- //\r
- TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);\r
-\r
- OpCode = *Rip++;\r
- //\r
- // Two-byte opecode, get next byte\r
- //\r
- if (OpCode == 0x0F) {\r
- OpCode = *Rip++;\r
- }\r
-\r
- switch (OpCode) {\r
- case 0x88:\r
- case 0x8A:\r
- case 0xB6:\r
- MmioSize = 1;\r
- break;\r
- case 0xB7:\r
- MmioSize = 2;\r
- break;\r
- default:\r
- MmioSize = Rex.Bits.W ? 8 : OpSize;\r
- break;\r
+ Status = ParseMmioExitInstructions (Regs, &InstructionData, &ParsedInstruction);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FatalError;\r
}\r
\r
- /* Punt on AH/BH/CH/DH unless it shows up. */\r
- ModRm.Val = *Rip++;\r
- TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4 && !SeenRex && OpCode != 0xB6);\r
- Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3));\r
- TDX_DECODER_BUG_ON (!Reg);\r
-\r
- if (ModRm.Bits.Rm == 4) {\r
- ++Rip; /* SIB byte */\r
+ if (Veinfo->GuestPA != (ParsedInstruction.Address | TdSharedPageMask)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: Address is not correct! (%d: 0x%llx != 0x%llx)\n",\r
+ __FUNCTION__,\r
+ ParsedInstruction.OpCode,\r
+ Veinfo->GuestPA,\r
+ ParsedInstruction.Address\r
+ ));\r
+ goto FatalError;\r
}\r
\r
- if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) && (ModRm.Bits.Rm == 5))) {\r
- Rip += 4; /* DISP32 */\r
- } else if (ModRm.Bits.Mod == 1) {\r
- ++Rip; /* DISP8 */\r
+ if (ParsedInstruction.ReadOrWrite == TDX_MMIO_WRITE ) {\r
+ Status = TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_WRITE, Veinfo->GuestPA, &ParsedInstruction.Val);\r
+ } else if (ParsedInstruction.ReadOrWrite == TDX_MMIO_READ) {\r
+ Val = 0;\r
+ Status = TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_READ, Veinfo->GuestPA, &Val);\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (ParsedInstruction.Register, &Val, ParsedInstruction.Bytes);\r
+ }\r
+ } else {\r
+ goto FatalError;\r
}\r
\r
- switch (OpCode) {\r
- case 0x88:\r
- case 0x89:\r
- CopyMem ((void *)&Val, Reg, MmioSize);\r
- Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
- break;\r
- case 0xC7:\r
- CopyMem ((void *)&Val, Rip, OpSize);\r
- Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
- Rip += OpSize;\r
- default:\r
- //\r
- // 32-bit write registers are zero extended to the full register\r
- // Hence 'MOVZX r[32/64], r/m16' is\r
- // hardcoded to reg size 8, and the straight MOV case has a reg\r
- // size of 8 in the 32-bit read case.\r
- //\r
- switch (OpCode) {\r
- case 0xB6:\r
- RegSize = Rex.Bits.W ? 8 : OpSize;\r
- break;\r
- case 0xB7:\r
- RegSize = 8;\r
- break;\r
- default:\r
- RegSize = MmioSize == 4 ? 8 : MmioSize;\r
- break;\r
- }\r
-\r
- Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0, &Val);\r
- if (Status == 0) {\r
- ZeroMem (Reg, RegSize);\r
- CopyMem (Reg, (void *)&Val, MmioSize);\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto FatalError;\r
}\r
\r
- if (Status == 0) {\r
- TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);\r
+ //\r
+ // We change instruction length to reflect true size so handler can\r
+ // bump rip\r
+ //\r
+ Veinfo->ExitInstructionLength = (UINT32)(CcInstructionLength (&InstructionData));\r
+ TdxDecodeInstruction ((UINT8 *)Regs->Rip, Veinfo->ExitInstructionLength);\r
\r
- //\r
- // We change instruction length to reflect true size so handler can\r
- // bump rip\r
- //\r
- Veinfo->ExitInstructionLength = (UINT32)((UINT64)Rip - Regs->Rip);\r
- }\r
+ return 0;\r
\r
- return Status;\r
+FatalError:\r
+ TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+ CpuDeadLoop ();\r
+ return 0;\r
}\r
\r
/**\r
if (Status != 0) {\r
DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));\r
TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+ CpuDeadLoop ();\r
}\r
\r
switch (ReturnData.VeInfo.ExitReason) {\r
));\r
\r
TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+ CpuDeadLoop ();\r
}\r
\r
SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;\r