]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdePkg: Introduce basic Tdx functions in BaseLib
authorMin Xu <min.m.xu@intel.com>
Wed, 10 Nov 2021 01:00:41 +0000 (09:00 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sat, 2 Apr 2022 08:15:12 +0000 (08:15 +0000)
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

Introduce basic Tdx functions in BaseLib:
 - TdCall ()
 - TdVmCall ()
 - TdIsEnabled ()

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
MdePkg/Include/Library/BaseLib.h
MdePkg/Library/BaseLib/BaseLib.inf
MdePkg/Library/BaseLib/IntelTdxNull.c [new file with mode: 0644]
MdePkg/Library/BaseLib/X64/TdCall.nasm [new file with mode: 0644]
MdePkg/Library/BaseLib/X64/TdProbe.c [new file with mode: 0644]
MdePkg/Library/BaseLib/X64/TdVmcall.nasm [new file with mode: 0644]

index 6aa0d972186e2101ca2b790caab3b6df03661c9d..9d58a7c4ad13e5a9eb240639370e3f964156e9c6 100644 (file)
@@ -4759,6 +4759,72 @@ SpeculationBarrier (
   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
index cebda3b210c1fe1bd73fd02e6e0fbe96d335faf0..16b7ac3917054f8001bfd6b0a1e8e31dd668bfdc 100644 (file)
   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
diff --git a/MdePkg/Library/BaseLib/IntelTdxNull.c b/MdePkg/Library/BaseLib/IntelTdxNull.c
new file mode 100644 (file)
index 0000000..ec95470
--- /dev/null
@@ -0,0 +1,83 @@
+/** @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
diff --git a/MdePkg/Library/BaseLib/X64/TdCall.nasm b/MdePkg/Library/BaseLib/X64/TdCall.nasm
new file mode 100644 (file)
index 0000000..e8a094b
--- /dev/null
@@ -0,0 +1,85 @@
+;------------------------------------------------------------------------------\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
diff --git a/MdePkg/Library/BaseLib/X64/TdProbe.c b/MdePkg/Library/BaseLib/X64/TdProbe.c
new file mode 100644 (file)
index 0000000..b893c0a
--- /dev/null
@@ -0,0 +1,63 @@
+/** @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
diff --git a/MdePkg/Library/BaseLib/X64/TdVmcall.nasm b/MdePkg/Library/BaseLib/X64/TdVmcall.nasm
new file mode 100644 (file)
index 0000000..5ecc10b
--- /dev/null
@@ -0,0 +1,145 @@
+;------------------------------------------------------------------------------\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