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:27 -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="202524434" X-IronPort-AV: E=Sophos;i="5.84,315,1620716400"; d="scan'208";a="202524434" 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:27 -0700 X-IronPort-AV: E=Sophos;i="5.84,315,1620716400"; d="scan'208";a="517433987" 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:24 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [PATCH 23/23] OvmfPkg: Update PlatformPei to support TDX Date: Thu, 12 Aug 2021 19:57:02 +0800 Message-Id: <50a57dfb90f362399d19dcdb19aa0063a2a12176.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 Intel TDX has its own requirement in InitializePlatform (PlatformPei). 1. Publish the ram region Host VMM pass the memory region to TDVF in TD Hob. These memory are accepted by TDVF before they're available for access. TDVF publish these memory information in the final hoblist for DXE. 2. Relocate mailbox At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is pre-allocated by host VMM. BSP & APs do the page accept together in that memory region. After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-size memory block which is allocated in the ACPI Nvs memory. APs are waken up and spin around the relocated mailbox waiting for further command. 3. Create PlatformInfoHob PlatformInfoHob contains the TDX specific information, for example, the relocated Mailbox address. gUefiOvmfPkgTdxPlatformGuid is the new GUID added in OvmfPkg.dec for this purpose. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/PlatformPei/FeatureControl.c | 9 +- OvmfPkg/PlatformPei/IntelTdx.c | 268 +++++++++++++++++++++++++ OvmfPkg/PlatformPei/IntelTdxNull.c | 35 ++++ OvmfPkg/PlatformPei/MemDetect.c | 20 +- OvmfPkg/PlatformPei/Platform.c | 2 + OvmfPkg/PlatformPei/Platform.h | 17 ++ OvmfPkg/PlatformPei/PlatformPei.inf | 14 ++ OvmfPkg/PlatformPei/X64/ApRunLoop.nasm | 83 ++++++++ 9 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 OvmfPkg/PlatformPei/IntelTdx.c create mode 100644 OvmfPkg/PlatformPei/IntelTdxNull.c create mode 100644 OvmfPkg/PlatformPei/X64/ApRunLoop.nasm diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index a9765f2a60be..2ad0b5de25e1 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -128,6 +128,7 @@ gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} + gUefiOvmfPkgTdxPlatformGuid = {0xdec9b486, 0x1f16, 0x47c7, {0x8f, 0x68, 0xdf, 0x1a, 0x41, 0x88, 0x8b, 0xa5}} [Ppis] # PPI whose presence in the PPI database signals that the TPM base address diff --git a/OvmfPkg/PlatformPei/FeatureControl.c b/OvmfPkg/PlatformPei/FeatureControl.c index dccf9505dd7b..36451d0c9c24 100644 --- a/OvmfPkg/PlatformPei/FeatureControl.c +++ b/OvmfPkg/PlatformPei/FeatureControl.c @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include "Platform.h" @@ -37,7 +40,11 @@ WriteFeatureControl ( IN OUT VOID *WorkSpace ) { - AsmWriteMsr64 (MSR_IA32_FEATURE_CONTROL, mFeatureControlValue); + if (TdxIsEnabled ()) { + TdVmCall (TDVMCALL_WRMSR, (UINT64) MSR_IA32_FEATURE_CONTROL, mFeatureControlValue, 0, 0, 0); + } else { + AsmWriteMsr64 (MSR_IA32_FEATURE_CONTROL, mFeatureControlValue); + } } /** diff --git a/OvmfPkg/PlatformPei/IntelTdx.c b/OvmfPkg/PlatformPei/IntelTdx.c new file mode 100644 index 000000000000..598286d8ae2b --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdx.c @@ -0,0 +1,268 @@ +/** @file + Initialize Intel TDX support. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Platform.h" + +VOID +EFIAPI +DEBUG_HOBLIST ( + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + DEBUG ((DEBUG_INFO, "HOB(%p) : %x %x\n", Hob, Hob.Header->HobType, Hob.Header->HobLength)); + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + DEBUG ((DEBUG_INFO, "\t: %x %x %llx %llx\n", + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength)); + + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + DEBUG ((DEBUG_INFO, "\t: %llx %llx %x\n", + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength, + Hob.MemoryAllocation->AllocDescriptor.MemoryType)); + break; + default: + break; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } +} + +/** + Transfer the incoming HobList for the TD to the final HobList for Dxe. + The Hobs transferred in this function are ResourceDescriptor hob and + MemoryAllocation hob. + + @param[in] VmmHobList The Hoblist pass the firmware + +**/ +VOID +EFIAPI +TransferTdxHobList ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + EFI_PHYSICAL_ADDRESS PhysicalEnd; + + // + // PcdOvmfSecGhcbBase is used as the TD_HOB in Tdx guest. + // + Hob.Raw = (UINT8 *) (UINTN) PcdGet32 (PcdOvmfSecGhcbBase); + while (!END_OF_HOB_LIST (Hob)) { + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + ResourceAttribute = Hob.ResourceDescriptor->ResourceAttribute; + PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength; + + // + // We mark each resource that we issue AcceptPage to with EFI_RESOURCE_SYSTEM_MEMORY + // + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && + (PhysicalEnd <= BASE_4GB)) { + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_ENCRYPTED; + } + BuildResourceDescriptorHob ( + Hob.ResourceDescriptor->ResourceType, + ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength); + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + BuildMemoryAllocationHob ( + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength, + Hob.MemoryAllocation->AllocDescriptor.MemoryType); + break; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + DEBUG_HOBLIST (GetHobList ()); +} + +/** + + Publish memory regions in Intel TDX guest. + +**/ +VOID +TdxPublishRamRegions ( + VOID + ) +{ + TransferTdxHobList (); + + // + // The memory region defined by PcdOvmfSecGhcbBackupBase is pre-allocated by + // host VMM and used as the td mailbox at the beginning of system boot. + // + BuildMemoryAllocationHob ( + PcdGet32 (PcdOvmfSecGhcbBackupBase), + PcdGet32 (PcdOvmfSecGhcbBackupSize), + EfiACPIMemoryNVS + ); +} + +/** + This function check the system status from QEMU via fw_cfg. + If the system status from QEMU is retrieved, its value is set + into PlatformInfoHob. + + @param[in] PlatformInfoHob The data structure of PlatformInfo hob +**/ +VOID +EFIAPI +CheckSystemStatsForOverride ( + IN EFI_HOB_PLATFORM_INFO * PlatformInfoHob + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + + // + // check for overrides + // + Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize); + if (Status != RETURN_SUCCESS || FwCfgSize != sizeof PlatformInfoHob->SystemStates) { + DEBUG ((DEBUG_INFO, "ACPI using S3/S4 defaults\n")); + return; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (PlatformInfoHob->SystemStates), PlatformInfoHob->SystemStates); +} + +/** + At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is + pre-allocated by host VMM. BSP & APs do the page accept together in that memory + region. + + After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-size + memory block which is allocated in the ACPI Nvs memory. APs are waken up and + spin around the relocated mailbox for further command. + + @return UINT64 Address of the relocated mailbox +**/ +UINT64 +EFIAPI +TdxRelocateMailbox ( + VOID + ) +{ + VOID *Address; + VOID *ApLoopFunc = NULL; + UINT32 RelocationPages; + MP_RELOCATION_MAP RelocationMap; + MP_WAKEUP_MAILBOX *RelocatedMailBox; + + // + // Get information needed to setup aps running in their + // run loop in allocated acpi reserved memory + // Add another page for mailbox + // + AsmGetRelocationMap (&RelocationMap); + RelocationPages = EFI_SIZE_TO_PAGES ((UINT32)RelocationMap.RelocateApLoopFuncSize) + 1; + + Address = AllocatePagesWithMemoryType (EfiACPIMemoryNVS, RelocationPages); + ApLoopFunc = (VOID *) ((UINTN) Address + EFI_PAGE_SIZE); + + CopyMem ( + ApLoopFunc, + RelocationMap.RelocateApLoopFuncAddress, + RelocationMap.RelocateApLoopFuncSize + ); + + DEBUG ((DEBUG_INFO, "Ap Relocation: mailbox %p, loop %p\n", + Address, ApLoopFunc)); + + // + // Initialize mailbox + // + RelocatedMailBox = (MP_WAKEUP_MAILBOX *)Address; + RelocatedMailBox->Command = MpProtectedModeWakeupCommandNoop; + RelocatedMailBox->ApicId = MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID; + RelocatedMailBox->WakeUpVector = 0; + + // + // Wakup APs and have been move to the finalized run loop + // They will spin until guest OS wakes them + // + MpSerializeStart (); + + MpSendWakeupCommand ( + MpProtectedModeWakeupCommandWakeup, + (UINT64)ApLoopFunc, + (UINT64)RelocatedMailBox, + 0, + 0, + 0); + + return (UINT64)RelocatedMailBox; +} + +/** + + This Function checks if TDX is available, if present then it sets + the dynamic PcdTdxIsEnabled and PcdIa32EferChangeAllowed. + + It relocates the td mailbox and create the PlatformInfo Hob which includes + the TDX specific information which will be consumed in DXE phase. + + **/ +VOID +IntelTdxInitialize ( + VOID + ) +{ + EFI_HOB_PLATFORM_INFO PlatformInfoHob; + RETURN_STATUS PcdStatus; + + if (!TdxIsEnabled ()) { + return; + } + + PcdStatus = PcdSetBoolS (PcdTdxIsEnabled, TRUE); + ASSERT_RETURN_ERROR (PcdStatus); + + PcdStatus = PcdSetBoolS (PcdIa32EferChangeAllowed, FALSE); + ASSERT_RETURN_ERROR (PcdStatus); + + ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); + PlatformInfoHob.HostBridgePciDevId = mHostBridgeDevId; + + PlatformInfoHob.RelocatedMailBox = TdxRelocateMailbox (); + + CheckSystemStatsForOverride (&PlatformInfoHob); + + BuildGuidDataHob (&gUefiOvmfPkgTdxPlatformGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO)); +} diff --git a/OvmfPkg/PlatformPei/IntelTdxNull.c b/OvmfPkg/PlatformPei/IntelTdxNull.c new file mode 100644 index 000000000000..871f213fca48 --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdxNull.c @@ -0,0 +1,35 @@ +/** @file + Main SEC phase code. Handles initial TDX Hob List Processing + + Copyright (c) 2008, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +VOID +TdxPublishRamRegions ( + VOID + ) +{ +} + +VOID +IntelTdxInitialize ( + VOID + ) +{ +} + +VOID +AsmGetRelocationMap ( + OUT MP_RELOCATION_MAP *AddressMap + ) +{ +} diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c index 2deec128f464..d36cd362f667 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -35,6 +35,8 @@ Module Name: #include #include #include +#include +#include #include "Platform.h" #include "Cmos.h" @@ -484,6 +486,7 @@ AddressWidthInitialization ( ) { UINT64 FirstNonAddress; + UINT64 TdxSharedPageMask; // // As guest-physical memory size grows, the permanent PEI RAM requirements @@ -511,6 +514,17 @@ AddressWidthInitialization ( if (mPhysMemAddressWidth <= 36) { mPhysMemAddressWidth = 36; } + + if (TdxIsEnabled ()) { + TdxSharedPageMask = TdSharedPageMask (); + if (TdxSharedPageMask == (1ULL << 47)) { + mPhysMemAddressWidth = 48; + } else { + DEBUG ((DEBUG_ERROR, "Currently only PhysMemAddressWidth = 48 is supported in TDX.\n")); + ASSERT (FALSE); + } + } + ASSERT (mPhysMemAddressWidth <= 48); } @@ -815,7 +829,11 @@ InitializeRamRegions ( VOID ) { - QemuInitializeRam (); + if (TdxIsEnabled ()) { + TdxPublishRamRegions (); + } else { + QemuInitializeRam (); + } if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) { // diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index d3a20122a2ea..4be3c4bd1d3c 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "Platform.h" #include "Cmos.h" @@ -742,6 +743,7 @@ InitializePlatform ( InstallClearCacheCallback (); AmdSevInitialize (); + IntelTdxInitialize (); MiscInitialization (); InstallFeatureControlCallback (); diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 8b1d270c2b0b..89121bcb8a41 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -10,6 +10,7 @@ #define _PLATFORM_PEI_H_INCLUDED_ #include +#include VOID AddIoMemoryBaseSizeHob ( @@ -102,6 +103,22 @@ AmdSevInitialize ( VOID ); +VOID +TdxPublishRamRegions ( + VOID + ); + +VOID +AsmGetRelocationMap ( + OUT MP_RELOCATION_MAP *AddressMap + ); + + +VOID +IntelTdxInitialize ( + VOID + ); + extern EFI_BOOT_MODE mBootMode; extern BOOLEAN mS3Supported; diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 89d1f7636870..80f2b3a52ac9 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -34,6 +34,13 @@ Platform.c Platform.h +[Sources.IA32, Sources.EBC] + IntelTdxNull.c + +[Sources.X64] + IntelTdx.c + X64/ApRunLoop.nasm + [Packages] EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec @@ -44,6 +51,7 @@ [Guids] gEfiMemoryTypeInformationGuid + gUefiOvmfPkgTdxPlatformGuid [LibraryClasses] BaseLib @@ -62,6 +70,10 @@ MtrrLib MemEncryptSevLib PcdLib + TdxProbeLib + TdxMailboxLib + TdxLib + MemoryAllocationLib [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase @@ -106,6 +118,8 @@ gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled + gUefiCpuPkgTokenSpaceGuid.PcdTdxIsEnabled + gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/OvmfPkg/PlatformPei/X64/ApRunLoop.nasm b/OvmfPkg/PlatformPei/X64/ApRunLoop.nasm new file mode 100644 index 000000000000..adf4f03c3a9e --- /dev/null +++ b/OvmfPkg/PlatformPei/X64/ApRunLoop.nasm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ApRunLoop.nasm +; +; Abstract: +; +; This is the assembly code for run loop for APs in the guest TD +; +;------------------------------------------------------------------------------- + +%include "TdxCommondefs.inc" + +DEFAULT REL + +SECTION .text + +BITS 64 + +%macro tdcall 0 + db 0x66, 0x0f, 0x01, 0xcc +%endmacro + +; +; Relocated Ap Mailbox loop +; +; @param[in] RBX: Relocated mailbox address +; @param[in] RBP: vCpuId +; +; @return None This routine does not return +; +global ASM_PFX(AsmRelocateApMailBoxLoop) +ASM_PFX(AsmRelocateApMailBoxLoop): +AsmRelocateApMailBoxLoopStart: + + ; + ; TdCall[TDINFO] to get the vCpuId + ; + ;mov rax, 1 + ;tdcall + ; + ; R8 [31:0] NUM_VCPUS + ; [63:32] MAX_VCPUS + ; R9 [31:0] VCPU_INDEX + ; + + mov r8, rbp +MailBoxLoop: + ; Spin until command set + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandNoop + je MailBoxLoop + ; Determine if this is a broadcast or directly for my apic-id, if not, ignore + cmp dword [rbx + ApicidOffset], MailboxApicidBroadcast + je MailBoxProcessCommand + cmp dword [rbx + ApicidOffset], r8d + jne MailBoxLoop +MailBoxProcessCommand: + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandWakeup + je MailBoxWakeUp + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandSleep + je MailBoxSleep + ; Don't support this command, so ignore + jmp MailBoxLoop +MailBoxWakeUp: + mov rax, [rbx + WakeupVectorOffset] + jmp rax +MailBoxSleep: + jmp $ +BITS 64 +AsmRelocateApMailBoxLoopEnd: + +;------------------------------------------------------------------------------------- +; AsmGetRelocationMap (&RelocationMap); +;------------------------------------------------------------------------------------- +global ASM_PFX(AsmGetRelocationMap) +ASM_PFX(AsmGetRelocationMap): + lea rax, [ASM_PFX(AsmRelocateApMailBoxLoopStart)] + mov qword [rcx], rax + mov qword [rcx + 8h], AsmRelocateApMailBoxLoopEnd - AsmRelocateApMailBoxLoopStart + ret -- 2.29.2.windows.2