18#define TDX_MMIO_READ 0
19#define TDX_MMIO_WRITE 1
77 Regs->Rax = CpuIdData.Regs[0];
78 Regs->Rbx = CpuIdData.Regs[1];
79 Regs->Rcx = CpuIdData.Regs[2];
80 Regs->Rdx = CpuIdData.Regs[3];
114 Write = Veinfo->ExitQualification.Io.Direction ?
FALSE :
TRUE;
115 Size = Veinfo->ExitQualification.Io.Size + 1;
116 Port = Veinfo->ExitQualification.Io.Port;
118 if (Veinfo->ExitQualification.Io.String) {
122 RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;
127 CopyMem (&Val, (VOID *)Regs->Rsi, Size);
131 Status =
TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ?
NULL : &Val));
136 if (Write ==
FALSE) {
137 CopyMem ((VOID *)Regs->Rdi, &Val, Size);
141 if (Veinfo->ExitQualification.Io.Rep) {
149 CopyMem (&Val, (VOID *)&Regs->Rax, Size);
152 Status =
TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ?
NULL : &Val));
153 if ((Status == 0) && (Write ==
FALSE)) {
154 CopyMem ((VOID *)&Regs->Rax, &Val, Size);
182 Status =
TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);
184 Regs->Rax = Data.Regs.Eax;
185 Regs->Rdx = Data.Regs.Edx;
212 Data.Regs.Eax = (UINT32)Regs->Rax;
213 Data.Regs.Edx = (UINT32)Regs->Rdx;
215 Status =
TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0,
NULL);
223TdxDecodeInstruction (
230 DEBUG ((DEBUG_INFO,
"TDX: #TD[EPT] instruction (%p):", Rip));
231 for (i = 0; i <
MIN (15, Length); i++) {
232 DEBUG ((DEBUG_INFO,
"%02x ", Rip[i]));
235 DEBUG ((DEBUG_INFO,
"\n"));
238#define TDX_DECODER_BUG_ON(x) \
240 TdxDecodeInstruction(Rip); \
241 TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \
260 IN UINT32 ReadOrWrite,
267 if ((MmioSize != 1) && (MmioSize != 2) && (MmioSize != 4) && (MmioSize != 8)) {
268 DEBUG ((DEBUG_ERROR,
"%a: Invalid MmioSize - %d\n", __func__, MmioSize));
269 return EFI_INVALID_PARAMETER;
273 return EFI_INVALID_PARAMETER;
277 if (ReadOrWrite == TDX_MMIO_READ) {
278 TdStatus =
TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_READ, GuestPA, 0, Val);
279 }
else if (ReadOrWrite == TDX_MMIO_WRITE) {
280 TdStatus =
TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_WRITE, GuestPA, *Val, 0);
282 return EFI_INVALID_PARAMETER;
286 DEBUG ((DEBUG_ERROR,
"%a: TdVmcall failed with %llx\n", __func__, TdStatus));
336 if (EFI_ERROR (Status)) {
337 DEBUG ((DEBUG_ERROR,
"%a: Initialize InstructionData failed! (%r)\n", __func__, Status));
341 OpCode = *(InstructionData->OpCodes);
342 if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
343 OpCode = *(InstructionData->OpCodes + 1);
357 Bytes = ((Bytes != 0) ? Bytes :
358 (InstructionData->DataSize == Size16Bits) ? 2 :
359 (InstructionData->DataSize == Size32Bits) ? 4 :
360 (InstructionData->DataSize == Size64Bits) ? 8 :
363 if (InstructionData->Ext.ModRm.Mod == 3) {
364 DEBUG ((DEBUG_ERROR,
"%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __func__, OpCode));
365 return EFI_UNSUPPORTED;
368 Address = InstructionData->Ext.RmData;
369 Val = InstructionData->Ext.RegData;
370 ReadOrWrite = TDX_MMIO_WRITE;
383 Bytes = ((Bytes != 0) ? Bytes :
384 (InstructionData->DataSize == Size16Bits) ? 2 :
385 (InstructionData->DataSize == Size32Bits) ? 4 :
386 (InstructionData->DataSize == Size64Bits) ? 8 :
389 InstructionData->ImmediateSize = (
UINTN)(1 << InstructionData->AddrSize);
390 InstructionData->End += InstructionData->ImmediateSize;
391 CopyMem (&Address, InstructionData->Immediate, InstructionData->ImmediateSize);
394 ReadOrWrite = TDX_MMIO_WRITE;
407 Bytes = ((Bytes != 0) ? Bytes :
408 (InstructionData->DataSize == Size16Bits) ? 2 :
409 (InstructionData->DataSize == Size32Bits) ? 4 :
410 (InstructionData->DataSize == Size64Bits) ? 8 :
413 InstructionData->ImmediateSize = Bytes;
414 InstructionData->End += Bytes;
417 CopyMem (&Val, InstructionData->Immediate, InstructionData->ImmediateSize);
419 Address = InstructionData->Ext.RmData;
420 ReadOrWrite = TDX_MMIO_WRITE;
434 Bytes = ((Bytes != 0) ? Bytes :
435 (InstructionData->DataSize == Size16Bits) ? 2 :
436 (InstructionData->DataSize == Size32Bits) ? 4 :
437 (InstructionData->DataSize == Size64Bits) ? 8 :
439 if (InstructionData->Ext.ModRm.Mod == 3) {
443 DEBUG ((DEBUG_ERROR,
"%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __func__, OpCode));
444 return EFI_UNSUPPORTED;
447 Address = InstructionData->Ext.RmData;
448 ReadOrWrite = TDX_MMIO_READ;
473 Bytes = ((Bytes != 0) ? Bytes :
474 (InstructionData->DataSize == Size16Bits) ? 2 :
475 (InstructionData->DataSize == Size32Bits) ? 4 :
476 (InstructionData->DataSize == Size64Bits) ? 8 :
479 InstructionData->ImmediateSize = (
UINTN)(1 << InstructionData->AddrSize);
480 InstructionData->End += InstructionData->ImmediateSize;
485 InstructionData->Immediate,
486 InstructionData->ImmediateSize
497 ReadOrWrite = TDX_MMIO_READ;
511 Bytes = (Bytes != 0) ? Bytes : 2;
512 Address = InstructionData->Ext.RmData;
521 ReadOrWrite = TDX_MMIO_READ;
535 Bytes = (Bytes != 0) ? Bytes : 2;
537 Address = InstructionData->Ext.RmData;
541 Data = (UINT8 *)&Val;
542 SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
545 Data = (UINT16 *)&Val;
546 SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
556 ReadOrWrite = TDX_MMIO_READ;
561 DEBUG ((DEBUG_ERROR,
"%a: Invalid MMIO opcode (%x)\n", __func__, OpCode));
562 Status = EFI_UNSUPPORTED;
565 if (!EFI_ERROR (Status)) {
566 ParsedInstruction->OpCode = OpCode;
567 ParsedInstruction->Address = Address;
568 ParsedInstruction->Bytes = Bytes;
569 ParsedInstruction->Register =
Register;
570 ParsedInstruction->Val = Val;
571 ParsedInstruction->ReadOrWrite = ReadOrWrite;
604 TdStatus =
TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
605 if (TdStatus == TDX_EXIT_REASON_SUCCESS) {
606 Gpaw = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);
609 DEBUG ((DEBUG_ERROR,
"%a: TDCALL failed with status=%llx\n", __func__, TdStatus));
614 DEBUG ((DEBUG_ERROR,
"%a: EPT-violation #VE on private memory is not allowed!", __func__));
619 if (EFI_ERROR (Status)) {
626 "%a: Address is not correct! (%d: 0x%llx != 0x%llx)\n",
628 ParsedInstruction.OpCode,
630 ParsedInstruction.Address
635 if (ParsedInstruction.ReadOrWrite == TDX_MMIO_WRITE ) {
636 Status =
TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_WRITE, Veinfo->GuestPA, &ParsedInstruction.Val);
637 }
else if (ParsedInstruction.ReadOrWrite == TDX_MMIO_READ) {
639 Status =
TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_READ, Veinfo->GuestPA, &Val);
640 if (!EFI_ERROR (Status)) {
641 CopyMem (ParsedInstruction.Register, &Val, ParsedInstruction.Bytes);
647 if (EFI_ERROR (Status)) {
656 TdxDecodeInstruction ((UINT8 *)Regs->Rip, Veinfo->ExitInstructionLength);
661 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
693 Regs = SystemContext.SystemContextX64;
694 Status =
TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);
695 ASSERT (Status == 0);
697 DEBUG ((DEBUG_ERROR,
"#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));
698 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
702 switch (ReturnData.VeInfo.ExitReason) {
703 case EXIT_REASON_CPUID:
704 Status =
CpuIdExit (Regs, &ReturnData.VeInfo);
707 "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
708 ReturnData.VeInfo.ExitReason,
709 ReturnData.VeInfo.ExitQualification.Val
713 case EXIT_REASON_HLT:
714 Status =
TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);
717 case EXIT_REASON_IO_INSTRUCTION:
718 Status =
IoExit (Regs, &ReturnData.VeInfo);
721 "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
722 ReturnData.VeInfo.ExitReason,
723 ReturnData.VeInfo.ExitQualification.Val
727 case EXIT_REASON_MSR_READ:
731 "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
732 ReturnData.VeInfo.ExitReason,
733 ReturnData.VeInfo.ExitQualification.Val,
739 case EXIT_REASON_MSR_WRITE:
743 "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
744 ReturnData.VeInfo.ExitReason,
745 ReturnData.VeInfo.ExitQualification.Val,
751 case EXIT_REASON_EPT_VIOLATION:
752 Status =
MmioExit (Regs, &ReturnData.VeInfo);
755 "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
756 ReturnData.VeInfo.ExitReason,
757 ReturnData.VeInfo.ExitQualification.Val
761 case EXIT_REASON_VMCALL:
762 case EXIT_REASON_MWAIT_INSTRUCTION:
763 case EXIT_REASON_MONITOR_INSTRUCTION:
764 case EXIT_REASON_WBINVD:
765 case EXIT_REASON_RDPMC:
766 case EXIT_REASON_INVD:
773 "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",
774 ReturnData.VeInfo.ExitReason,
775 ReturnData.VeInfo.ExitQualification.Val
785 "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",
787 ReturnData.VeInfo.ExitReason,
788 ReturnData.VeInfo.ExitQualification.Val
791 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
795 SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;
UINTN EFIAPI TdCall(IN UINT64 Leaf, IN UINT64 Arg1, IN UINT64 Arg2, IN UINT64 Arg3, IN OUT VOID *Results)
VOID EFIAPI CpuDeadLoop(VOID)
UINTN EFIAPI TdVmCall(IN UINT64 Leaf, IN UINT64 Arg1, IN UINT64 Arg2, IN UINT64 Arg3, IN UINT64 Arg4, IN OUT VOID *Results)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
EFI_STATUS EFIAPI TdVmCallCpuid(IN UINT64 Eax, IN UINT64 Ecx, OUT VOID *Results)
STATIC UINT64 EFIAPI MmioExit(IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN TDCALL_VEINFO_RETURN_DATA *Veinfo)
STATIC UINT64 EFIAPI CpuIdExit(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN TDCALL_VEINFO_RETURN_DATA *Veinfo)
STATIC EFI_STATUS TdxMmioReadWrite(IN UINT32 MmioSize, IN UINT32 ReadOrWrite, IN UINT64 GuestPA, IN UINT64 *Val)
EFI_STATUS EFIAPI CcExitHandleVe(IN OUT EFI_EXCEPTION_TYPE *ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext)
STATIC EFI_STATUS ParseMmioExitInstructions(IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData, OUT MMIO_EXIT_PARSED_INSTRUCTION *ParsedInstruction)
STATIC UINT64 ReadMsrExit(IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN TDCALL_VEINFO_RETURN_DATA *Veinfo)
STATIC UINT64 EFIAPI IoExit(IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN TDCALL_VEINFO_RETURN_DATA *Veinfo)
STATIC UINT64 WriteMsrExit(IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN TDCALL_VEINFO_RETURN_DATA *Veinfo)
UINT64 * CcGetRegisterPointer(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN UINT8 Register)
VOID CcDecodeModRm(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
EFI_STATUS CcInitInstructionData(IN OUT CC_INSTRUCTION_DATA *InstructionData, IN GHCB *Ghcb, IN EFI_SYSTEM_CONTEXT_X64 *Regs)
UINT64 CcInstructionLength(IN CC_INSTRUCTION_DATA *InstructionData)
#define DEBUG(Expression)
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
UINT64 EFIAPI TdSharedPageMask(VOID)
UINT64 EFI_PHYSICAL_ADDRESS