Hi, Michael & Liming & Zhiguang I am doing the TDVF upstreaming and this commit is in MdeModulePkg. You're the maintainer/reviewer of MdeModulePkg. Your comments to this patch is great helpful. The complete code is at: https://github.com/mxu9/edk2/tree/tdvf_wave2.v6
Thanks Min > RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 > > Introduce basic Tdx functions in BaseLib: > - TdCall () > - TdVmCall () > - TdIsEnabled () > > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Liming Gao <gaolim...@byosoft.com.cn> > Cc: Zhiguang Liu <zhiguang....@intel.com> > Cc: Brijesh Singh <brijesh.si...@amd.com> > Cc: Erdem Aktas <erdemak...@google.com> > Cc: James Bottomley <j...@linux.ibm.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Tom Lendacky <thomas.lenda...@amd.com> > Cc: Gerd Hoffmann <kra...@redhat.com> > Acked-by: Gerd Hoffmann <kra...@redhat.com> > Signed-off-by: Min Xu <min.m...@intel.com> > --- > MdePkg/Include/Library/BaseLib.h | 62 ++++++++++ > MdePkg/Library/BaseLib/BaseLib.inf | 11 ++ > MdePkg/Library/BaseLib/IntelTdxNull.c | 83 +++++++++++++ > MdePkg/Library/BaseLib/X64/TdCall.nasm | 85 +++++++++++++ > MdePkg/Library/BaseLib/X64/TdProbe.c | 62 ++++++++++ > MdePkg/Library/BaseLib/X64/TdVmcall.nasm | 145 > +++++++++++++++++++++++ > 6 files changed, 448 insertions(+) > create mode 100644 MdePkg/Library/BaseLib/IntelTdxNull.c > create mode 100644 MdePkg/Library/BaseLib/X64/TdCall.nasm > create mode 100644 MdePkg/Library/BaseLib/X64/TdProbe.c > create mode 100644 MdePkg/Library/BaseLib/X64/TdVmcall.nasm > > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index 6aa0d972186e..bd762843198f 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -4759,6 +4759,68 @@ SpeculationBarrier ( > 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 > +**/ > +UINTN > +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 > + > +**/ > +UINTN > +EFIAPI > +TdVmCall ( > + IN UINT64 Leaf, > + IN UINT64 Arg1, > + IN UINT64 Arg2, > + IN UINT64 Arg3, > + IN UINT64 Arg4, > + IN OUT VOID *Results > + ); > + > +/** > + Probe if TD is enabled. > + > + @return TRUE TD is enabled. > + @return FALSE TD is not enabled. > +**/ > +BOOLEAN > +EFIAPI > +TdIsEnabled ( > + VOID > + ); > + > #if defined (MDE_CPU_X64) > // > // The page size for the PVALIDATE instruction diff --git > a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf > index cebda3b210c1..1185f13204df 100644 > --- a/MdePkg/Library/BaseLib/BaseLib.inf > +++ b/MdePkg/Library/BaseLib/BaseLib.inf > @@ -210,6 +210,7 @@ > X86RdRand.c > X86PatchInstruction.c > X86SpeculationBarrier.c > + IntelTdxNull.c > > [Sources.X64] > X64/Thunk16.nasm > @@ -293,6 +294,9 @@ > X64/ReadCr0.nasm| MSFT > X64/ReadEflags.nasm| MSFT > > + X64/TdCall.nasm > + X64/TdVmcall.nasm > + X64/TdProbe.c > > X64/Non-existing.c > Math64.c > @@ -333,6 +337,7 @@ > Ebc/SpeculationBarrier.c > Unaligned.c > Math64.c > + IntelTdxNull.c > > [Sources.ARM] > Arm/InternalSwitchStack.c > @@ -370,6 +375,8 @@ > Arm/MemoryFence.S | GCC > Arm/SpeculationBarrier.S | GCC > > + IntelTdxNull.c > + > [Sources.AARCH64] > Arm/InternalSwitchStack.c > Arm/Unaligned.c > @@ -393,6 +400,8 @@ > AArch64/CpuBreakpoint.asm | MSFT > AArch64/SpeculationBarrier.asm | MSFT > > + IntelTdxNull.c > + > [Sources.RISCV64] > Math64.c > Unaligned.c > @@ -409,6 +418,8 @@ > RiscV64/RiscVInterrupt.S | GCC > RiscV64/FlushCache.S | GCC > > + IntelTdxNull.c > + > [Packages] > MdePkg/MdePkg.dec > > diff --git a/MdePkg/Library/BaseLib/IntelTdxNull.c > b/MdePkg/Library/BaseLib/IntelTdxNull.c > new file mode 100644 > index 000000000000..ec95470bd43e > --- /dev/null > +++ b/MdePkg/Library/BaseLib/IntelTdxNull.c > @@ -0,0 +1,83 @@ > +/** @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 <Uefi/UefiBaseType.h> > + > +/** > + 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 > +**/ > +UINTN > +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 > + > +**/ > +UINTN > +EFIAPI > +TdVmCall ( > + IN UINT64 Leaf, > + IN UINT64 Arg1, > + IN UINT64 Arg2, > + IN UINT64 Arg3, > + IN UINT64 Arg4, > + IN OUT VOID *Results > + ) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + Probe if TD is enabled. > + > + @return TRUE TD is enabled. > + @return FALSE TD is not enabled. > +**/ > +BOOLEAN > +EFIAPI > +TdIsEnabled ( > + ) > +{ > + return FALSE; > +} > diff --git a/MdePkg/Library/BaseLib/X64/TdCall.nasm > b/MdePkg/Library/BaseLib/X64/TdCall.nasm > new file mode 100644 > index 000000000000..e8a094b0eb3f > --- /dev/null > +++ b/MdePkg/Library/BaseLib/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/BaseLib/X64/TdProbe.c > b/MdePkg/Library/BaseLib/X64/TdProbe.c > new file mode 100644 > index 000000000000..a1cf02717bf2 > --- /dev/null > +++ b/MdePkg/Library/BaseLib/X64/TdProbe.c > @@ -0,0 +1,62 @@ > +/** @file > + > + Copyright (c) 2020-2021, Intel Corporation. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Library/BaseLib.h> > +#include <Register/Intel/Cpuid.h> > + > +/** > + Probe if TD is enabled. > + > + @return TRUE TD is enabled. > + @return FALSE TD is not enabled. > +**/ > +BOOLEAN > +EFIAPI > +TdIsEnabled ( > + ) > +{ > + UINT32 Eax; > + UINT32 Ebx; > + UINT32 Ecx; > + UINT32 Edx; > + UINT32 LargestEax; > + BOOLEAN TdEnabled; > + > + TdEnabled = FALSE; > + > + do { > + AsmCpuid (CPUID_SIGNATURE, &LargestEax, &Ebx, &Ecx, &Edx); > + > + if ( (Ebx != CPUID_SIGNATURE_GENUINE_INTEL_EBX) > + || (Edx != CPUID_SIGNATURE_GENUINE_INTEL_EDX) > + || (Ecx != CPUID_SIGNATURE_GENUINE_INTEL_ECX)) > + { > + break; > + } > + > + AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &Ecx, NULL); > + if ((Ecx & BIT31) == 0) { > + break; > + } > + > + if (LargestEax < 0x21) { > + break; > + } > + > + AsmCpuidEx (0x21, 0, &Eax, &Ebx, &Ecx, &Edx); > + if ( (Ebx != SIGNATURE_32 ('I', 'n', 't', 'e')) > + || (Edx != SIGNATURE_32 ('l', 'T', 'D', 'X')) > + || (Ecx != SIGNATURE_32 (' ', ' ', ' ', ' '))) > + { > + break; > + } > + > + TdEnabled = TRUE; > + } while (FALSE); > + > + return TdEnabled; > +} > diff --git a/MdePkg/Library/BaseLib/X64/TdVmcall.nasm > b/MdePkg/Library/BaseLib/X64/TdVmcall.nasm > new file mode 100644 > index 000000000000..5ecc10b17193 > --- /dev/null > +++ b/MdePkg/Library/BaseLib/X64/TdVmcall.nasm > @@ -0,0 +1,145 @@ > +;---------------------------------------------------------------------- > +-------- > +;* > +;* 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 > + > +%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 > -- > 2.29.2.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#86873): https://edk2.groups.io/g/devel/message/86873 Mute This Topic: https://groups.io/mt/89252021/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-