From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web09.21069.1628769481864596349 for ; Thu, 12 Aug 2021 04:58:03 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.20, mailfrom: min.m.xu@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10073"; a="202524274" X-IronPort-AV: E=Sophos;i="5.84,315,1620716400"; d="scan'208";a="202524274" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2021 04:58:02 -0700 X-IronPort-AV: E=Sophos;i="5.84,315,1620716400"; d="scan'208";a="517433773" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.249.175.248]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2021 04:58:00 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Eric Dong , Ray Ni , Rahul Kumar Subject: [PATCH 13/23] UefiCpuPkg: Enable Tdx support in MpInitLib Date: Thu, 12 Aug 2021 19:56:52 +0800 Message-Id: <88cf26946cb606b11c1821323a43dbceacaf2cf2.1628767741.git.min.m.xu@intel.com> X-Mailer: git-send-email 2.29.2.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 In TDVF BSP and APs are simplified. BSP is the vCPU-0, while the others are treated as APs. So MP intialization is rather simple. The processor info is retrieved by TDCALL, ApWorker is not supported, BSP is always the working processor, while the APs are just in a wait-for-precedure state. Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Signed-off-by: Min Xu --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 5 + UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 14 +- UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h | 107 +++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 26 ++++ UefiCpuPkg/Library/MpInitLib/MpLibTdx.c | 142 ++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c | 117 +++++++++++++++ UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 5 + .../Library/MpInitLib/X64/IntelTdcall.nasm | 120 +++++++++++++++ 8 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h create mode 100644 UefiCpuPkg/Library/MpInitLib/MpLibTdx.c create mode 100644 UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index d34419c2a524..2e1cc34d2657 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -22,10 +22,13 @@ # [Sources.IA32] + MpLibTdxNull.c Ia32/MpFuncs.nasm [Sources.X64] + MpLibTdx.c X64/MpFuncs.nasm + X64/IntelTdcall.nasm [Sources.common] MpEqu.inc @@ -33,6 +36,7 @@ MpLib.c MpLib.h Microcode.c + MpIntelTdx.h [Packages] MdePkg/MdePkg.dec @@ -76,3 +80,4 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdTdxIsEnabled ## CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 93fc63bf93e3..b7275db3d564 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -7,6 +7,7 @@ **/ #include "MpLib.h" +#include "MpIntelTdx.h" #include #include @@ -15,7 +16,6 @@ #include #include #include - #include #define AP_SAFE_STACK_SIZE 128 @@ -801,6 +801,10 @@ MpInitLibStartupThisAP ( { EFI_STATUS Status; + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + // // temporarily stop checkAllApsStatus for avoid resource dead-lock. // @@ -857,6 +861,10 @@ MpInitLibSwitchBSP ( EFI_TIMER_ARCH_PROTOCOL *Timer; UINT64 TimerPeriod; + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + TimerPeriod = 0; // // Locate Timer Arch Protocol @@ -930,6 +938,10 @@ MpInitLibEnableDisableAP ( EFI_STATUS Status; BOOLEAN TempStopCheckState; + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + TempStopCheckState = FALSE; // // temporarily stop checkAllAPsStatus for initialize parameters. diff --git a/UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h b/UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h new file mode 100644 index 000000000000..cbb45d2eaf0a --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h @@ -0,0 +1,107 @@ +/** @file + Intel Tdx header file. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef MP_INTEL_TDX_H_ +#define MP_INTEL_TDX_H_ + +#include +#include +#include +#include +#include + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where information for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ); + +/** + Retrieves the number of logical processor in the platform and the number of + those logical processors that are enabled on this boot. This service may only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of logical + processors in the system, including the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical + processors that exist in system, including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ); + +/** + 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 +MyTdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ); + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ); + +#endif diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index b9a06747edbf..d03ad8ff483e 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -9,6 +9,7 @@ **/ #include "MpLib.h" +#include "MpIntelTdx.h" #include #include #include @@ -1965,6 +1966,10 @@ MpInitLibInitialize ( UINTN BackupBufferAddr; UINTN ApIdtBase; + if (MpTdxIsEnabled ()) { + return EFI_SUCCESS; + } + OldCpuMpData = GetCpuMpDataFromGuidedHob (); if (OldCpuMpData == NULL) { MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber); @@ -2215,6 +2220,10 @@ MpInitLibGetProcessorInfo ( CPU_INFO_IN_HOB *CpuInfoInHob; UINTN OriginalProcessorNumber; + if (MpTdxIsEnabled ()) { + return TdxMpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, HealthData); + } + CpuMpData = GetCpuMpData (); CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; @@ -2446,6 +2455,10 @@ EnableDisableApWorker ( CPU_MP_DATA *CpuMpData; UINTN CallerNumber; + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + CpuMpData = GetCpuMpData (); // @@ -2506,6 +2519,11 @@ MpInitLibWhoAmI ( return EFI_INVALID_PARAMETER; } + if (MpTdxIsEnabled ()) { + *ProcessorNumber = 0; + return EFI_SUCCESS; + } + CpuMpData = GetCpuMpData (); return GetProcessorNumber (CpuMpData, ProcessorNumber); @@ -2544,6 +2562,10 @@ MpInitLibGetNumberOfProcessors ( UINTN EnabledProcessorNumber; UINTN Index; + if (MpTdxIsEnabled ()) { + return TdxMpInitLibGetNumberOfProcessors(NumberOfProcessors, NumberOfEnabledProcessors); + } + CpuMpData = GetCpuMpData (); if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) { @@ -2629,6 +2651,10 @@ StartupAllCPUsWorker ( BOOLEAN HasEnabledAp; CPU_STATE ApState; + if (MpTdxIsEnabled ()) { + return EFI_SUCCESS; + } + CpuMpData = GetCpuMpData (); if (FailedCpuList != NULL) { diff --git a/UefiCpuPkg/Library/MpInitLib/MpLibTdx.c b/UefiCpuPkg/Library/MpInitLib/MpLibTdx.c new file mode 100644 index 000000000000..2c4445ff02b6 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpLibTdx.c @@ -0,0 +1,142 @@ +/** @file + CPU MP Initialize Library common functions. + + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, AMD Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include "MpIntelTdx.h" + +#include +#include +#include + + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where information for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ) +{ + EFI_STATUS Status; + TD_RETURN_DATA TdReturnData; + + if (ProcessorInfoBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = MyTdCall(TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status == EFI_SUCCESS); + + if (ProcessorNumber >= TdReturnData.TdInfo.NumVcpus) { + return EFI_NOT_FOUND; + } + + ProcessorInfoBuffer->ProcessorId = ProcessorNumber; + ProcessorInfoBuffer->StatusFlag = 0; + if (ProcessorNumber == 0) { + ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT; + } + ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT; + + // + // Get processor location information + // + GetProcessorLocationByApicId ( + (UINT32)ProcessorNumber, + &ProcessorInfoBuffer->Location.Package, + &ProcessorInfoBuffer->Location.Core, + &ProcessorInfoBuffer->Location.Thread + ); + + if (HealthData != NULL) { + HealthData->Uint32 = 0; + } + + return Status; +} + +/** + Retrieves the number of logical processor in the platform and the number of + those logical processors that are enabled on this boot. This service may only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of logical + processors in the system, including the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical + processors that exist in system, including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ) +{ + EFI_STATUS Status; + TD_RETURN_DATA TdReturnData; + + if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = MyTdCall(TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status == EFI_SUCCESS); + + if (NumberOfProcessors != NULL) { + *NumberOfProcessors = TdReturnData.TdInfo.NumVcpus; + } + if (NumberOfEnabledProcessors != NULL) { + *NumberOfEnabledProcessors = TdReturnData.TdInfo.MaxVcpus; + } + + return Status; +} + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ) +{ + return PcdGetBool (PcdTdxIsEnabled); +} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c b/UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c new file mode 100644 index 000000000000..b00c8deefb5f --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c @@ -0,0 +1,117 @@ +/** @file + CPU MP Initialize Library common functions. + + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, AMD Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include "MpIntelTdx.h" +#include + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where information for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +/** + Retrieves the number of logical processor in the platform and the number of + those logical processors that are enabled on this boot. This service may only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of logical + processors in the system, including the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical + processors that exist in system, including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ) +{ + return FALSE; +} + +/** + 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 + + @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 +MyTdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf index 36fcb96b5852..fe246b74aaef 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -22,10 +22,13 @@ # [Sources.IA32] + MpLibTdxNull.c Ia32/MpFuncs.nasm [Sources.X64] + MpLibTdx.c X64/MpFuncs.nasm + X64/IntelTdcall.nasm [Sources.common] MpEqu.inc @@ -33,6 +36,7 @@ MpLib.c MpLib.h Microcode.c + MpIntelTdx.h [Packages] MdePkg/MdePkg.dec @@ -65,6 +69,7 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdTdxIsEnabled ## CONSUMES [Ppis] gEdkiiPeiShadowMicrocodePpiGuid ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm b/UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm new file mode 100644 index 000000000000..9f83b9e73acb --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm @@ -0,0 +1,120 @@ +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+;* 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) + +%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(MyTdCall) +ASM_PFX(MyTdCall): + 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 -- 2.29.2.windows.2