From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web11.17835.1646036243454643146 for ; Mon, 28 Feb 2022 00:17:23 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=cV91WRXC; spf=pass (domain: intel.com, ip: 192.55.52.43, mailfrom: min.m.xu@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646036243; x=1677572243; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5Lv19neryxmypdNKHk8NDXeqOk1peojKJDwHHDj8HEg=; b=cV91WRXCuFnl41GLFLdj5o27BpMJj71uuzq19jf3Q/zTpk97P3zlQ+wB Ow5zi+H1f8t4HvfgANwfewGZWoPc9RSAznkKxBAplMKxNakaayMqrrrOQ enF9LEuvMU+qmTgehvKs4RUz6upfVMt3Z73OFTj85xyzTYwx4KTattyVq 1Ezmwhwd0KWiYNA1eE9E2EX9cQbUj9xpNITAAxIrA9Jc8gT+UoR5AdTHU wX0vZ1y9tnbag2DV1sZPDcnTm6sc7nSCPvjU1mULZ1wwhO3qUlIi8D/Si BEegy5tO3sKTJ0AGUhNL+gjXfVISYpqs1LnayDBTcV3Oqi8jlQRk0do8L g==; X-IronPort-AV: E=McAfee;i="6200,9189,10271"; a="339268979" X-IronPort-AV: E=Sophos;i="5.90,142,1643702400"; d="scan'208";a="339268979" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Feb 2022 00:17:21 -0800 X-IronPort-AV: E=Sophos;i="5.90,142,1643702400"; d="scan'208";a="550140122" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.238.2.184]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Feb 2022 00:17:13 -0800 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Michael D Kinney , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Gerd Hoffmann Subject: [PATCH V4 05/10] OvmfPkg/IntelTdx: Add Sec to bring up both Legacy and Tdx guest Date: Mon, 28 Feb 2022 16:16:26 +0800 Message-Id: <20220228081631.681-6-min.m.xu@intel.com> X-Mailer: git-send-email 2.29.2.windows.2 In-Reply-To: <20220228081631.681-1-min.m.xu@intel.com> References: <20220228081631.681-1-min.m.xu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 OvmfPkg/IntelTdx/Sec is a simplied version of OvmfPkg/Sec. There are below differences between these 2 Sec - IntelTdx/Sec only supports Legacy guest and Tdx guest in X64. - IntelTdx/Sec calls PeilessStartup () to jump from SEC to DXE directly. - IntelTdx/Sec uses MemoryAllocationLib / HobLib / PrePiLib in EmbeddedPkg. Cc: Michael D Kinney Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Gerd Hoffmann Acked-by: Gerd Hoffmann Signed-off-by: Min Xu OvmfPkg/IntelTdx: Sec/SecMain --- OvmfPkg/IntelTdx/Sec/SecMain.c | 198 +++++++++++++++++++++++++ OvmfPkg/IntelTdx/Sec/SecMain.inf | 61 ++++++++ OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm | 151 +++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 OvmfPkg/IntelTdx/Sec/SecMain.c create mode 100644 OvmfPkg/IntelTdx/Sec/SecMain.inf create mode 100644 OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.c b/OvmfPkg/IntelTdx/Sec/SecMain.c new file mode 100644 index 000000000000..26d56be335e1 --- /dev/null +++ b/OvmfPkg/IntelTdx/Sec/SecMain.c @@ -0,0 +1,198 @@ +/** @file + Main SEC phase code. Transitions to PEI. + + Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SEC_IDT_ENTRY_COUNT 34 + +typedef struct _SEC_IDT_TABLE { + EFI_PEI_SERVICES *PeiService; + IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; +} SEC_IDT_TABLE; + +// +// Template of an IDT entry pointing to 10:FFFFFFE4h. +// +IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { + { // Bits + 0xffe4, // OffsetLow + 0x10, // Selector + 0x0, // Reserved_0 + IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType + 0xffff // OffsetHigh + } +}; + +VOID +EFIAPI +SecCoreStartupWithStack ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, + IN VOID *TopOfCurrentStack + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + SEC_IDT_TABLE IdtTableInStack; + IA32_DESCRIPTOR IdtDescriptor; + UINT32 Index; + volatile UINT8 *Table; + + if (TdIsEnabled ()) { + // + // For Td guests, the memory map info is in TdHobLib. It should be processed + // first so that the memory is accepted. Otherwise access to the unaccepted + // memory will trigger tripple fault. + // + if (ProcessTdxHobList () != EFI_SUCCESS) { + CpuDeadLoop (); + } + } + + // + // To ensure SMM can't be compromised on S3 resume, we must force re-init of + // the BaseExtractGuidedSectionLib. Since this is before library contructors + // are called, we must use a loop rather than SetMem. + // + Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress); + for (Index = 0; + Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize); + ++Index) + { + Table[Index] = 0; + } + + // + // Initialize IDT - Since this is before library constructors are called, + // we use a loop rather than CopyMem. + // + IdtTableInStack.PeiService = NULL; + + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) { + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memcpy() + // + CONST UINT8 *Src; + volatile UINT8 *Dst; + UINTN Byte; + + Src = (CONST UINT8 *)&mIdtEntryTemplate; + Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index]; + + for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) { + Dst[Byte] = Src[Byte]; + } + } + + IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + ProcessLibraryConstructorList (NULL, NULL); + + // + // Load the IDTR. + // + AsmWriteIdtr (&IdtDescriptor); + + if (TdIsEnabled ()) { + // + // InitializeCpuExceptionHandlers () should be called in Td guests so that + // #VE exceptions can be handled correctly. + // + InitializeCpuExceptionHandlers (NULL); + } + + DEBUG (( + DEBUG_INFO, + "SecCoreStartupWithStack(0x%x, 0x%x)\n", + (UINT32)(UINTN)BootFv, + (UINT32)(UINTN)TopOfCurrentStack + )); + + // + // Initialize floating point operating environment + // to be compliant with UEFI spec. + // + InitializeFloatingPointUnits (); + + // + // ASSERT that the Page Tables were set by the reset vector code to + // the address we expect. + // + ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase)); + + // + // |-------------| <-- TopOfCurrentStack + // | Stack | 32k + // |-------------| + // | Heap | 32k + // |-------------| <-- SecCoreData.TemporaryRamBase + // + + ASSERT ( + (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) + + PcdGet32 (PcdOvmfSecPeiTempRamSize)) == + (UINTN)TopOfCurrentStack + ); + + // + // Initialize SEC hand-off state + // + SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); + + SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize); + SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); + + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; + SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.BootFirmwareVolumeBase = BootFv; + SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength; + + // + // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled + // + IoWrite8 (0x21, 0xff); + IoWrite8 (0xA1, 0xff); + + // + // Initialize Local APIC Timer hardware and disable Local APIC Timer + // interrupts before initializing the Debug Agent and the debug timer is + // enabled. + // + InitializeApicTimer (0, MAX_UINT32, TRUE, 5); + DisableApicTimerInterrupt (); + + PeilessStartup (&SecCoreData); + + ASSERT (FALSE); + CpuDeadLoop (); +} diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.inf b/OvmfPkg/IntelTdx/Sec/SecMain.inf new file mode 100644 index 000000000000..df2e749c3505 --- /dev/null +++ b/OvmfPkg/IntelTdx/Sec/SecMain.inf @@ -0,0 +1,61 @@ +## @file +# SEC Driver +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecMain + FILE_GUID = 69d96630-eb64-4b33-8491-13a5cf023dcf + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + ENTRY_POINT = SecMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + SecMain.c + X64/SecEntry.nasm + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PcdLib + UefiCpuLib + DebugAgentLib + IoLib + PeCoffLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + ExtractGuidedSectionLib + LocalApicLib + MemEncryptSevLib + CpuExceptionHandlerLib + PeilessStartupLib + PlatformInitLib + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress + gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase diff --git a/OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm b/OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm new file mode 100644 index 000000000000..4528fec309a0 --- /dev/null +++ b/OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm @@ -0,0 +1,151 @@ +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+;* SPDX-License-Identifier: BSD-2-Clause-Patent +;* +;* CpuAsm.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ + +#include +%include "TdxCommondefs.inc" + +DEFAULT REL +SECTION .text + +extern ASM_PFX(SecCoreStartupWithStack) + +%macro tdcall 0 + db 0x66, 0x0f, 0x01, 0xcc +%endmacro + +; +; SecCore Entry Point +; +; Processor is in flat protected mode +; +; @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test) +; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +; @param[in] RBP Pointer to the start of the Boot Firmware Volume +; @param[in] DS Selector allowing flat access to all addresses +; @param[in] ES Selector allowing flat access to all addresses +; @param[in] FS Selector allowing flat access to all addresses +; @param[in] GS Selector allowing flat access to all addresses +; @param[in] SS Selector allowing flat access to all addresses +; +; @return None This routine does not return +; +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + + ; + ; Guest type is stored in OVMF_WORK_AREA + ; + %define OVMF_WORK_AREA FixedPcdGet32 (PcdOvmfWorkAreaBase) + %define VM_GUEST_TYPE_TDX 2 + mov eax, OVMF_WORK_AREA + cmp byte[eax], VM_GUEST_TYPE_TDX + jne InitStack + + mov rax, TDCALL_TDINFO + tdcall + + ; + ; R8 [31:0] NUM_VCPUS + ; [63:32] MAX_VCPUS + ; R9 [31:0] VCPU_INDEX + ; Td Guest set the VCPU0 as the BSP, others are the APs + ; APs jump to spinloop and get released by DXE's MpInitLib + ; + mov rax, r9 + and rax, 0xffff + test rax, rax + jne ParkAp + +InitStack: + + ; + ; Fill the temporary RAM with the initial stack value. + ; The loop below will seed the heap as well, but that's harmless. + ; + mov rax, (FixedPcdGet32 (PcdInitValueInTempStack) << 32) | FixedPcdGet32 (PcdInitValueInTempStack) + ; qword to store + mov rdi, FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) ; base address, + ; relative to + ; ES + mov rcx, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 8 ; qword count + cld ; store from base + ; up + rep stosq + + ; + ; Load temporary RAM stack based on PCDs + ; + %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + \ + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) + mov rsp, SEC_TOP_OF_STACK + nop + + ; + ; Setup parameters and call SecCoreStartupWithStack + ; rcx: BootFirmwareVolumePtr + ; rdx: TopOfCurrentStack + ; + mov rcx, rbp + mov rdx, rsp + sub rsp, 0x20 + call ASM_PFX(SecCoreStartupWithStack) + + ; + ; Note: BSP never gets here. APs will be unblocked by DXE + ; + ; R8 [31:0] NUM_VCPUS + ; [63:32] MAX_VCPUS + ; R9 [31:0] VCPU_INDEX + ; +ParkAp: + + mov rbp, r9 + +.do_wait_loop: + mov rsp, FixedPcdGet32 (PcdOvmfSecGhcbBackupBase) + + ; + ; register itself in [rsp + CpuArrivalOffset] + ; + mov rax, 1 + lock xadd dword [rsp + CpuArrivalOffset], eax + inc eax + +.check_arrival_cnt: + cmp eax, r8d + je .check_command + mov eax, dword[rsp + CpuArrivalOffset] + jmp .check_arrival_cnt + +.check_command: + mov eax, dword[rsp + CommandOffset] + cmp eax, MpProtectedModeWakeupCommandNoop + je .check_command + + cmp eax, MpProtectedModeWakeupCommandWakeup + je .do_wakeup + + ; Don't support this command, so ignore + jmp .check_command + +.do_wakeup: + ; + ; BSP sets these variables before unblocking APs + ; RAX: WakeupVectorOffset + ; RBX: Relocated mailbox address + ; RBP: vCpuId + ; + mov rax, 0 + mov eax, dword[rsp + WakeupVectorOffset] + mov rbx, [rsp + WakeupArgsRelocatedMailBox] + nop + jmp rax + jmp $ -- 2.29.2.windows.2