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]
-=-=-=-=-=-=-=-=-=-=-=-
> +// 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]
-=-=-=-=-=-=-=-=-=-=-=-
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]
-=-=-=-=-=-=-=-=-=-=-=-
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] -=-=-=-=-=-=-=-=-=-=-=-
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] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.