From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga12.intel.com (mga12.intel.com []) by mx.groups.io with SMTP id smtpd.web10.2226.1615251291604715253 for ; Mon, 08 Mar 2021 16:54:56 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: min.m.xu@intel.com) IronPort-SDR: NzTxj9TsX6oILfKvW+GWsfWzLK5vwoFUIs1zj75hbVwbSyL8f+CRPTFj3s0wonjJZWfXA6wqUB e8Z5WQu3EV9w== X-IronPort-AV: E=McAfee;i="6000,8403,9917"; a="167402285" X-IronPort-AV: E=Sophos;i="5.81,233,1610438400"; d="scan'208";a="167402285" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Mar 2021 16:54:55 -0800 IronPort-SDR: 04rZxs3Z3bcjW3u1kk1ImvNfRqaA5FACIH184RUEJho19q6zFouwksz/KwV+U8xNWi+ipcTMBs EviUW3kRmg0g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,233,1610438400"; d="scan'208";a="376308092" Received: from unknown (HELO shwdeSSSDDPDSW2.ccr.corp.intel.com) ([10.239.54.61]) by fmsmga007.fm.intel.com with ESMTP; 08 Mar 2021 16:54:54 -0800 From: min.m.xu@intel.com To: devel@edk2.groups.io Cc: Min Xu , Doug Reiland , Jordan Justen , Laszlo Ersek , Jiewen Yao Subject: [PATCH 3/3] OvmfPkg: Implement library support for TdxLib SEC and DXE on OVMF Date: Tue, 9 Mar 2021 08:54:43 +0800 Message-Id: <1147786124d77b8855634384cb4ec6175646477f.1615249174.git.min.m.xu@intel.com> X-Mailer: git-send-email 2.30.1.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Min Xu 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. Signed-off-by: Min Xu Signed-off-by: Doug Reiland CC: Jordan Justen CC: Laszlo Ersek CC: Jiewen Yao --- 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 0000000000..3848bb6a95 --- /dev/null +++ b/OvmfPkg/Library/TdxLib/AcceptPages.c @@ -0,0 +1,68 @@ +/** @file=0D +=0D + There are 4 defined types in TD memory.=0D + Unaccepted memory is a special type of private memory. The OVMF must=0D + invoke TDCALL [TDG.MEM.PAGE.ACCEPT] the unaccepted memory before use it.= =0D +=0D + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +UINT64 mNumberOfDuplicatedAcceptedPages;=0D +=0D +/**=0D + This function accept a pending private page, and initialize the page to= =0D + all-0 using the TD ephemeral private key.=0D +=0D + @param[in] StartAddress Guest physical address of the private= =0D + page to accept.=0D + @param[in] NumberOfPages Number of the pages to be accepted.=0D +=0D + @return EFI_SUCCESS=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TdAcceptPages (=0D + IN UINT64 StartAddress,=0D + IN UINT64 NumberOfPages=0D + )=0D +{=0D + UINT64 Address;=0D + UINT64 Status;=0D + UINT64 Index;=0D +=0D + //=0D + // Determine if we need to accept pages before use=0D + //=0D + if (FixedPcdGetBool(PcdUseTdxAcceptPage) =3D=3D FALSE) {=0D + return EFI_SUCCESS;=0D + }=0D +=0D + Address =3D StartAddress;=0D +=0D + for( Index =3D 0; Index < NumberOfPages; Index++) {=0D + Status =3D TdCall(TDCALL_TDACCEPTPAGE,Address, 0, 0, 0);=0D + if (Status !=3D TDX_EXIT_REASON_SUCCESS) {=0D + if ((Status & ~0xFFULL) =3D=3D TDX_EXIT_REASON_PAGE_ALREADY_ACCEPT= ED) {=0D + ++mNumberOfDuplicatedAcceptedPages;=0D + DEBUG((DEBUG_VERBOSE, "Address %llx already accepted. Total numb= er of already accepted pages %ld\n",=0D + Address, mNumberOfDuplicatedAcceptedPages));=0D + } else {=0D + DEBUG((DEBUG_ERROR, "Address %llx failed to be accepted. Error = =3D %ld\n",=0D + Address, Status));=0D + ASSERT(Status =3D=3D TDX_EXIT_REASON_SUCCESS);=0D + }=0D + }=0D + Address +=3D EFI_PAGE_SIZE;=0D + }=0D + return EFI_SUCCESS;=0D +}=0D +=0D diff --git a/OvmfPkg/Library/TdxLib/Rtmr.c b/OvmfPkg/Library/TdxLib/Rtmr.c new file mode 100644 index 0000000000..a4b36b6c4b --- /dev/null +++ b/OvmfPkg/Library/TdxLib/Rtmr.c @@ -0,0 +1,80 @@ +/** @file=0D +=0D + Extends one of the RTMR measurement registers in TDCS with the provided= =0D + extension data in memory.=0D +=0D + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#define RTMR_COUNT 4=0D +=0D +/**=0D + This function extends one of the RTMR measurement register=0D + in TDCS with the provided extension data in memory.=0D + RTMR extending supports SHA384 which length is 48 bytes.=0D +=0D + @param[in] Data Point to the data to be extended=0D + @param[in] DataLen Length of the data. Must be 48=0D + @param[in] Index RTMR index=0D +=0D + @return EFI_SUCCESS=0D + @return EFI_INVALID_PARAMETER=0D + @return EFI_DEVICE_ERROR=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TdExtendRtmr(=0D + IN UINT32 *Data,=0D + IN UINT32 DataLen,=0D + IN UINT8 Index=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT64 *Buffer;=0D + UINT64 TdCallStatus;=0D +=0D + Status =3D EFI_SUCCESS;=0D +=0D + ASSERT(Index >=3D 0 && Index < RTMR_COUNT);=0D + ASSERT(DataLen =3D=3D SHA384_DIGEST_SIZE);=0D +=0D + //=0D + // Allocate 64B aligned mem to hold the sha384 hash value=0D + //=0D + Buffer =3D AllocateAlignedPages(EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE), 6= 4);=0D + if(Data =3D=3D NULL){=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D + CopyMem(Buffer, Data, SHA384_DIGEST_SIZE);=0D +=0D + TdCallStatus =3D TdCall(TDCALL_TDEXTENDRTMR, (UINT64)Buffer, Index, 0, 0= );=0D +=0D + if(TdCallStatus =3D=3D TDX_EXIT_REASON_SUCCESS){=0D + Status =3D EFI_SUCCESS;=0D + }else if(TdCallStatus =3D=3D TDX_EXIT_REASON_OPERAND_INVALID){=0D + Status =3D EFI_INVALID_PARAMETER;=0D + }else{=0D + Status =3D EFI_DEVICE_ERROR;=0D + }=0D +=0D + if(Status !=3D EFI_SUCCESS){=0D + DEBUG((DEBUG_ERROR, "Error returned from TdExtendRtmr call - 0x%lx\n",= TdCallStatus));=0D + }=0D +=0D + FreeAlignedPages(Buffer, EFI_SIZE_TO_PAGES(SHA384_DIGEST_SIZE));=0D +=0D + return Status;=0D +}=0D diff --git a/OvmfPkg/Library/TdxLib/TdReport.c b/OvmfPkg/Library/TdxLib/TdR= eport.c new file mode 100644 index 0000000000..ace213bcf4 --- /dev/null +++ b/OvmfPkg/Library/TdxLib/TdReport.c @@ -0,0 +1,102 @@ +/** @file=0D +=0D + Retrieve TDREPORT_STRUCT structure from TDX=0D +=0D + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#define REPORT_STRUCT_SIZE 1024=0D +#define ADDITIONAL_DATA_SIZE 64=0D +=0D +/**=0D + This function retrieve TDREPORT_STRUCT structure from TDX.=0D + The struct contains the measurements/configuration information of=0D + the guest TD that called the function, measurements/configuratio=0D + information of the TDX-SEAM module and a REPORTMACSTRUCT.=0D + The REPORTMACSTRUCT is integrity protected with a MAC and=0D + contains the hash of the measurements and configuration=0D + as well as additional REPORTDATA provided by the TD software.=0D +=0D + AdditionalData, a 64-byte value, is provided by the guest TD=0D + to be included in the TDREPORT=0D +=0D + @param[in,out] Report Holds the TEREPORT_STRUCT.=0D + @param[in] ReportSize Size of the report. It must be=0D + larger than 1024B.=0D + @param[in] AdditionalData Point to the additional data.=0D + @param[in] AdditionalDataSize Size of the additional data.=0D + If AdditionalData !=3D NULL, then=0D + this value must be 64B.=0D +=0D + @return EFI_SUCCESS=0D + @return EFI_INVALID_PARAMETER=0D + @return EFI_DEVICE_ERROR=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TdReport(=0D + IN OUT UINT8 *Report,=0D + IN UINT32 ReportSize,=0D + IN UINT8 *AdditionalData,=0D + IN UINT32 AdditionalDataSize=0D + )=0D +=0D +{=0D + EFI_STATUS Status;=0D + UINT64 *Data;=0D + UINT64 *Report_Struct;=0D + UINT64 *Report_Data;=0D + UINT64 TdCallStatus;=0D +=0D + if(ReportSize < REPORT_STRUCT_SIZE){=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if(AdditionalData !=3D NULL && AdditionalDataSize !=3D ADDITIONAL_DATA_S= IZE){=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + Data =3D AllocatePages(EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE + ADDITIONAL= _DATA_SIZE));=0D + if(Data =3D=3D NULL){=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + Report_Struct =3D Data;=0D + Report_Data =3D Data + REPORT_STRUCT_SIZE;=0D + if(AdditionalData !=3D NULL){=0D + CopyMem(Report_Data, AdditionalData, ADDITIONAL_DATA_SIZE);=0D + }else{=0D + ZeroMem(Report_Data, ADDITIONAL_DATA_SIZE);=0D + }=0D +=0D + TdCallStatus =3D TdCall(TDCALL_TDREPORT, (UINT64)Report_Struct, (UINT64)= Report_Data, 0, 0);=0D +=0D + if(TdCallStatus =3D=3D TDX_EXIT_REASON_SUCCESS){=0D + Status =3D EFI_SUCCESS;=0D + }else if(TdCallStatus =3D=3D TDX_EXIT_REASON_OPERAND_INVALID){=0D + Status =3D EFI_INVALID_PARAMETER;=0D + }else{=0D + Status =3D EFI_DEVICE_ERROR;=0D + }=0D +=0D + if(Status !=3D EFI_SUCCESS){=0D + DEBUG((DEBUG_ERROR, "Error returned from TdReport call - 0x%lx\n", TdC= allStatus));=0D + }else{=0D + CopyMem(Report, Data, REPORT_STRUCT_SIZE);=0D + }=0D +=0D + FreePages(Data, EFI_SIZE_TO_PAGES(REPORT_STRUCT_SIZE + ADDITIONAL_DATA_S= IZE));=0D +=0D + return Status;=0D +}=0D diff --git a/OvmfPkg/Library/TdxLib/TdxLib.inf b/OvmfPkg/Library/TdxLib/Tdx= Lib.inf new file mode 100644 index 0000000000..f642de9e3a --- /dev/null +++ b/OvmfPkg/Library/TdxLib/TdxLib.inf @@ -0,0 +1,48 @@ +## @file=0D +# Tdx library=0D +#=0D +# Copyright (c) 2020- 2021, Intel Corporation. All rights reserved.
=0D +# This program and the accompanying materials=0D +# are licensed and made available under the terms and conditions of the BS= D License=0D +# which accompanies this distribution. The full text of the license may b= e found at=0D +# http://opensource.org/licenses/bsd-license.php.=0D +#=0D +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=0D +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED.=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D TdxLib=0D + FILE_GUID =3D 032A8E0D-0C27-40C0-9CAA-23B731C1B223= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D TdxLib|PEI_CORE PEIM DXE_CORE DXE_DRI= VER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D X64=0D +#=0D +=0D +[Sources]=0D + Rtmr.c=0D + TdReport.c=0D + AcceptPages.c=0D + X64/Tdcall.nasm=0D + X64/Tdvmcall.nasm=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + BaseMemoryLib=0D + DebugLib=0D + MemoryAllocationLib=0D +=0D +[Pcd]=0D + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage=0D + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation=0D diff --git a/OvmfPkg/Library/TdxLib/TdxLibSec.inf b/OvmfPkg/Library/TdxLib/= TdxLibSec.inf new file mode 100644 index 0000000000..82ef4f08be --- /dev/null +++ b/OvmfPkg/Library/TdxLib/TdxLibSec.inf @@ -0,0 +1,45 @@ +## @file=0D +# Tdx library for SEC phase.=0D +#=0D +# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
=0D +# This program and the accompanying materials=0D +# are licensed and made available under the terms and conditions of the BS= D License=0D +# which accompanies this distribution. The full text of the license may b= e found at=0D +# http://opensource.org/licenses/bsd-license.php.=0D +#=0D +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=0D +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED.=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D TdxLibSec=0D + FILE_GUID =3D 498E8E1E-5B11-41F3-9083-EEE3A32B009D= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D TdxLib|SEC=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D X64=0D +#=0D +=0D +[Sources]=0D + AcceptPages.c=0D + X64/Tdcall.nasm=0D + X64/Tdvmcall.nasm=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + BaseMemoryLib=0D + DebugLib=0D +=0D +[Pcd]=0D + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxAcceptPage=0D + gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation=0D diff --git a/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm b/OvmfPkg/Library/TdxLi= b/X64/Tdcall.nasm new file mode 100644 index 0000000000..d0d55e2a94 --- /dev/null +++ b/OvmfPkg/Library/TdxLib/X64/Tdcall.nasm @@ -0,0 +1,125 @@ +;-------------------------------------------------------------------------= -----=0D +;*=0D +;* Copyright (c) 2020, Intel Corporation. All rights reserved.
=0D +;* This program and the accompanying materials=0D +;* are licensed and made available under the terms and conditions of the= BSD License=0D +;* which accompanies this distribution. The full text of the license ma= y be found at=0D +;* http://opensource.org/licenses/bsd-license.php=0D +;*=0D +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,= =0D +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR = IMPLIED.=0D +;*=0D +;*=0D +;-------------------------------------------------------------------------= -----=0D +=0D +DEFAULT REL=0D +SECTION .text=0D +=0D +%macro tdcall 0=0D +%if (FixedPcdGet32 (PcdUseTdxEmulation) !=3D 0)=0D + vmcall=0D +%else=0D + db 0x66,0x0f,0x01,0xcc=0D +%endif=0D +%endmacro=0D +=0D +%macro tdcall_push_regs 0=0D + push rbp=0D + mov rbp, rsp=0D + push r15=0D + push r14=0D + push r13=0D + push r12=0D + push rbx=0D + push rsi=0D + push rdi=0D +%endmacro=0D +=0D +%macro tdcall_pop_regs 0=0D + pop rdi=0D + pop rsi=0D + pop rbx=0D + pop r12=0D + pop r13=0D + pop r14=0D + pop r15=0D + pop rbp=0D +%endmacro=0D +=0D +%define number_of_regs_pushed 8=0D +%define number_of_parameters 4=0D +=0D +; Keep these in sync for push_regs/pop_regs, code below uses them to find = 5th or greater parameters=0D +%define first_variable_on_stack_offset (number_of_regs_pushed * 8) + (num= ber_of_parameters * 8) + 8=0D +%define second_variable_on_stack_offset (first_variable_on_stack_offset) += 8=0D +=0D +%macro tdcall_regs_preamble 2=0D + mov rax, %1=0D +=0D + mov ecx, %2=0D +=0D + ; R10 =3D 0 (standard TDVMCALL)=0D +=0D + xor r10d, r10d=0D +=0D + ; Zero out unused (for standard TDVMCALL) registers to avoid leaking=0D + ; secrets to the VMM.=0D +=0D + xor ebx, ebx=0D + xor esi, esi=0D + xor edi, edi=0D +=0D + xor edx, edx=0D + xor ebp, ebp=0D + xor r8d, r8d=0D + xor r9d, r9d=0D +%endmacro=0D +=0D +%macro tdcall_regs_postamble 0=0D + xor ebx, ebx=0D + xor esi, esi=0D + xor edi, edi=0D +=0D + xor ecx, ecx=0D + xor edx, edx=0D + xor r8d, r8d=0D + xor r9d, r9d=0D + xor r10d, r10d=0D + xor r11d, r11d=0D +%endmacro=0D +=0D +; TdCall (=0D +; UINT64 Leaf, // Rcx=0D +; UINT64 P1, // Rdx=0D +; UINT64 P2, // R8=0D +; UINT64 P3, // R9=0D +; UINT64 Results, // rsp + 0x28=0D +; )=0D +global ASM_PFX(TdCall)=0D +ASM_PFX(TdCall):=0D + tdcall_push_regs=0D +=0D + mov rax, rcx=0D + mov rcx, rdx=0D + mov rdx, r8=0D + mov r8, r9=0D +=0D + tdcall=0D +=0D + ; exit if tdcall reports failure.=0D + test rax, rax=0D + jnz .exit=0D +=0D + ; test if caller wanted results=0D + mov r12, [rsp + first_variable_on_stack_offset ]=0D + test r12, r12=0D + jz .exit=0D + mov [r12 + 0 ], rcx=0D + mov [r12 + 8 ], rdx=0D + mov [r12 + 16], r8=0D + mov [r12 + 24], r9=0D + mov [r12 + 32], r10=0D + mov [r12 + 40], r11=0D +.exit:=0D + tdcall_pop_regs=0D + ret=0D diff --git a/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm b/OvmfPkg/Library/Tdx= Lib/X64/Tdvmcall.nasm new file mode 100644 index 0000000000..e1da9b4fbd --- /dev/null +++ b/OvmfPkg/Library/TdxLib/X64/Tdvmcall.nasm @@ -0,0 +1,211 @@ +;-------------------------------------------------------------------------= -----=0D +;*=0D +;* Copyright (c) 2020, Intel Corporation. All rights reserved.
=0D +;* This program and the accompanying materials=0D +;* are licensed and made available under the terms and conditions of the= BSD License=0D +;* which accompanies this distribution. The full text of the license ma= y be found at=0D +;* http://opensource.org/licenses/bsd-license.php=0D +;*=0D +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,= =0D +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR = IMPLIED.=0D +;*=0D +;*=0D +;-------------------------------------------------------------------------= -----=0D +=0D +DEFAULT REL=0D +SECTION .text=0D +=0D +%define TDVMCALL_EXPOSE_REGS_MASK 0xffec=0D +%define TDVMCALL 0x0=0D +%define EXIT_REASON_CPUID 0xa=0D +=0D +%macro tdcall 0=0D +%if (FixedPcdGet32 (PcdUseTdxEmulation) !=3D 0)=0D + vmcall=0D +%else=0D + db 0x66,0x0f,0x01,0xcc=0D +%endif=0D +%endmacro=0D +=0D +%macro tdcall_push_regs 0=0D + push rbp=0D + mov rbp, rsp=0D + push r15=0D + push r14=0D + push r13=0D + push r12=0D + push rbx=0D + push rsi=0D + push rdi=0D +%endmacro=0D +=0D +%macro tdcall_pop_regs 0=0D + pop rdi=0D + pop rsi=0D + pop rbx=0D + pop r12=0D + pop r13=0D + pop r14=0D + pop r15=0D + pop rbp=0D +%endmacro=0D +=0D +%define number_of_regs_pushed 8=0D +%define number_of_parameters 4=0D +=0D +; Keep these in sync for push_regs/pop_regs, code below uses them to find = 5th or greater parameters=0D +%define first_variable_on_stack_offset (number_of_regs_pushed * 8) + (num= ber_of_parameters * 8) + 8=0D +%define second_variable_on_stack_offset (first_variable_on_stack_offset) += 8=0D +=0D +%macro tdcall_regs_preamble 2=0D + mov rax, %1=0D +=0D + mov ecx, %2=0D +=0D + ; R10 =3D 0 (standard TDVMCALL)=0D +=0D + xor r10d, r10d=0D +=0D + ; Zero out unused (for standard TDVMCALL) registers to avoid leaking=0D + ; secrets to the VMM.=0D +=0D + xor ebx, ebx=0D + xor esi, esi=0D + xor edi, edi=0D +=0D + xor edx, edx=0D + xor ebp, ebp=0D + xor r8d, r8d=0D + xor r9d, r9d=0D +%endmacro=0D +=0D +%macro tdcall_regs_postamble 0=0D + xor ebx, ebx=0D + xor esi, esi=0D + xor edi, edi=0D +=0D + xor ecx, ecx=0D + xor edx, edx=0D + xor r8d, r8d=0D + xor r9d, r9d=0D + xor r10d, r10d=0D + xor r11d, r11d=0D +%endmacro=0D +=0D +;-------------------------------------------------------------------------= -----=0D +; 0 =3D> RAX =3D TDCALL leaf=0D +; M =3D> RCX =3D TDVMCALL register behavior=0D +; 1 =3D> R10 =3D standard vs. vendor=0D +; RDI =3D> R11 =3D TDVMCALL function / nr=0D +; RSI =3D R12 =3D p1=0D +; RDX =3D> R13 =3D p2=0D +; RCX =3D> R14 =3D p3=0D +; R8 =3D> R15 =3D p4=0D +=0D +; UINT64=0D +; EFIAPI=0D +; TdVmCall (=0D +; UINT64 Leaf, // Rcx=0D +; UINT64 P1, // Rdx=0D +; UINT64 P2, // R8=0D +; UINT64 P3, // R9=0D +; UINT64 P4, // rsp + 0x28=0D +; UINT64 *Val // rsp + 0x30=0D +; )=0D +global ASM_PFX(TdVmCall)=0D +ASM_PFX(TdVmCall):=0D + tdcall_push_regs=0D +=0D + mov r11, rcx=0D + mov r12, rdx=0D + mov r13, r8=0D + mov r14, r9=0D + mov r15, [rsp + first_variable_on_stack_offset ]=0D +=0D + tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK=0D +=0D + tdcall=0D +=0D + ; ignore return dataif TDCALL reports failure.=0D + test rax, rax=0D + jnz .no_return_data=0D +=0D + ; Propagate TDVMCALL success/failure to return value.=0D + mov rax, r10=0D +=0D + ; Retrieve the Val pointer.=0D + mov r9, [rsp + second_variable_on_stack_offset ]=0D + test r9, r9=0D + jz .no_return_data=0D +=0D + ; On success, propagate TDVMCALL output value to output param=0D + test rax, rax=0D + jnz .no_return_data=0D + mov [r9], r11=0D +.no_return_data:=0D + tdcall_regs_postamble=0D +=0D + tdcall_pop_regs=0D +=0D + ret=0D +=0D +;-------------------------------------------------------------------------= -----=0D +; 0 =3D> RAX =3D TDCALL leaf=0D +; M =3D> RCX =3D TDVMCALL register behavior=0D +; 1 =3D> R10 =3D standard vs. vendor=0D +; RDI =3D> R11 =3D TDVMCALL function / nr=0D +; RSI =3D R12 =3D p1=0D +; RDX =3D> R13 =3D p2=0D +; RCX =3D> R14 =3D p3=0D +; R8 =3D> R15 =3D p4=0D +=0D +; UINT64=0D +; EFIAPI=0D +; TdVmCallCpuid (=0D +; UINT64 EaxIn, // Rcx=0D +; UINT64 EcxIn, // Rdx=0D +; UINT64 *Results // R8=0D +; )=0D +global ASM_PFX(TdVmCallCpuid)=0D +ASM_PFX(TdVmCallCpuid):=0D + tdcall_push_regs=0D +=0D + mov r11, EXIT_REASON_CPUID=0D + mov r12, rcx=0D + mov r13, rdx=0D +=0D + tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK=0D +=0D + ; Save *results pointers=0D + push r8=0D +=0D + tdcall=0D +=0D + ; Panic if TDCALL reports failure.=0D + test rax, rax=0D + jnz .no_return_data=0D +=0D + ; Propagate TDVMCALL success/failure to return value.=0D + mov rax, r10=0D + test rax, rax=0D + jnz .no_return_data=0D +=0D + ; Retrieve *Results=0D + pop r8=0D + test r8, r8=0D + jnz .no_return_data=0D + ; Caller pass in buffer so store results r12-r15 contains eax-edx=0D + mov [r8 + 0], r12=0D + mov [r8 + 8], r13=0D + mov [r8 + 16], r14=0D + mov [r8 + 24], r15=0D +=0D +.no_return_data:=0D + tdcall_regs_postamble=0D +=0D + tdcall_pop_regs=0D +=0D + ret=0D +=0D +.panic:=0D + ud2=0D --=20 2.29.2.windows.2