The base TdxLib in MdePkg/Library provides a default limited interface.
As it does not provide full support, create an OVMF version of this library
to begin the process of providing full support of TDX in OVMF.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
Signed-off-by: Doug Reiland <doug.reiland@intel.com>
---
OvmfPkg/Library/TdxLib/AcceptPages.c | 68 ++++++++
OvmfPkg/Library/TdxLib/Rtmr.c | 80 +++++++++
OvmfPkg/Library/TdxLib/TdReport.c | 102 +++++++++++
OvmfPkg/Library/TdxLib/TdxLib.inf | 48 ++++++
OvmfPkg/Library/TdxLib/TdxLibSec.inf | 45 +++++
OvmfPkg/Library/TdxLib/X64/Tdcall.nasm | 125 ++++++++++++++
OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm | 211 +++++++++++++++++++++++
7 files changed, 679 insertions(+)
create mode 100644 OvmfPkg/Library/TdxLib/AcceptPages.c
create mode 100644 OvmfPkg/Library/TdxLib/Rtmr.c
create mode 100644 OvmfPkg/Library/TdxLib/TdReport.c
create mode 100644 OvmfPkg/Library/TdxLib/TdxLib.inf
create mode 100644 OvmfPkg/Library/TdxLib/TdxLibSec.inf
create mode 100644 OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
create mode 100644 OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
diff --git a/OvmfPkg/Library/TdxLib/AcceptPages.c b/OvmfPkg/Library/TdxLib/AcceptPages.c
new file mode 100644
index 000000000000..3848bb6a95a4
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/AcceptPages.c
@@ -0,0 +1,68 @@
+/** @file
+
+ There are 4 defined types in TD memory.
+ Unaccepted memory is a special type of private memory. The OVMF must
+ invoke TDCALL [TDG.MEM.PAGE.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;
+
+/**
+ This function accept 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.
+
+ @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TdAcceptPages (
+ IN UINT64 StartAddress,
+ IN UINT64 NumberOfPages
+ )
+{
+ UINT64 Address;
+ UINT64 Status;
+ UINT64 Index;
+
+ //
+ // Determine if we need to accept pages before use
+ //
+ if (FixedPcdGetBool(PcdUseTdxAcceptPage) == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ Address = StartAddress;
+
+ for( Index = 0; Index < NumberOfPages; Index++) {
+ Status = TdCall(TDCALL_TDACCEPTPAGE,Address, 0, 0, 0);
+ if (Status != TDX_EXIT_REASON_SUCCESS) {
+ if ((Status & ~0xFFULL) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED) {
+ ++mNumberOfDuplicatedAcceptedPages;
+ DEBUG((DEBUG_VERBOSE, "Address %llx already accepted. Total number of already accepted pages %ld\n",
+ Address, mNumberOfDuplicatedAcceptedPages));
+ } else {
+ DEBUG((DEBUG_ERROR, "Address %llx failed to be accepted. Error = %ld\n",
+ Address, Status));
+ ASSERT(Status == TDX_EXIT_REASON_SUCCESS);
+ }
+ }
+ Address += EFI_PAGE_SIZE;
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/OvmfPkg/Library/TdxLib/Rtmr.c b/OvmfPkg/Library/TdxLib/Rtmr.c
new file mode 100644
index 000000000000..a4b36b6c4bef
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/Rtmr.c
@@ -0,0 +1,80 @@
+/** @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 <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/Tdx.h>
+#include <Protocol/Tdx.h>
+
+#define RTMR_COUNT 4
+
+/**
+ 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 *Buffer;
+ UINT64 TdCallStatus;
+
+ Status = EFI_SUCCESS;
+
+ ASSERT(Index >= 0 && Index < RTMR_COUNT);
+ ASSERT(DataLen == SHA384_DIGEST_SIZE);
+
+ //
+ // Allocate 64B aligned mem to hold the sha384 hash value
+ //
+ Buffer = AllocateAlignedPages(EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE), 64);
+ if(Data == NULL){
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem(Buffer, Data, SHA384_DIGEST_SIZE);
+
+ TdCallStatus = TdCall(TDCALL_TDEXTENDRTMR, (UINT64)Buffer, 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));
+ }
+
+ FreeAlignedPages(Buffer, EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE));
+
+ return Status;
+}
diff --git a/OvmfPkg/Library/TdxLib/TdReport.c b/OvmfPkg/Library/TdxLib/TdReport.c
new file mode 100644
index 000000000000..ace213bcf467
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/TdReport.c
@@ -0,0 +1,102 @@
+/** @file
+
+ Retrieve TDREPORT_STRUCT structure from TDX
+
+ 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/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Tdx.h>
+#include <Library/TdxLib.h>
+
+#define REPORT_STRUCT_SIZE 1024
+#define ADDITIONAL_DATA_SIZE 64
+
+/**
+ This function retrieve TDREPORT_STRUCT structure from TDX.
+ The struct contains the measurements/configuration information of
+ the guest TD that called the function, measurements/configuratio
+ information of the TDX-SEAM module and a REPORTMACSTRUCT.
+ The REPORTMACSTRUCT is integrity protected with a MAC and
+ contains the hash of the measurements and configuration
+ as well as additional REPORTDATA provided by the TD software.
+
+ AdditionalData, a 64-byte value, is provided by the guest TD
+ to be included in the TDREPORT
+
+ @param[in,out] Report Holds the TEREPORT_STRUCT.
+ @param[in] ReportSize Size of the report. It must be
+ larger than 1024B.
+ @param[in] AdditionalData Point to the additional data.
+ @param[in] AdditionalDataSize Size of the additional data.
+ If AdditionalData != NULL, then
+ this value must be 64B.
+
+ @return EFI_SUCCESS
+ @return EFI_INVALID_PARAMETER
+ @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+EFIAPI
+TdReport(
+ IN OUT UINT8 *Report,
+ IN UINT32 ReportSize,
+ IN UINT8 *AdditionalData,
+ IN UINT32 AdditionalDataSize
+ )
+
+{
+ EFI_STATUS Status;
+ UINT64 *Data;
+ UINT64 *Report_Struct;
+ UINT64 *Report_Data;
+ UINT64 TdCallStatus;
+
+ if(ReportSize < REPORT_STRUCT_SIZE){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(AdditionalData != NULL && AdditionalDataSize != ADDITIONAL_DATA_SIZE){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = AllocatePages(EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE + ADDITIONAL_DATA_SIZE));
+ if(Data == NULL){
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Report_Struct = Data;
+ Report_Data = Data + REPORT_STRUCT_SIZE;
+ if(AdditionalData != NULL){
+ CopyMem(Report_Data, AdditionalData, ADDITIONAL_DATA_SIZE);
+ }else{
+ ZeroMem(Report_Data, ADDITIONAL_DATA_SIZE);
+ }
+
+ TdCallStatus = TdCall(TDCALL_TDREPORT, (UINT64)Report_Struct, (UINT64)Report_Data, 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 TdReport call - 0x%lx\n", TdCallStatus));
+ }else{
+ CopyMem(Report, Data, REPORT_STRUCT_SIZE);
+ }
+
+ FreePages(Data, EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE + ADDITIONAL_DATA_SIZE));
+
+ return Status;
+}
diff --git a/OvmfPkg/Library/TdxLib/TdxLib.inf b/OvmfPkg/Library/TdxLib/TdxLib.inf
new file mode 100644
index 000000000000..f642de9e3a5f
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/TdxLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Tdx library
+#
+# Copyright (c) 2020- 2021, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TdxLib
+ FILE_GUID = 032A8E0D-0C27-40C0-9CAA-23B731C1B223
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TdxLib|PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ Rtmr.c
+ TdReport.c
+ AcceptPages.c
+ X64/Tdcall.nasm
+ X64/Tdvmcall.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage
+ gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation
diff --git a/OvmfPkg/Library/TdxLib/TdxLibSec.inf b/OvmfPkg/Library/TdxLib/TdxLibSec.inf
new file mode 100644
index 000000000000..82ef4f08be8c
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/TdxLibSec.inf
@@ -0,0 +1,45 @@
+## @file
+# Tdx library for SEC phase.
+#
+# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TdxLibSec
+ FILE_GUID = 498E8E1E-5B11-41F3-9083-EEE3A32B009D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TdxLib|SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ AcceptPages.c
+ X64/Tdcall.nasm
+ X64/Tdvmcall.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage
+ gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation
diff --git a/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm b/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
new file mode 100644
index 000000000000..d0d55e2a9443
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
@@ -0,0 +1,125 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+;* This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;*
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+%macro tdcall 0
+%if (FixedPcdGet32 (PcdUseTdxEmulation) != 0)
+ vmcall
+%else
+ db 0x66,0x0f,0x01,0xcc
+%endif
+%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
+
+ 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
+
+; 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/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm b/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
new file mode 100644
index 000000000000..e1da9b4fbdd6
--- /dev/null
+++ b/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
@@ -0,0 +1,211 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+;* This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;*
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+%define TDVMCALL_EXPOSE_REGS_MASK 0xffec
+%define TDVMCALL 0x0
+%define EXIT_REASON_CPUID 0xa
+
+%macro tdcall 0
+%if (FixedPcdGet32 (PcdUseTdxEmulation) != 0)
+ vmcall
+%else
+ db 0x66,0x0f,0x01,0xcc
+%endif
+%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
+
+ 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
+
+ tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
+
+ ; Save *results pointers
+ push r8
+
+ 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
+ jnz .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
--
2.29.2.windows.2
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72568): https://edk2.groups.io/g/devel/message/72568
Mute This Topic: https://groups.io/mt/81195559/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Hi
Would you please try to merge TdxLib and TdxLibSec?
I am not sure if we really need two instance.
Also, can we remove MemoryAllocationLib ?
If it is just used to allocate aligned memory, can we allocate aligned memory in stack instead of heap ?
> -----Original Message-----
> From: Xu, Min M <min.m.xu@intel.com>
> Sent: Tuesday, March 9, 2021 2:13 PM
> To: devel@edk2.groups.io
> Cc: Xu, Min M <min.m.xu@intel.com>; Justen, Jordan L
> <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Reiland, Doug <doug.reiland@intel.com>
> Subject: [PATCH V3 3/3] OvmfPkg: Implement library support for TdxLib SEC and
> DXE on OVMF
>
> The base TdxLib in MdePkg/Library provides a default limited interface.
> As it does not provide full support, create an OVMF version of this library
> to begin the process of providing full support of TDX in OVMF.
>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
>
> Signed-off-by: Min Xu <min.m.xu@intel.com>
> Signed-off-by: Doug Reiland <doug.reiland@intel.com>
> ---
> OvmfPkg/Library/TdxLib/AcceptPages.c | 68 ++++++++
> OvmfPkg/Library/TdxLib/Rtmr.c | 80 +++++++++
> OvmfPkg/Library/TdxLib/TdReport.c | 102 +++++++++++
> OvmfPkg/Library/TdxLib/TdxLib.inf | 48 ++++++
> OvmfPkg/Library/TdxLib/TdxLibSec.inf | 45 +++++
> OvmfPkg/Library/TdxLib/X64/Tdcall.nasm | 125 ++++++++++++++
> OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm | 211 +++++++++++++++++++++++
> 7 files changed, 679 insertions(+)
> create mode 100644 OvmfPkg/Library/TdxLib/AcceptPages.c
> create mode 100644 OvmfPkg/Library/TdxLib/Rtmr.c
> create mode 100644 OvmfPkg/Library/TdxLib/TdReport.c
> create mode 100644 OvmfPkg/Library/TdxLib/TdxLib.inf
> create mode 100644 OvmfPkg/Library/TdxLib/TdxLibSec.inf
> create mode 100644 OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
> create mode 100644 OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
>
> diff --git a/OvmfPkg/Library/TdxLib/AcceptPages.c
> b/OvmfPkg/Library/TdxLib/AcceptPages.c
> new file mode 100644
> index 000000000000..3848bb6a95a4
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/AcceptPages.c
> @@ -0,0 +1,68 @@
> +/** @file
> +
> + There are 4 defined types in TD memory.
> + Unaccepted memory is a special type of private memory. The OVMF must
> + invoke TDCALL [TDG.MEM.PAGE.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;
> +
> +/**
> + This function accept 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.
> +
> + @return EFI_SUCCESS
> +**/
> +EFI_STATUS
> +EFIAPI
> +TdAcceptPages (
> + IN UINT64 StartAddress,
> + IN UINT64 NumberOfPages
> + )
> +{
> + UINT64 Address;
> + UINT64 Status;
> + UINT64 Index;
> +
> + //
> + // Determine if we need to accept pages before use
> + //
> + if (FixedPcdGetBool(PcdUseTdxAcceptPage) == FALSE) {
> + return EFI_SUCCESS;
> + }
> +
> + Address = StartAddress;
> +
> + for( Index = 0; Index < NumberOfPages; Index++) {
> + Status = TdCall(TDCALL_TDACCEPTPAGE,Address, 0, 0, 0);
> + if (Status != TDX_EXIT_REASON_SUCCESS) {
> + if ((Status & ~0xFFULL) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED)
> {
> + ++mNumberOfDuplicatedAcceptedPages;
> + DEBUG((DEBUG_VERBOSE, "Address %llx already accepted. Total number
> of already accepted pages %ld\n",
> + Address, mNumberOfDuplicatedAcceptedPages));
> + } else {
> + DEBUG((DEBUG_ERROR, "Address %llx failed to be accepted. Error
> = %ld\n",
> + Address, Status));
> + ASSERT(Status == TDX_EXIT_REASON_SUCCESS);
> + }
> + }
> + Address += EFI_PAGE_SIZE;
> + }
> + return EFI_SUCCESS;
> +}
> +
> diff --git a/OvmfPkg/Library/TdxLib/Rtmr.c b/OvmfPkg/Library/TdxLib/Rtmr.c
> new file mode 100644
> index 000000000000..a4b36b6c4bef
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/Rtmr.c
> @@ -0,0 +1,80 @@
> +/** @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 <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Tpm20.h>
> +#include <IndustryStandard/Tdx.h>
> +#include <Protocol/Tdx.h>
> +
> +#define RTMR_COUNT 4
> +
> +/**
> + 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 *Buffer;
> + UINT64 TdCallStatus;
> +
> + Status = EFI_SUCCESS;
> +
> + ASSERT(Index >= 0 && Index < RTMR_COUNT);
> + ASSERT(DataLen == SHA384_DIGEST_SIZE);
> +
> + //
> + // Allocate 64B aligned mem to hold the sha384 hash value
> + //
> + Buffer = AllocateAlignedPages(EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE), 64);
> + if(Data == NULL){
> + return EFI_OUT_OF_RESOURCES;
> + }
> + CopyMem(Buffer, Data, SHA384_DIGEST_SIZE);
> +
> + TdCallStatus = TdCall(TDCALL_TDEXTENDRTMR, (UINT64)Buffer, 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));
> + }
> +
> + FreeAlignedPages(Buffer, EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE));
> +
> + return Status;
> +}
> diff --git a/OvmfPkg/Library/TdxLib/TdReport.c
> b/OvmfPkg/Library/TdxLib/TdReport.c
> new file mode 100644
> index 000000000000..ace213bcf467
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/TdReport.c
> @@ -0,0 +1,102 @@
> +/** @file
> +
> + Retrieve TDREPORT_STRUCT structure from TDX
> +
> + 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/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Tdx.h>
> +#include <Library/TdxLib.h>
> +
> +#define REPORT_STRUCT_SIZE 1024
> +#define ADDITIONAL_DATA_SIZE 64
> +
> +/**
> + This function retrieve TDREPORT_STRUCT structure from TDX.
> + The struct contains the measurements/configuration information of
> + the guest TD that called the function, measurements/configuratio
> + information of the TDX-SEAM module and a REPORTMACSTRUCT.
> + The REPORTMACSTRUCT is integrity protected with a MAC and
> + contains the hash of the measurements and configuration
> + as well as additional REPORTDATA provided by the TD software.
> +
> + AdditionalData, a 64-byte value, is provided by the guest TD
> + to be included in the TDREPORT
> +
> + @param[in,out] Report Holds the TEREPORT_STRUCT.
> + @param[in] ReportSize Size of the report. It must be
> + larger than 1024B.
> + @param[in] AdditionalData Point to the additional data.
> + @param[in] AdditionalDataSize Size of the additional data.
> + If AdditionalData != NULL, then
> + this value must be 64B.
> +
> + @return EFI_SUCCESS
> + @return EFI_INVALID_PARAMETER
> + @return EFI_DEVICE_ERROR
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TdReport(
> + IN OUT UINT8 *Report,
> + IN UINT32 ReportSize,
> + IN UINT8 *AdditionalData,
> + IN UINT32 AdditionalDataSize
> + )
> +
> +{
> + EFI_STATUS Status;
> + UINT64 *Data;
> + UINT64 *Report_Struct;
> + UINT64 *Report_Data;
> + UINT64 TdCallStatus;
> +
> + if(ReportSize < REPORT_STRUCT_SIZE){
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if(AdditionalData != NULL && AdditionalDataSize != ADDITIONAL_DATA_SIZE){
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Data = AllocatePages(EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE +
> ADDITIONAL_DATA_SIZE));
> + if(Data == NULL){
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Report_Struct = Data;
> + Report_Data = Data + REPORT_STRUCT_SIZE;
> + if(AdditionalData != NULL){
> + CopyMem(Report_Data, AdditionalData, ADDITIONAL_DATA_SIZE);
> + }else{
> + ZeroMem(Report_Data, ADDITIONAL_DATA_SIZE);
> + }
> +
> + TdCallStatus = TdCall(TDCALL_TDREPORT, (UINT64)Report_Struct,
> (UINT64)Report_Data, 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 TdReport call - 0x%lx\n",
> TdCallStatus));
> + }else{
> + CopyMem(Report, Data, REPORT_STRUCT_SIZE);
> + }
> +
> + FreePages(Data, EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE +
> ADDITIONAL_DATA_SIZE));
> +
> + return Status;
> +}
> diff --git a/OvmfPkg/Library/TdxLib/TdxLib.inf
> b/OvmfPkg/Library/TdxLib/TdxLib.inf
> new file mode 100644
> index 000000000000..f642de9e3a5f
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/TdxLib.inf
> @@ -0,0 +1,48 @@
> +## @file
> +# Tdx library
> +#
> +# Copyright (c) 2020- 2021, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php.
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = TdxLib
> + FILE_GUID = 032A8E0D-0C27-40C0-9CAA-23B731C1B223
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = TdxLib|PEI_CORE PEIM DXE_CORE DXE_DRIVER
> DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +# VALID_ARCHITECTURES = X64
> +#
> +
> +[Sources]
> + Rtmr.c
> + TdReport.c
> + AcceptPages.c
> + X64/Tdcall.nasm
> + X64/Tdvmcall.nasm
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + BaseMemoryLib
> + DebugLib
> + MemoryAllocationLib
> +
> +[Pcd]
> + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage
> + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation
> diff --git a/OvmfPkg/Library/TdxLib/TdxLibSec.inf
> b/OvmfPkg/Library/TdxLib/TdxLibSec.inf
> new file mode 100644
> index 000000000000..82ef4f08be8c
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/TdxLibSec.inf
> @@ -0,0 +1,45 @@
> +## @file
> +# Tdx library for SEC phase.
> +#
> +# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be found
> at
> +# http://opensource.org/licenses/bsd-license.php.
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = TdxLibSec
> + FILE_GUID = 498E8E1E-5B11-41F3-9083-EEE3A32B009D
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = TdxLib|SEC
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +# VALID_ARCHITECTURES = X64
> +#
> +
> +[Sources]
> + AcceptPages.c
> + X64/Tdcall.nasm
> + X64/Tdvmcall.nasm
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + BaseMemoryLib
> + DebugLib
> +
> +[Pcd]
> + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage
> + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation
> diff --git a/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
> b/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
> new file mode 100644
> index 000000000000..d0d55e2a9443
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm
> @@ -0,0 +1,125 @@
> +;------------------------------------------------------------------------------
> +;*
> +;* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +;* This program and the accompanying materials
> +;* are licensed and made available under the terms and conditions of the BSD
> License
> +;* which accompanies this distribution. The full text of the license may be
> found at
> +;* http://opensource.org/licenses/bsd-license.php
> +;*
> +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +;*
> +;*
> +;------------------------------------------------------------------------------
> +
> +DEFAULT REL
> +SECTION .text
> +
> +%macro tdcall 0
> +%if (FixedPcdGet32 (PcdUseTdxEmulation) != 0)
> + vmcall
> +%else
> + db 0x66,0x0f,0x01,0xcc
> +%endif
> +%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
> +
> + 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
> +
> +; 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/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
> b/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
> new file mode 100644
> index 000000000000..e1da9b4fbdd6
> --- /dev/null
> +++ b/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm
> @@ -0,0 +1,211 @@
> +;------------------------------------------------------------------------------
> +;*
> +;* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +;* This program and the accompanying materials
> +;* are licensed and made available under the terms and conditions of the BSD
> License
> +;* which accompanies this distribution. The full text of the license may be
> found at
> +;* http://opensource.org/licenses/bsd-license.php
> +;*
> +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +;*
> +;*
> +;------------------------------------------------------------------------------
> +
> +DEFAULT REL
> +SECTION .text
> +
> +%define TDVMCALL_EXPOSE_REGS_MASK 0xffec
> +%define TDVMCALL 0x0
> +%define EXIT_REASON_CPUID 0xa
> +
> +%macro tdcall 0
> +%if (FixedPcdGet32 (PcdUseTdxEmulation) != 0)
> + vmcall
> +%else
> + db 0x66,0x0f,0x01,0xcc
> +%endif
> +%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
> +
> + 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
> +
> + tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
> +
> + ; Save *results pointers
> + push r8
> +
> + 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
> + jnz .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
> --
> 2.29.2.windows.2
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72572): https://edk2.groups.io/g/devel/message/72572
Mute This Topic: https://groups.io/mt/81195559/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.