[edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations

Min Xu posted 28 patches 4 years, 4 months ago
There is a newer version of this series
[edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations
Posted by Min Xu 4 years, 4 months ago
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

TdxLib is created with functions to perform the related Tdx operation.
This includes functions for:
 - TdCall          : Cause a VM exit to the Intel TDX module.
 - TdVmCall        : It helps invoke services from the host VMM to pass/
                     receive information.
 - TdVmCallCpuid   : Enable the TD guest to request VMM to emulate CPUID
 - TdAcceptPages   : Accept pending private pages and initialize the pages
                     to all-0 using the TD ephemeral private key.
 - TdExtendRtmr    : Extend measurement to one of the RTMR registers.
 - TdSharedPageMask: Get the Td guest shared page mask which indicates it
                     is a Shared or Private page.
 - TdMaxVCpuNum    : Get the maximum number of virtual CPUs.
 - TdVCpuNum       : Get the number of virtual CPUs.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 MdePkg/Include/Library/TdxLib.h         | 167 +++++++++++++++++++
 MdePkg/Library/TdxLib/AcceptPages.c     | 136 ++++++++++++++++
 MdePkg/Library/TdxLib/Rtmr.c            | 118 ++++++++++++++
 MdePkg/Library/TdxLib/TdInfo.c          | 103 ++++++++++++
 MdePkg/Library/TdxLib/TdxLib.inf        |  39 +++++
 MdePkg/Library/TdxLib/TdxLibNull.c      | 192 ++++++++++++++++++++++
 MdePkg/Library/TdxLib/X64/Tdcall.nasm   |  85 ++++++++++
 MdePkg/Library/TdxLib/X64/Tdvmcall.nasm | 207 ++++++++++++++++++++++++
 MdePkg/MdePkg.dec                       |   3 +
 MdePkg/MdePkg.dsc                       |   1 +
 10 files changed, 1051 insertions(+)
 create mode 100644 MdePkg/Include/Library/TdxLib.h
 create mode 100644 MdePkg/Library/TdxLib/AcceptPages.c
 create mode 100644 MdePkg/Library/TdxLib/Rtmr.c
 create mode 100644 MdePkg/Library/TdxLib/TdInfo.c
 create mode 100644 MdePkg/Library/TdxLib/TdxLib.inf
 create mode 100644 MdePkg/Library/TdxLib/TdxLibNull.c
 create mode 100644 MdePkg/Library/TdxLib/X64/Tdcall.nasm
 create mode 100644 MdePkg/Library/TdxLib/X64/Tdvmcall.nasm

diff --git a/MdePkg/Include/Library/TdxLib.h b/MdePkg/Include/Library/TdxLib.h
new file mode 100644
index 000000000000..43a7d709657e
--- /dev/null
+++ b/MdePkg/Include/Library/TdxLib.h
@@ -0,0 +1,167 @@
+/** @file
+  TdxLib definitions
+
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TDX_LIB_H_
+#define TDX_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/DebugSupport.h>
+
+/**
+  This function accepts a pending private page, and initialize the page to
+  all-0 using the TD ephemeral private key.
+
+  @param[in]  StartAddress     Guest physical address of the private page
+                               to accept.
+  @param[in]  NumberOfPages    Number of the pages to be accepted.
+  @param[in]  PageSize         GPA page size. Accept 2M/4K page size.
+
+  @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TdAcceptPages (
+  IN UINT64  StartAddress,
+  IN UINT64  NumberOfPages,
+  IN UINT64  PageSize
+  );
+
+/**
+  This function extends one of the RTMR measurement register
+  in TDCS with the provided extension data in memory.
+  RTMR extending supports SHA384 which length is 48 bytes.
+
+  @param[in]  Data      Point to the data to be extended
+  @param[in]  DataLen   Length of the data. Must be 48
+  @param[in]  Index     RTMR index
+
+  @return EFI_SUCCESS
+  @return EFI_INVALID_PARAMETER
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+TdExtendRtmr (
+  IN  UINT32  *Data,
+  IN  UINT32  DataLen,
+  IN  UINT8   Index
+  );
+
+
+/**
+  This function gets the Td guest shared page mask.
+
+  The guest indicates if a page is shared using the Guest Physical Address
+  (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.
+  If the GPAW is 52, the S-bit is bit-51.
+
+  @return Shared page bit mask
+**/
+UINT64
+EFIAPI
+TdSharedPageMask (
+  VOID
+  );
+
+/**
+  This function gets the maximum number of Virtual CPUs that are usable for
+  Td Guest.
+
+  @return maximum Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdMaxVCpuNum (
+  VOID
+  );
+
+/**
+  This function gets the number of Virtual CPUs that are usable for Td
+  Guest.
+
+  @return Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdVCpuNum (
+  VOID
+  );
+
+
+/**
+  The TDCALL instruction causes a VM exit to the Intel TDX module.  It is
+  used to call guest-side Intel TDX functions, either local or a TD exit
+  to the host VMM, as selected by Leaf.
+
+  @param[in]      Leaf        Leaf number of TDCALL instruction
+  @param[in]      Arg1        Arg1
+  @param[in]      Arg2        Arg2
+  @param[in]      Arg3        Arg3
+  @param[in,out]  Results  Returned result of the Leaf function
+
+  @return EFI_SUCCESS
+  @return Other           See individual leaf functions
+**/
+EFI_STATUS
+EFIAPI
+TdCall (
+  IN UINT64           Leaf,
+  IN UINT64           Arg1,
+  IN UINT64           Arg2,
+  IN UINT64           Arg3,
+  IN OUT VOID         *Results
+  );
+
+/**
+  TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from the
+  host VMM to pass/receive information.
+
+  @param[in]     Leaf        Number of sub-functions
+  @param[in]     Arg1        Arg1
+  @param[in]     Arg2        Arg2
+  @param[in]     Arg3        Arg3
+  @param[in]     Arg4        Arg4
+  @param[in,out] Results     Returned result of the sub-function
+
+  @return EFI_SUCCESS
+  @return Other           See individual sub-functions
+
+**/
+EFI_STATUS
+EFIAPI
+TdVmCall (
+  IN UINT64          Leaf,
+  IN UINT64          Arg1,
+  IN UINT64          Arg2,
+  IN UINT64          Arg3,
+  IN UINT64          Arg4,
+  IN OUT VOID        *Results
+  );
+
+/**
+  This function enable the TD guest to request the VMM to emulate CPUID
+  operation, especially for non-architectural, CPUID leaves.
+
+  @param[in]  Eax        Main leaf of the CPUID
+  @param[in]  Ecx        Sub-leaf of the CPUID
+  @param[out] Results    Returned result of CPUID operation
+
+  @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TdVmCallCpuid (
+  IN UINT64         Eax,
+  IN UINT64         Ecx,
+  OUT VOID          *Results
+  );
+
+#endif
diff --git a/MdePkg/Library/TdxLib/AcceptPages.c b/MdePkg/Library/TdxLib/AcceptPages.c
new file mode 100644
index 000000000000..8941dc05b114
--- /dev/null
+++ b/MdePkg/Library/TdxLib/AcceptPages.c
@@ -0,0 +1,136 @@
+/** @file
+
+  Unaccepted memory is a special type of private memory. In Td guest
+  TDCALL [TDG.MEM.PAGE.ACCEPT] is invoked to accept the unaccepted
+  memory before use it.
+
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Tdx.h>
+#include <Library/TdxLib.h>
+#include <Library/BaseMemoryLib.h>
+
+UINT64  mNumberOfDuplicatedAcceptedPages;
+
+// PageSize is mapped to PageLevel like below:
+// 4KB - 0, 2MB - 1
+UINT64  mTdxAcceptPageLevelMap[2] = {
+  SIZE_4KB,
+  SIZE_2MB
+};
+
+/**
+  This function gets the PageLevel according to the input page size.
+
+  @param[in]  PageSize    Page size
+
+  @return UINTN           The mapped page level
+**/
+UINTN
+GetGpaPageLevel (
+  UINT64 PageSize
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdxAcceptPageLevelMap[0]); Index++) {
+    if (mTdxAcceptPageLevelMap[Index] == PageSize) {
+      break;
+    }
+  }
+
+  return Index;
+}
+
+/**
+  This function accept a pending private page, and initialize the page to
+  all-0 using the TD ephemeral private key.
+
+  Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return
+  TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel is
+  not workable. In this case we need to try to fallback to a smaller
+  PageLevel if possible.
+
+  @param[in]  StartAddress      Guest physical address of the private
+                                page to accept.
+  @param[in]  NumberOfPages     Number of the pages to be accepted.
+  @param[in]  PageSize          GPA page size. Only accept 1G/2M/4K size.
+
+  @return EFI_SUCCESS           Accept successfully
+  @return others                Indicate other errors
+**/
+EFI_STATUS
+EFIAPI
+TdAcceptPages (
+  IN UINT64  StartAddress,
+  IN UINT64  NumberOfPages,
+  IN UINT64  PageSize
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Address;
+  UINT64      TdxStatus;
+  UINT64      Index;
+  UINT64      GpaPageLevel;
+  UINT64      PageSize2;
+
+  Address = StartAddress;
+
+  GpaPageLevel = (UINT64) GetGpaPageLevel (PageSize);
+  if (GpaPageLevel > sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdxAcceptPageLevelMap[0])) {
+    DEBUG ((DEBUG_ERROR, "Accept page size must be 4K/2M. Invalid page size - 0x%llx\n", PageSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EFI_SUCCESS;
+  for (Index = 0; Index < NumberOfPages; Index++) {
+    TdxStatus = TdCall (TDCALL_TDACCEPTPAGE, Address | GpaPageLevel, 0, 0, 0);
+    if (TdxStatus != TDX_EXIT_REASON_SUCCESS) {
+        if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED) {
+          //
+          // Already accepted
+          //
+          mNumberOfDuplicatedAcceptedPages++;
+        } else if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_PAGE_SIZE_MISMATCH) {
+          //
+          // GpaPageLevel is mismatch, fall back to a smaller GpaPageLevel if possible
+          //
+          DEBUG ((DEBUG_VERBOSE, "Address %llx cannot be accepted in PageLevel of %d\n", Address, GpaPageLevel));
+
+          if (GpaPageLevel == 0) {
+            //
+            // Cannot fall back to smaller page level
+            //
+            DEBUG ((DEBUG_ERROR, "AcceptPage cannot fallback from PageLevel %d\n", GpaPageLevel));
+            Status = EFI_INVALID_PARAMETER;
+            break;
+          } else {
+            //
+            // Fall back to a smaller page size
+            //
+            PageSize2 = mTdxAcceptPageLevelMap [GpaPageLevel - 1];
+            Status = TdAcceptPages(Address, 512, PageSize2);
+            if (EFI_ERROR (Status)) {
+              break;
+            }
+          }
+        }else {
+
+          //
+          // Other errors
+          //
+          DEBUG ((DEBUG_ERROR, "Address %llx (%d) failed to be accepted. Error = 0x%llx\n",
+            Address, Index, TdxStatus));
+          Status = EFI_INVALID_PARAMETER;
+          break;
+        }
+    }
+    Address += PageSize;
+  }
+  return Status;
+}
diff --git a/MdePkg/Library/TdxLib/Rtmr.c b/MdePkg/Library/TdxLib/Rtmr.c
new file mode 100644
index 000000000000..c86902ae21bc
--- /dev/null
+++ b/MdePkg/Library/TdxLib/Rtmr.c
@@ -0,0 +1,118 @@
+/** @file
+
+  Extends one of the RTMR measurement registers in TDCS with the provided
+  extension data in memory.
+
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TdxLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/Tdx.h>
+
+#define RTMR_COUNT                  4
+#define TD_EXTEND_BUFFER_LEN        (64 + 64)
+#define EXTEND_BUFFER_ADDRESS_MASK  0x3f
+
+
+#pragma pack(16)
+typedef struct {
+  UINT8   Buffer[TD_EXTEND_BUFFER_LEN];
+} TDX_EXTEND_BUFFER;
+#pragma pack()
+
+UINT8               *mExtendBufferAddress = NULL;
+TDX_EXTEND_BUFFER   mExtendBuffer;
+
+/**
+  TD.RTMR.EXTEND requires 64B-aligned guest physical address of
+  48B-extension data. In runtime we walk thru the Buffer to find
+  out a 64B-aligned start address.
+
+  @return Start address of the extend buffer
+
+**/
+UINT8 *
+EFIAPI
+GetExtendBuffer (
+  VOID
+  )
+{
+  UINT8     *ExtendBufferAddress;
+  UINT64    Gap;
+
+  if (mExtendBufferAddress != NULL) {
+    return mExtendBufferAddress;
+  }
+
+  ExtendBufferAddress = mExtendBuffer.Buffer;
+
+  Gap = 0x40 - ((UINT64)(UINTN)ExtendBufferAddress & EXTEND_BUFFER_ADDRESS_MASK);
+  mExtendBufferAddress = (UINT8*)((UINT64)(UINTN)ExtendBufferAddress + Gap);
+
+  DEBUG ((DEBUG_VERBOSE, "ExtendBufferAddress: 0x%p, Gap: 0x%x\n", ExtendBufferAddress, Gap));
+  DEBUG ((DEBUG_VERBOSE, "mExtendBufferAddress: 0x%p\n", mExtendBufferAddress));
+
+  ASSERT (mExtendBufferAddress + 64 <= ExtendBufferAddress + TD_EXTEND_BUFFER_LEN);
+
+  return mExtendBufferAddress;
+}
+
+
+/**
+  This function extends one of the RTMR measurement register
+  in TDCS with the provided extension data in memory.
+  RTMR extending supports SHA384 which length is 48 bytes.
+
+  @param[in]  Data      Point to the data to be extended
+  @param[in]  DataLen   Length of the data. Must be 48
+  @param[in]  Index     RTMR index
+
+  @return EFI_SUCCESS
+  @return EFI_INVALID_PARAMETER
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+TdExtendRtmr (
+  IN  UINT32  *Data,
+  IN  UINT32  DataLen,
+  IN  UINT8   Index
+  )
+{
+  EFI_STATUS            Status;
+  UINT64                TdCallStatus;
+  UINT8                 *ExtendBuffer;
+
+  Status = EFI_SUCCESS;
+
+  ASSERT (Index >= 0 && Index < RTMR_COUNT);
+  ASSERT (DataLen == SHA384_DIGEST_SIZE);
+
+  ExtendBuffer = GetExtendBuffer();
+  ASSERT (ExtendBuffer != NULL);
+  ZeroMem (ExtendBuffer, SHA384_DIGEST_SIZE);
+  CopyMem (ExtendBuffer, Data, SHA384_DIGEST_SIZE);
+
+  TdCallStatus = TdCall (TDCALL_TDEXTENDRTMR, (UINT64)(UINTN)ExtendBuffer, Index, 0, 0);
+
+  if (TdCallStatus == TDX_EXIT_REASON_SUCCESS) {
+    Status = EFI_SUCCESS;
+  } else if (TdCallStatus == TDX_EXIT_REASON_OPERAND_INVALID) {
+    Status = EFI_INVALID_PARAMETER;
+  } else {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "Error returned from TdExtendRtmr call - 0x%lx\n", TdCallStatus));
+  }
+
+  return Status;
+}
diff --git a/MdePkg/Library/TdxLib/TdInfo.c b/MdePkg/Library/TdxLib/TdInfo.c
new file mode 100644
index 000000000000..56c268e70c8d
--- /dev/null
+++ b/MdePkg/Library/TdxLib/TdInfo.c
@@ -0,0 +1,103 @@
+/** @file
+
+  Fetch the Tdx info.
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Tdx.h>
+#include <Library/TdxLib.h>
+#include <Library/BaseMemoryLib.h>
+
+UINT64  mTdSharedPageMask = 0;
+UINT32  mTdMaxVCpuNum     = 0;
+UINT32  mTdVCpuNum        = 0;
+
+/**
+  This function gets the Td guest shared page mask.
+
+  The guest indicates if a page is shared using the Guest Physical Address
+  (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.
+  If the GPAW is 52, the S-bit is bit-51.
+
+  @return Shared page bit mask
+**/
+UINT64
+EFIAPI
+TdSharedPageMask (
+  VOID
+  )
+{
+  UINT64                      Status;
+  UINT8                       Gpaw;
+  TD_RETURN_DATA              TdReturnData;
+
+  if (mTdSharedPageMask != 0) {
+    return mTdSharedPageMask;
+  }
+
+  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
+  ASSERT (Status == TDX_EXIT_REASON_SUCCESS);
+
+  Gpaw = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);
+  ASSERT(Gpaw == 48 || Gpaw == 52);
+  mTdSharedPageMask = 1ULL << (Gpaw - 1);
+  return mTdSharedPageMask;
+}
+
+/**
+  This function gets the maximum number of Virtual CPUs that are usable for
+  Td Guest.
+
+  @return maximum Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdMaxVCpuNum (
+  VOID
+  )
+{
+  UINT64                      Status;
+  TD_RETURN_DATA              TdReturnData;
+
+  if (mTdMaxVCpuNum != 0) {
+    return mTdMaxVCpuNum;
+  }
+
+  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
+  ASSERT (Status == TDX_EXIT_REASON_SUCCESS);
+
+  mTdMaxVCpuNum = TdReturnData.TdInfo.MaxVcpus;
+
+  return mTdMaxVCpuNum;
+}
+
+/**
+  This function gets the number of Virtual CPUs that are usable for Td
+  Guest.
+
+  @return Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdVCpuNum (
+  VOID
+  )
+{
+  UINT64                      Status;
+  TD_RETURN_DATA              TdReturnData;
+
+  if (mTdVCpuNum != 0) {
+    return mTdVCpuNum;
+  }
+
+  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
+  ASSERT (Status == TDX_EXIT_REASON_SUCCESS);
+
+  mTdVCpuNum = TdReturnData.TdInfo.NumVcpus;
+  return mTdVCpuNum;
+}
diff --git a/MdePkg/Library/TdxLib/TdxLib.inf b/MdePkg/Library/TdxLib/TdxLib.inf
new file mode 100644
index 000000000000..772abcc49d8b
--- /dev/null
+++ b/MdePkg/Library/TdxLib/TdxLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Tdx library
+#
+#  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = TdxLib
+  FILE_GUID                      = 032A8E0D-0C27-40C0-9CAA-23B731C1B223
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TdxLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.IA32]
+  TdxLibNull.c
+
+[Sources.X64]
+  AcceptPages.c
+  Rtmr.c
+  TdInfo.c
+  X64/Tdcall.nasm
+  X64/Tdvmcall.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
diff --git a/MdePkg/Library/TdxLib/TdxLibNull.c b/MdePkg/Library/TdxLib/TdxLibNull.c
new file mode 100644
index 000000000000..5a8f19c6d8d2
--- /dev/null
+++ b/MdePkg/Library/TdxLib/TdxLibNull.c
@@ -0,0 +1,192 @@
+/** @file
+
+  Null stub of TdxLib
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TdxLib.h>
+
+/**
+  This function accepts a pending private page, and initialize the page to
+  all-0 using the TD ephemeral private key.
+
+  @param[in]  StartAddress     Guest physical address of the private page
+                               to accept.
+  @param[in]  NumberOfPages    Number of the pages to be accepted.
+  @param[in]  PageSize         GPA page size. Accept 1G/2M/4K page size.
+
+  @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TdAcceptPages (
+  IN UINT64  StartAddress,
+  IN UINT64  NumberOfPages,
+  IN UINT64  PageSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This function extends one of the RTMR measurement register
+  in TDCS with the provided extension data in memory.
+  RTMR extending supports SHA384 which length is 48 bytes.
+
+  @param[in]  Data      Point to the data to be extended
+  @param[in]  DataLen   Length of the data. Must be 48
+  @param[in]  Index     RTMR index
+
+  @return EFI_SUCCESS
+  @return EFI_INVALID_PARAMETER
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+TdExtendRtmr (
+  IN  UINT32  *Data,
+  IN  UINT32  DataLen,
+  IN  UINT8   Index
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  This function gets the Td guest shared page mask.
+
+  The guest indicates if a page is shared using the Guest Physical Address
+  (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.
+  If the GPAW is 52, the S-bit is bit-51.
+
+  @return Shared page bit mask
+**/
+UINT64
+EFIAPI
+TdSharedPageMask (
+  VOID
+  )
+{
+  return 0;
+}
+
+
+/**
+  This function gets the maximum number of Virtual CPUs that are usable for
+  Td Guest.
+
+  @return maximum Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdMaxVCpuNum (
+  VOID
+  )
+{
+  return 0;
+}
+
+
+/**
+  This function gets the number of Virtual CPUs that are usable for Td
+  Guest.
+
+  @return Virtual CPUs number
+**/
+UINT32
+EFIAPI
+TdVCpuNum (
+  VOID
+  )
+{
+  return 0;
+}
+
+
+/**
+  The TDCALL instruction causes a VM exit to the Intel TDX module.  It is
+  used to call guest-side Intel TDX functions, either local or a TD exit
+  to the host VMM, as selected by Leaf.
+  Leaf functions are described at <https://software.intel.com/content/
+  www/us/en/develop/articles/intel-trust-domain-extensions.html>
+
+  @param[in]      Leaf        Leaf number of TDCALL instruction
+  @param[in]      Arg1        Arg1
+  @param[in]      Arg2        Arg2
+  @param[in]      Arg3        Arg3
+  @param[in,out]  Results  Returned result of the Leaf function
+
+  @return EFI_SUCCESS
+  @return Other           See individual leaf functions
+**/
+EFI_STATUS
+EFIAPI
+TdCall (
+  IN UINT64           Leaf,
+  IN UINT64           Arg1,
+  IN UINT64           Arg2,
+  IN UINT64           Arg3,
+  IN OUT VOID         *Results
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from the
+  host VMM to pass/receive information.
+
+  @param[in]     Leaf        Number of sub-functions
+  @param[in]     Arg1        Arg1
+  @param[in]     Arg2        Arg2
+  @param[in]     Arg3        Arg3
+  @param[in]     Arg4        Arg4
+  @param[in,out] Results     Returned result of the sub-function
+
+  @return EFI_SUCCESS
+  @return Other           See individual sub-functions
+
+**/
+EFI_STATUS
+EFIAPI
+TdVmCall (
+  IN UINT64          Leaf,
+  IN UINT64          Arg1,
+  IN UINT64          Arg2,
+  IN UINT64          Arg3,
+  IN UINT64          Arg4,
+  IN OUT VOID        *Results
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  This function enable the TD guest to request the VMM to emulate CPUID
+  operation, especially for non-architectural, CPUID leaves.
+
+  @param[in]  Eax        Main leaf of the CPUID
+  @param[in]  Ecx        Sub-leaf of the CPUID
+  @param[out] Results    Returned result of CPUID operation
+
+  @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TdVmCallCpuid (
+  IN UINT64         Eax,
+  IN UINT64         Ecx,
+  OUT VOID          *Results
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/MdePkg/Library/TdxLib/X64/Tdcall.nasm b/MdePkg/Library/TdxLib/X64/Tdcall.nasm
new file mode 100644
index 000000000000..e8a094b0eb3f
--- /dev/null
+++ b/MdePkg/Library/TdxLib/X64/Tdcall.nasm
@@ -0,0 +1,85 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+;* SPDX-License-Identifier: BSD-2-Clause-Patent
+;*
+;*
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+%macro tdcall 0
+    db 0x66,0x0f,0x01,0xcc
+%endmacro
+
+%macro tdcall_push_regs 0
+    push rbp
+    mov  rbp, rsp
+    push r15
+    push r14
+    push r13
+    push r12
+    push rbx
+    push rsi
+    push rdi
+%endmacro
+
+%macro tdcall_pop_regs 0
+    pop rdi
+    pop rsi
+    pop rbx
+    pop r12
+    pop r13
+    pop r14
+    pop r15
+    pop rbp
+%endmacro
+
+%define number_of_regs_pushed 8
+%define number_of_parameters  4
+
+;
+; Keep these in sync for push_regs/pop_regs, code below
+; uses them to find 5th or greater parameters
+;
+%define first_variable_on_stack_offset \
+  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)
+%define second_variable_on_stack_offset \
+  ((first_variable_on_stack_offset) + 8)
+
+;  TdCall (
+;    UINT64  Leaf,    // Rcx
+;    UINT64  P1,      // Rdx
+;    UINT64  P2,      // R8
+;    UINT64  P3,      // R9
+;    UINT64  Results, // rsp + 0x28
+;    )
+global ASM_PFX(TdCall)
+ASM_PFX(TdCall):
+       tdcall_push_regs
+
+       mov rax, rcx
+       mov rcx, rdx
+       mov rdx, r8
+       mov r8, r9
+
+       tdcall
+
+       ; exit if tdcall reports failure.
+       test rax, rax
+       jnz .exit
+
+       ; test if caller wanted results
+       mov r12, [rsp + first_variable_on_stack_offset ]
+       test r12, r12
+       jz .exit
+       mov [r12 + 0 ], rcx
+       mov [r12 + 8 ], rdx
+       mov [r12 + 16], r8
+       mov [r12 + 24], r9
+       mov [r12 + 32], r10
+       mov [r12 + 40], r11
+.exit:
+       tdcall_pop_regs
+       ret
diff --git a/MdePkg/Library/TdxLib/X64/Tdvmcall.nasm b/MdePkg/Library/TdxLib/X64/Tdvmcall.nasm
new file mode 100644
index 000000000000..eb1cb967dc29
--- /dev/null
+++ b/MdePkg/Library/TdxLib/X64/Tdvmcall.nasm
@@ -0,0 +1,207 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+;* SPDX-License-Identifier: BSD-2-Clause-Patent
+;*
+;*
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+%define TDVMCALL_EXPOSE_REGS_MASK       0xffec
+%define TDVMCALL                        0x0
+%define EXIT_REASON_CPUID               0xa
+
+%macro tdcall 0
+    db 0x66,0x0f,0x01,0xcc
+%endmacro
+
+%macro tdcall_push_regs 0
+    push rbp
+    mov  rbp, rsp
+    push r15
+    push r14
+    push r13
+    push r12
+    push rbx
+    push rsi
+    push rdi
+%endmacro
+
+%macro tdcall_pop_regs 0
+    pop rdi
+    pop rsi
+    pop rbx
+    pop r12
+    pop r13
+    pop r14
+    pop r15
+    pop rbp
+%endmacro
+
+%define number_of_regs_pushed 8
+%define number_of_parameters  4
+
+;
+; Keep these in sync for push_regs/pop_regs, code below
+; uses them to find 5th or greater parameters
+;
+%define first_variable_on_stack_offset \
+  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)
+%define second_variable_on_stack_offset \
+  ((first_variable_on_stack_offset) + 8)
+
+%macro tdcall_regs_preamble 2
+    mov rax, %1
+
+    xor rcx, rcx
+    mov ecx, %2
+
+    ; R10 = 0 (standard TDVMCALL)
+
+    xor r10d, r10d
+
+    ; Zero out unused (for standard TDVMCALL) registers to avoid leaking
+    ; secrets to the VMM.
+
+    xor ebx, ebx
+    xor esi, esi
+    xor edi, edi
+
+    xor edx, edx
+    xor ebp, ebp
+    xor r8d, r8d
+    xor r9d, r9d
+%endmacro
+
+%macro tdcall_regs_postamble 0
+    xor ebx, ebx
+    xor esi, esi
+    xor edi, edi
+
+    xor ecx, ecx
+    xor edx, edx
+    xor r8d,  r8d
+    xor r9d,  r9d
+    xor r10d, r10d
+    xor r11d, r11d
+%endmacro
+
+;------------------------------------------------------------------------------
+; 0   => RAX = TDCALL leaf
+; M   => RCX = TDVMCALL register behavior
+; 1   => R10 = standard vs. vendor
+; RDI => R11 = TDVMCALL function / nr
+; RSI =  R12 = p1
+; RDX => R13 = p2
+; RCX => R14 = p3
+; R8  => R15 = p4
+
+;  UINT64
+;  EFIAPI
+;  TdVmCall (
+;    UINT64  Leaf,  // Rcx
+;    UINT64  P1,  // Rdx
+;    UINT64  P2,  // R8
+;    UINT64  P3,  // R9
+;    UINT64  P4,  // rsp + 0x28
+;    UINT64  *Val // rsp + 0x30
+;    )
+global ASM_PFX(TdVmCall)
+ASM_PFX(TdVmCall):
+       tdcall_push_regs
+
+       mov r11, rcx
+       mov r12, rdx
+       mov r13, r8
+       mov r14, r9
+       mov r15, [rsp + first_variable_on_stack_offset ]
+
+       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
+
+       tdcall
+
+       ; ignore return dataif TDCALL reports failure.
+       test rax, rax
+       jnz .no_return_data
+
+       ; Propagate TDVMCALL success/failure to return value.
+       mov rax, r10
+
+       ; Retrieve the Val pointer.
+       mov r9, [rsp + second_variable_on_stack_offset ]
+       test r9, r9
+       jz .no_return_data
+
+       ; On success, propagate TDVMCALL output value to output param
+       test rax, rax
+       jnz .no_return_data
+       mov [r9], r11
+.no_return_data:
+       tdcall_regs_postamble
+
+       tdcall_pop_regs
+
+       ret
+
+;------------------------------------------------------------------------------
+; 0   => RAX = TDCALL leaf
+; M   => RCX = TDVMCALL register behavior
+; 1   => R10 = standard vs. vendor
+; RDI => R11 = TDVMCALL function / nr
+; RSI =  R12 = p1
+; RDX => R13 = p2
+; RCX => R14 = p3
+; R8  => R15 = p4
+
+;  UINT64
+;  EFIAPI
+;  TdVmCallCpuid (
+;    UINT64  EaxIn,    // Rcx
+;    UINT64  EcxIn,    // Rdx
+;    UINT64  *Results  // R8
+;    )
+global ASM_PFX(TdVmCallCpuid)
+ASM_PFX(TdVmCallCpuid):
+       tdcall_push_regs
+
+       mov r11, EXIT_REASON_CPUID
+       mov r12, rcx
+       mov r13, rdx
+
+       ; Save *results pointers
+       push r8
+
+       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
+
+       tdcall
+
+       ; Panic if TDCALL reports failure.
+       test rax, rax
+       jnz .no_return_data
+
+       ; Propagate TDVMCALL success/failure to return value.
+       mov rax, r10
+       test rax, rax
+       jnz .no_return_data
+
+       ; Retrieve *Results
+       pop r8
+       test r8, r8
+       jz .no_return_data
+       ; Caller pass in buffer so store results r12-r15 contains eax-edx
+       mov [r8 +  0], r12
+       mov [r8 +  8], r13
+       mov [r8 + 16], r14
+       mov [r8 + 24], r15
+
+.no_return_data:
+       tdcall_regs_postamble
+
+       tdcall_pop_regs
+
+       ret
+
+.panic:
+       ud2
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 9cdc915ebae9..8b85f59e6dfb 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -296,6 +296,9 @@
   ##  @libraryclass  Provides services to log the SMI handler registration.
   SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h
 
+  ##  @libraryclass  Provides function to support TDX processing.
+  TdxLib|Include/Library/TdxLib.h
+
 [Guids]
   #
   # GUID defined in UEFI2.1/UEFI2.0/EFI1.1
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index a94959169b2f..d6a7af412be7 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -175,6 +175,7 @@
   MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
   MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
   MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
+  MdePkg/Library/TdxLib/TdxLib.inf
 
 [Components.EBC]
   MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-- 
2.29.2.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81477): https://edk2.groups.io/g/devel/message/81477
Mute This Topic: https://groups.io/mt/86085729/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations
Posted by Gerd Hoffmann 4 years, 3 months ago
> +// PageSize is mapped to PageLevel like below:
> +// 4KB - 0, 2MB - 1
> +UINT64  mTdxAcceptPageLevelMap[2] = {
> +  SIZE_4KB,
> +  SIZE_2MB

No 1G pages?

> +UINTN
> +GetGpaPageLevel (
> +  UINT64 PageSize

Uh, UINT32 is not enough?  Keep the door open for 512G pages?

> +{
> +  UINTN Index;
> +
> +  for (Index = 0; Index < sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdxAcceptPageLevelMap[0]); Index++) {

There is an ARRAY_SIZE() macro, no need to open code the sizeof() trick.

> +    if (mTdxAcceptPageLevelMap[Index] == PageSize) {
> +      break;
> +    }
> +  }
> +
> +  return Index;
> +}

No error handling (invalid PageSize) here?

> +/**
> +  This function accept a pending private page, and initialize the page to
> +  all-0 using the TD ephemeral private key.
> +
> +  Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return
> +  TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel is
> +  not workable. In this case we need to try to fallback to a smaller
> +  PageLevel if possible.
> +
> +  @param[in]  StartAddress      Guest physical address of the private
> +                                page to accept.
> +  @param[in]  NumberOfPages     Number of the pages to be accepted.
> +  @param[in]  PageSize          GPA page size. Only accept 1G/2M/4K size.
> +
> +  @return EFI_SUCCESS           Accept successfully
> +  @return others                Indicate other errors
> +**/
> +EFI_STATUS
> +EFIAPI
> +TdAcceptPages (
> +  IN UINT64  StartAddress,
> +  IN UINT64  NumberOfPages,
> +  IN UINT64  PageSize
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT64      Address;
> +  UINT64      TdxStatus;
> +  UINT64      Index;
> +  UINT64      GpaPageLevel;
> +  UINT64      PageSize2;
> +
> +  Address = StartAddress;
> +
> +  GpaPageLevel = (UINT64) GetGpaPageLevel (PageSize);

Why cast?

> +  if (GpaPageLevel > sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdxAcceptPageLevelMap[0])) {
> +    DEBUG ((DEBUG_ERROR, "Accept page size must be 4K/2M. Invalid page size - 0x%llx\n", PageSize));

Ah.  Errors are catched here.  Well, no.  The check is wrong,
it should be ">=" not ">".

Better would be GetGpaPageLevel explicitly returning a specific value
(for example -1) on error.

> +  Status = EFI_SUCCESS;
> +  for (Index = 0; Index < NumberOfPages; Index++) {
> +    TdxStatus = TdCall (TDCALL_TDACCEPTPAGE, Address | GpaPageLevel, 0, 0, 0);
> +    if (TdxStatus != TDX_EXIT_REASON_SUCCESS) {
> +        if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED) {
> +          //
> +          // Already accepted
> +          //
> +          mNumberOfDuplicatedAcceptedPages++;

Hmm.  When this happens we have a bug somewhere, right?
So should this be an assert()?
Or should we at least log the address?

> +#define RTMR_COUNT                  4
> +#define TD_EXTEND_BUFFER_LEN        (64 + 64)
> +#define EXTEND_BUFFER_ADDRESS_MASK  0x3f
> +
> +
> +#pragma pack(16)
> +typedef struct {
> +  UINT8   Buffer[TD_EXTEND_BUFFER_LEN];
> +} TDX_EXTEND_BUFFER;
> +#pragma pack()
> +
> +UINT8               *mExtendBufferAddress = NULL;
> +TDX_EXTEND_BUFFER   mExtendBuffer;
> +
> +/**
> +  TD.RTMR.EXTEND requires 64B-aligned guest physical address of
> +  48B-extension data. In runtime we walk thru the Buffer to find
> +  out a 64B-aligned start address.

Can't you just use __attribute__((aligned(64))) for that?

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81810): https://edk2.groups.io/g/devel/message/81810
Mute This Topic: https://groups.io/mt/86085729/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations
Posted by Min Xu 4 years, 3 months ago
On October 12, 2021 4:22 PM, Gerd Hoffmann wrote:
> > +// PageSize is mapped to PageLevel like below:
> > +// 4KB - 0, 2MB - 1
> > +UINT64  mTdxAcceptPageLevelMap[2] = {
> > +  SIZE_4KB,
> > +  SIZE_2MB
> 
> No 1G pages?
TDX: https://software.intel.com/content/dam/develop/external/us/en/documents/tdx-module-1.0-public-spec-v0.931.pdf 
Theoretically there are 3 AcceptPageSize (4KB/2MB/1GB). But currently only 4KB and 2MB are supported. See section 22.3.2.
> 
> > +UINTN
> > +GetGpaPageLevel (
> > +  UINT64 PageSize
> 
> Uh, UINT32 is not enough?  Keep the door open for 512G pages?
Thanks for reminder. UINT32 is enough. It will be updated in next version.
> 
> > +{
> > +  UINTN Index;
> > +
> > +  for (Index = 0; Index < sizeof (mTdxAcceptPageLevelMap) / sizeof
> > + (mTdxAcceptPageLevelMap[0]); Index++) {
> 
> There is an ARRAY_SIZE() macro, no need to open code the sizeof() trick.
Thanks for reminder. It will be updated in next version.
> 
> > +    if (mTdxAcceptPageLevelMap[Index] == PageSize) {
> > +      break;
> > +    }
> > +  }
> > +
> > +  return Index;
> > +}
> 
> No error handling (invalid PageSize) here?
> 
> > +/**
> > +  This function accept a pending private page, and initialize the
> > +page to
> > +  all-0 using the TD ephemeral private key.
> > +
> > +  Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return
> > + TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel
> > + is  not workable. In this case we need to try to fallback to a
> > + smaller  PageLevel if possible.
> > +
> > +  @param[in]  StartAddress      Guest physical address of the private
> > +                                page to accept.
> > +  @param[in]  NumberOfPages     Number of the pages to be accepted.
> > +  @param[in]  PageSize          GPA page size. Only accept 1G/2M/4K size.
> > +
> > +  @return EFI_SUCCESS           Accept successfully
> > +  @return others                Indicate other errors
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +TdAcceptPages (
> > +  IN UINT64  StartAddress,
> > +  IN UINT64  NumberOfPages,
> > +  IN UINT64  PageSize
> > +  )
> > +{
> > +  EFI_STATUS  Status;
> > +  UINT64      Address;
> > +  UINT64      TdxStatus;
> > +  UINT64      Index;
> > +  UINT64      GpaPageLevel;
> > +  UINT64      PageSize2;
> > +
> > +  Address = StartAddress;
> > +
> > +  GpaPageLevel = (UINT64) GetGpaPageLevel (PageSize);
> 
> Why cast?
Thanks for reminder. The cast is not needed. It will be updated in next version.
> 
> > +  if (GpaPageLevel > sizeof (mTdxAcceptPageLevelMap) / sizeof
> (mTdxAcceptPageLevelMap[0])) {
> > +    DEBUG ((DEBUG_ERROR, "Accept page size must be 4K/2M. Invalid
> > + page size - 0x%llx\n", PageSize));
> 
> Ah.  Errors are catched here.  Well, no.  The check is wrong, it should be ">=" not
> ">".
> 
> Better would be GetGpaPageLevel explicitly returning a specific value (for
> example -1) on error.
You're right. A dumb error ... It will be fixed in the next version.
> 
> > +  Status = EFI_SUCCESS;
> > +  for (Index = 0; Index < NumberOfPages; Index++) {
> > +    TdxStatus = TdCall (TDCALL_TDACCEPTPAGE, Address | GpaPageLevel, 0, 0,
> 0);
> > +    if (TdxStatus != TDX_EXIT_REASON_SUCCESS) {
> > +        if ((TdxStatus & ~0xFFFFULL) ==
> TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED) {
> > +          //
> > +          // Already accepted
> > +          //
> > +          mNumberOfDuplicatedAcceptedPages++;
> 
> Hmm.  When this happens we have a bug somewhere, right?
> So should this be an assert()?
> Or should we at least log the address?
ASSERT() is not necessary because the code can still run. But we should log the address which has been already accepted.
It  will be added in the next version.
> 
> > +#define RTMR_COUNT                  4
> > +#define TD_EXTEND_BUFFER_LEN        (64 + 64)
> > +#define EXTEND_BUFFER_ADDRESS_MASK  0x3f
> > +
> > +
> > +#pragma pack(16)
> > +typedef struct {
> > +  UINT8   Buffer[TD_EXTEND_BUFFER_LEN];
> > +} TDX_EXTEND_BUFFER;
> > +#pragma pack()
> > +
> > +UINT8               *mExtendBufferAddress = NULL;
> > +TDX_EXTEND_BUFFER   mExtendBuffer;
> > +
> > +/**
> > +  TD.RTMR.EXTEND requires 64B-aligned guest physical address of
> > +  48B-extension data. In runtime we walk thru the Buffer to find
> > +  out a 64B-aligned start address.
> 
> Can't you just use __attribute__((aligned(64))) for that?
> 
In the PoC of TDVF I had thought about it. But at last I gave up such solution. The reasons are:
1) OVMF/TDVF supports both GCC and VS2019 tool chain. __attribute__((aligned(64))) is for GCC. Its counterpart of VS2019 Tool chain is __declspec(align(x)).
2) There is the limitation of /ALIGN:32 in the build scripts which means aligned 64 exceeds  the /ALIGN 32, unless /ALIGN is updated to 64.
That's why the current solution is used.

Thanks!
Min



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81883): https://edk2.groups.io/g/devel/message/81883
Mute This Topic: https://groups.io/mt/86085729/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations
Posted by Gerd Hoffmann 4 years, 3 months ago
  Hi,

> > > +UINT8               *mExtendBufferAddress = NULL;
> > > +TDX_EXTEND_BUFFER   mExtendBuffer;
> > > +
> > > +/**
> > > +  TD.RTMR.EXTEND requires 64B-aligned guest physical address of
> > > +  48B-extension data. In runtime we walk thru the Buffer to find
> > > +  out a 64B-aligned start address.
> > 
> > Can't you just use __attribute__((aligned(64))) for that?
> > 
> In the PoC of TDVF I had thought about it. But at last I gave up such solution. The reasons are:
> 1) OVMF/TDVF supports both GCC and VS2019 tool chain. __attribute__((aligned(64))) is for GCC. Its counterpart of VS2019 Tool chain is __declspec(align(x)).
> 2) There is the limitation of /ALIGN:32 in the build scripts which means aligned 64 exceeds  the /ALIGN 32, unless /ALIGN is updated to 64.
> That's why the current solution is used.

MdePkg/Include/Base.h has a bunch of ALIGN_* macros to do the math for
you, which should simplify this alot.  I'd suggest to also drop the
mExtendBufferAddress and the function calculating it.  Just use the
macro instead when needed.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81943): https://edk2.groups.io/g/devel/message/81943
Mute This Topic: https://groups.io/mt/86085729/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations
Posted by Min Xu 4 years, 3 months ago
On October 14, 2021 1:30 PM, Gerd Hoffmann wrote:
> > > > +UINT8               *mExtendBufferAddress = NULL;
> > > > +TDX_EXTEND_BUFFER   mExtendBuffer;
> > > > +
> > > > +/**
> > > > +  TD.RTMR.EXTEND requires 64B-aligned guest physical address of
> > > > +  48B-extension data. In runtime we walk thru the Buffer to find
> > > > +  out a 64B-aligned start address.
> > >
> > > Can't you just use __attribute__((aligned(64))) for that?
> > >
> > In the PoC of TDVF I had thought about it. But at last I gave up such solution.
> The reasons are:
> > 1) OVMF/TDVF supports both GCC and VS2019 tool chain.
> __attribute__((aligned(64))) is for GCC. Its counterpart of VS2019 Tool chain
> is __declspec(align(x)).
> > 2) There is the limitation of /ALIGN:32 in the build scripts which means
> aligned 64 exceeds  the /ALIGN 32, unless /ALIGN is updated to 64.
> > That's why the current solution is used.
> 
> MdePkg/Include/Base.h has a bunch of ALIGN_* macros to do the math for
> you, which should simplify this alot.  I'd suggest to also drop the
> mExtendBufferAddress and the function calculating it.  Just use the macro
> instead when needed.
Thanks for reminder. It will be updated in the next version.

Thanks.
Min


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#82468): https://edk2.groups.io/g/devel/message/82468
Mute This Topic: https://groups.io/mt/86085729/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-