VOID\r
);\r
\r
+#if defined (MDE_CPU_X64) || defined (MDE_CPU_IA32)\r
+\r
+/**\r
+ The TDCALL instruction causes a VM exit to the Intel TDX module. It is\r
+ used to call guest-side Intel TDX functions, either local or a TD exit\r
+ to the host VMM, as selected by Leaf.\r
+\r
+ @param[in] Leaf Leaf number of TDCALL instruction\r
+ @param[in] Arg1 Arg1\r
+ @param[in] Arg2 Arg2\r
+ @param[in] Arg3 Arg3\r
+ @param[in,out] Results Returned result of the Leaf function\r
+\r
+ @return 0 A successful call\r
+ @return Other See individual leaf functions\r
+**/\r
+UINTN\r
+EFIAPI\r
+TdCall (\r
+ IN UINT64 Leaf,\r
+ IN UINT64 Arg1,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN OUT VOID *Results\r
+ );\r
+\r
+/**\r
+ TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from the\r
+ host VMM to pass/receive information.\r
+\r
+ @param[in] Leaf Number of sub-functions\r
+ @param[in] Arg1 Arg1\r
+ @param[in] Arg2 Arg2\r
+ @param[in] Arg3 Arg3\r
+ @param[in] Arg4 Arg4\r
+ @param[in,out] Results Returned result of the sub-function\r
+\r
+ @return 0 A successful call\r
+ @return Other See individual sub-functions\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+TdVmCall (\r
+ IN UINT64 Leaf,\r
+ IN UINT64 Arg1,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN UINT64 Arg4,\r
+ IN OUT VOID *Results\r
+ );\r
+\r
+/**\r
+ Probe if TD is enabled.\r
+\r
+ @return TRUE TD is enabled.\r
+ @return FALSE TD is not enabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdIsEnabled (\r
+ VOID\r
+ );\r
+\r
+#endif\r
+\r
#if defined (MDE_CPU_X64)\r
//\r
// The page size for the PVALIDATE instruction\r
X86RdRand.c\r
X86PatchInstruction.c\r
X86SpeculationBarrier.c\r
+ IntelTdxNull.c\r
\r
[Sources.X64]\r
X64/Thunk16.nasm\r
X64/ReadCr0.nasm| MSFT\r
X64/ReadEflags.nasm| MSFT\r
\r
+ X64/TdCall.nasm\r
+ X64/TdVmcall.nasm\r
+ X64/TdProbe.c\r
\r
X64/Non-existing.c\r
Math64.c\r
--- /dev/null
+/** @file\r
+\r
+ Null stub of TdxLib\r
+\r
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+/**\r
+ The TDCALL instruction causes a VM exit to the Intel TDX module. It is\r
+ used to call guest-side Intel TDX functions, either local or a TD exit\r
+ to the host VMM, as selected by Leaf.\r
+ Leaf functions are described at <https://software.intel.com/content/\r
+ www/us/en/develop/articles/intel-trust-domain-extensions.html>\r
+\r
+ @param[in] Leaf Leaf number of TDCALL instruction\r
+ @param[in] Arg1 Arg1\r
+ @param[in] Arg2 Arg2\r
+ @param[in] Arg3 Arg3\r
+ @param[in,out] Results Returned result of the Leaf function\r
+\r
+ @return EFI_SUCCESS\r
+ @return Other See individual leaf functions\r
+**/\r
+UINTN\r
+EFIAPI\r
+TdCall (\r
+ IN UINT64 Leaf,\r
+ IN UINT64 Arg1,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN OUT VOID *Results\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from the\r
+ host VMM to pass/receive information.\r
+\r
+ @param[in] Leaf Number of sub-functions\r
+ @param[in] Arg1 Arg1\r
+ @param[in] Arg2 Arg2\r
+ @param[in] Arg3 Arg3\r
+ @param[in] Arg4 Arg4\r
+ @param[in,out] Results Returned result of the sub-function\r
+\r
+ @return EFI_SUCCESS\r
+ @return Other See individual sub-functions\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+TdVmCall (\r
+ IN UINT64 Leaf,\r
+ IN UINT64 Arg1,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN UINT64 Arg4,\r
+ IN OUT VOID *Results\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Probe if TD is enabled.\r
+\r
+ @return TRUE TD is enabled.\r
+ @return FALSE TD is not enabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdIsEnabled (\r
+ )\r
+{\r
+ return FALSE;\r
+}\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+;* SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;*\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+DEFAULT REL\r
+SECTION .text\r
+\r
+%macro tdcall 0\r
+ db 0x66,0x0f,0x01,0xcc\r
+%endmacro\r
+\r
+%macro tdcall_push_regs 0\r
+ push rbp\r
+ mov rbp, rsp\r
+ push r15\r
+ push r14\r
+ push r13\r
+ push r12\r
+ push rbx\r
+ push rsi\r
+ push rdi\r
+%endmacro\r
+\r
+%macro tdcall_pop_regs 0\r
+ pop rdi\r
+ pop rsi\r
+ pop rbx\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+ pop rbp\r
+%endmacro\r
+\r
+%define number_of_regs_pushed 8\r
+%define number_of_parameters 4\r
+\r
+;\r
+; Keep these in sync for push_regs/pop_regs, code below\r
+; uses them to find 5th or greater parameters\r
+;\r
+%define first_variable_on_stack_offset \\r
+ ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)\r
+%define second_variable_on_stack_offset \\r
+ ((first_variable_on_stack_offset) + 8)\r
+\r
+; TdCall (\r
+; UINT64 Leaf, // Rcx\r
+; UINT64 P1, // Rdx\r
+; UINT64 P2, // R8\r
+; UINT64 P3, // R9\r
+; UINT64 Results, // rsp + 0x28\r
+; )\r
+global ASM_PFX(TdCall)\r
+ASM_PFX(TdCall):\r
+ tdcall_push_regs\r
+\r
+ mov rax, rcx\r
+ mov rcx, rdx\r
+ mov rdx, r8\r
+ mov r8, r9\r
+\r
+ tdcall\r
+\r
+ ; exit if tdcall reports failure.\r
+ test rax, rax\r
+ jnz .exit\r
+\r
+ ; test if caller wanted results\r
+ mov r12, [rsp + first_variable_on_stack_offset ]\r
+ test r12, r12\r
+ jz .exit\r
+ mov [r12 + 0 ], rcx\r
+ mov [r12 + 8 ], rdx\r
+ mov [r12 + 16], r8\r
+ mov [r12 + 24], r9\r
+ mov [r12 + 32], r10\r
+ mov [r12 + 40], r11\r
+.exit:\r
+ tdcall_pop_regs\r
+ ret\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2020-2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Register/Intel/Cpuid.h>\r
+\r
+/**\r
+ Probe if TD is enabled.\r
+\r
+ @return TRUE TD is enabled.\r
+ @return FALSE TD is not enabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdIsEnabled (\r
+ )\r
+{\r
+ UINT32 Eax;\r
+ UINT32 Ebx;\r
+ UINT32 Ecx;\r
+ UINT32 Edx;\r
+ UINT32 LargestEax;\r
+ BOOLEAN TdEnabled;\r
+ CPUID_VERSION_INFO_ECX CpuIdVersionInfoEcx;\r
+\r
+ TdEnabled = FALSE;\r
+\r
+ do {\r
+ AsmCpuid (CPUID_SIGNATURE, &LargestEax, &Ebx, &Ecx, &Edx);\r
+\r
+ if ( (Ebx != CPUID_SIGNATURE_GENUINE_INTEL_EBX)\r
+ || (Edx != CPUID_SIGNATURE_GENUINE_INTEL_EDX)\r
+ || (Ecx != CPUID_SIGNATURE_GENUINE_INTEL_ECX))\r
+ {\r
+ break;\r
+ }\r
+\r
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &CpuIdVersionInfoEcx.Uint32, NULL);\r
+ if (CpuIdVersionInfoEcx.Bits.ParaVirtualized == 0) {\r
+ break;\r
+ }\r
+\r
+ if (LargestEax < CPUID_GUESTTD_RUNTIME_ENVIRONMENT) {\r
+ break;\r
+ }\r
+\r
+ AsmCpuidEx (CPUID_GUESTTD_RUNTIME_ENVIRONMENT, 0, &Eax, &Ebx, &Ecx, &Edx);\r
+ if ( (Ebx != CPUID_GUESTTD_SIGNATURE_GENUINE_INTEL_EBX)\r
+ || (Edx != CPUID_GUESTTD_SIGNATURE_GENUINE_INTEL_EDX)\r
+ || (Ecx != CPUID_GUESTTD_SIGNATURE_GENUINE_INTEL_ECX))\r
+ {\r
+ break;\r
+ }\r
+\r
+ TdEnabled = TRUE;\r
+ } while (FALSE);\r
+\r
+ return TdEnabled;\r
+}\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+;* SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;*\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+DEFAULT REL\r
+SECTION .text\r
+\r
+%define TDVMCALL_EXPOSE_REGS_MASK 0xffec\r
+%define TDVMCALL 0x0\r
+\r
+%macro tdcall 0\r
+ db 0x66,0x0f,0x01,0xcc\r
+%endmacro\r
+\r
+%macro tdcall_push_regs 0\r
+ push rbp\r
+ mov rbp, rsp\r
+ push r15\r
+ push r14\r
+ push r13\r
+ push r12\r
+ push rbx\r
+ push rsi\r
+ push rdi\r
+%endmacro\r
+\r
+%macro tdcall_pop_regs 0\r
+ pop rdi\r
+ pop rsi\r
+ pop rbx\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+ pop rbp\r
+%endmacro\r
+\r
+%define number_of_regs_pushed 8\r
+%define number_of_parameters 4\r
+\r
+;\r
+; Keep these in sync for push_regs/pop_regs, code below\r
+; uses them to find 5th or greater parameters\r
+;\r
+%define first_variable_on_stack_offset \\r
+ ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)\r
+%define second_variable_on_stack_offset \\r
+ ((first_variable_on_stack_offset) + 8)\r
+\r
+%macro tdcall_regs_preamble 2\r
+ mov rax, %1\r
+\r
+ xor rcx, rcx\r
+ mov ecx, %2\r
+\r
+ ; R10 = 0 (standard TDVMCALL)\r
+\r
+ xor r10d, r10d\r
+\r
+ ; Zero out unused (for standard TDVMCALL) registers to avoid leaking\r
+ ; secrets to the VMM.\r
+\r
+ xor ebx, ebx\r
+ xor esi, esi\r
+ xor edi, edi\r
+\r
+ xor edx, edx\r
+ xor ebp, ebp\r
+ xor r8d, r8d\r
+ xor r9d, r9d\r
+%endmacro\r
+\r
+%macro tdcall_regs_postamble 0\r
+ xor ebx, ebx\r
+ xor esi, esi\r
+ xor edi, edi\r
+\r
+ xor ecx, ecx\r
+ xor edx, edx\r
+ xor r8d, r8d\r
+ xor r9d, r9d\r
+ xor r10d, r10d\r
+ xor r11d, r11d\r
+%endmacro\r
+\r
+;------------------------------------------------------------------------------\r
+; 0 => RAX = TDCALL leaf\r
+; M => RCX = TDVMCALL register behavior\r
+; 1 => R10 = standard vs. vendor\r
+; RDI => R11 = TDVMCALL function / nr\r
+; RSI = R12 = p1\r
+; RDX => R13 = p2\r
+; RCX => R14 = p3\r
+; R8 => R15 = p4\r
+\r
+; UINT64\r
+; EFIAPI\r
+; TdVmCall (\r
+; UINT64 Leaf, // Rcx\r
+; UINT64 P1, // Rdx\r
+; UINT64 P2, // R8\r
+; UINT64 P3, // R9\r
+; UINT64 P4, // rsp + 0x28\r
+; UINT64 *Val // rsp + 0x30\r
+; )\r
+global ASM_PFX(TdVmCall)\r
+ASM_PFX(TdVmCall):\r
+ tdcall_push_regs\r
+\r
+ mov r11, rcx\r
+ mov r12, rdx\r
+ mov r13, r8\r
+ mov r14, r9\r
+ mov r15, [rsp + first_variable_on_stack_offset ]\r
+\r
+ tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK\r
+\r
+ tdcall\r
+\r
+ ; ignore return dataif TDCALL reports failure.\r
+ test rax, rax\r
+ jnz .no_return_data\r
+\r
+ ; Propagate TDVMCALL success/failure to return value.\r
+ mov rax, r10\r
+\r
+ ; Retrieve the Val pointer.\r
+ mov r9, [rsp + second_variable_on_stack_offset ]\r
+ test r9, r9\r
+ jz .no_return_data\r
+\r
+ ; On success, propagate TDVMCALL output value to output param\r
+ test rax, rax\r
+ jnz .no_return_data\r
+ mov [r9], r11\r
+.no_return_data:\r
+ tdcall_regs_postamble\r
+\r
+ tdcall_pop_regs\r
+\r
+ ret\r