From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web12.10811.1639400329822569312 for ; Mon, 13 Dec 2021 04:59:21 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.com header.s=intel header.b=DcfLhDqy; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: min.m.xu@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1639400361; x=1670936361; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Kmbfz+ikp1kz0M5N2MA466hWSWQvolDyxWutFdrn5qA=; b=DcfLhDqy8bWjCt+r9aeqtVtsVZ75foxvE6yfaFvU2WryixB6XOf1f/gf 8IrOR0huMvBdjGcqvWbV4ZgxctFokckwDSPKCaOBXKaOU0BFvbJO3hy0+ odCZhJwN6tbKMGsUeL1UPo0evZrAWj1dr4Pe40x/02DNjqlsX8y0ekIVE l1KUCfXTSuRAVDbEkHvAcVDdKhpeE3d12oEXfE7DD8cHfkYid0GOXLkCK Qa317IWYpfB5ETLRIDH+U7Rrfwew8wxoAk2MzurAkRfkaTWHyAoJgvdhw 6NVu3pR9rfNZaE3GJIkPsFVuDWbIBNG7bY7b8QGzH3bJQeLJTe/39DSq0 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10196"; a="225584963" X-IronPort-AV: E=Sophos;i="5.88,202,1635231600"; d="scan'208";a="225584963" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Dec 2021 04:59:20 -0800 X-IronPort-AV: E=Sophos;i="5.88,202,1635231600"; d="scan'208";a="517738908" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.249.173.142]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Dec 2021 04:59:18 -0800 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 , Gerd Hoffmann Subject: [PATCH V4 22/31] OvmfPkg: Update PlatformPei to support TDX Date: Mon, 13 Dec 2021 20:56:53 +0800 Message-Id: <94bb5cbbb19bb7b14513082b386554fc59168eb4.1639399598.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-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. 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 Cc: Gerd Hoffmann Signed-off-by: Min Xu --- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/PlatformPei/FeatureControl.c | 8 +- OvmfPkg/PlatformPei/IntelTdx.c | 223 +++++++++++++++++++++++++++ OvmfPkg/PlatformPei/IntelTdxNull.c | 49 ++++++ OvmfPkg/PlatformPei/MemDetect.c | 56 +++++-- OvmfPkg/PlatformPei/Platform.c | 1 + OvmfPkg/PlatformPei/Platform.h | 22 +++ OvmfPkg/PlatformPei/PlatformPei.inf | 12 ++ 8 files changed, 359 insertions(+), 13 deletions(-) create mode 100644 OvmfPkg/PlatformPei/IntelTdx.c create mode 100644 OvmfPkg/PlatformPei/IntelTdxNull.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 7a4a58c7a2ce..37427d71a355 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -129,6 +129,7 @@ gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} gConfidentialComputingSevSnpBlobGuid = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}} + 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 9af58c2655f8..b351ee1c7288 100644 --- a/OvmfPkg/PlatformPei/FeatureControl.c +++ b/OvmfPkg/PlatformPei/FeatureControl.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "Platform.h" @@ -37,7 +39,11 @@ WriteFeatureControl ( IN OUT VOID *WorkSpace ) { - AsmWriteMsr64 (MSR_IA32_FEATURE_CONTROL, mFeatureControlValue); + if (PlatformPeiIsTdxGuest ()) { + 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..e250ecac3ae3 --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdx.c @@ -0,0 +1,223 @@ +/** @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 +#include +#include "Platform.h" + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ) +{ + CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; + + CcWorkAreaHeader = (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *)FixedPcdGet32 (PcdOvmfWorkAreaBase); + return (CcWorkAreaHeader != NULL && CcWorkAreaHeader->GuestType == GUEST_TYPE_INTEL_TDX); +} + +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; + + // + // 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; + + 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); +} + +/** + + 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 (!PlatformPeiIsTdxGuest ()) { + return; + } + + PcdStatus = PcdSet64S (PcdConfidentialComputingGuestAttr, CCAttrIntelTdx); + ASSERT_RETURN_ERROR (PcdStatus); + + PcdStatus = PcdSetBoolS (PcdIa32EferChangeAllowed, FALSE); + ASSERT_RETURN_ERROR (PcdStatus); + + PcdStatus = PcdSet64S (PcdTdxSharedBitMask, TdSharedPageMask ()); + ASSERT_RETURN_ERROR (PcdStatus); + + ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); + PlatformInfoHob.HostBridgePciDevId = mHostBridgeDevId; + + 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..f887afae363a --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdxNull.c @@ -0,0 +1,49 @@ +/** @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 + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ) +{ + return FALSE; +} + +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 934d5c196570..9227fa260ccd 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -36,6 +36,7 @@ Module Name: #include #include #include +#include #include "Platform.h" #include "Cmos.h" @@ -556,7 +557,19 @@ AddressWidthInitialization ( mPhysMemAddressWidth = 36; } + #if defined (MDE_CPU_X64) + if (PlatformPeiIsTdxGuest ()) { + if (TdSharedPageMask () == (1ULL << 47)) { + mPhysMemAddressWidth = 48; + } else { + mPhysMemAddressWidth = 52; + } + } + + ASSERT (mPhysMemAddressWidth <= 52); + #else ASSERT (mPhysMemAddressWidth <= 48); + #endif } /** @@ -572,8 +585,10 @@ GetPeiMemoryCap ( UINT32 RegEax; UINT32 RegEdx; UINT32 Pml4Entries; + UINT32 Pml5Entries; UINT32 PdpEntries; UINTN TotalPages; + UINT8 PhysicalAddressBits; // // If DXE is 32-bit, then just return the traditional 64 MB cap. @@ -602,20 +617,33 @@ GetPeiMemoryCap ( } } - if (mPhysMemAddressWidth <= 39) { - Pml4Entries = 1; - PdpEntries = 1 << (mPhysMemAddressWidth - 30); - ASSERT (PdpEntries <= 0x200); + PhysicalAddressBits = mPhysMemAddressWidth; + Pml5Entries = 1; + + if (PhysicalAddressBits > 48) { + Pml5Entries = (UINT32)LShiftU64 (1, PhysicalAddressBits - 48); + PhysicalAddressBits = 48; + } + + Pml4Entries = 1; + if (PhysicalAddressBits > 39) { + Pml4Entries = (UINT32)LShiftU64 (1, PhysicalAddressBits - 39); + PhysicalAddressBits = 39; + } + + PdpEntries = 1; + ASSERT (PhysicalAddressBits > 30); + PdpEntries = (UINT32)LShiftU64 (1, PhysicalAddressBits - 30); + + // + // Pre-allocate big pages to avoid later allocations. + // + if (!Page1GSupport) { + TotalPages = ((PdpEntries + 1) * Pml4Entries + 1) * Pml5Entries + 1; } else { - Pml4Entries = 1 << (mPhysMemAddressWidth - 39); - ASSERT (Pml4Entries <= 0x200); - PdpEntries = 512; + TotalPages = (Pml4Entries + 1) * Pml5Entries + 1; } - TotalPages = Page1GSupport ? Pml4Entries + 1 : - (PdpEntries + 1) * Pml4Entries + 1; - ASSERT (TotalPages <= 0x40201); - // // Add 64 MB for miscellaneous allocations. Note that for // mPhysMemAddressWidth values close to 36, the cap will actually be @@ -876,7 +904,11 @@ InitializeRamRegions ( VOID ) { - QemuInitializeRam (); + if (PlatformPeiIsTdxGuest ()) { + TdxPublishRamRegions (); + } else { + QemuInitializeRam (); + } SevInitializeRam (); diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 906f64615de7..70e3eae0f0fb 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -792,6 +792,7 @@ InitializePlatform ( InstallClearCacheCallback (); AmdSevInitialize (); + IntelTdxInitialize (); MiscInitialization (); InstallFeatureControlCallback (); diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 24e4da4e1d93..add04926f8f0 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,27 @@ AmdSevInitialize ( VOID ); +VOID +TdxPublishRamRegions ( + VOID + ); + +VOID +IntelTdxInitialize ( + VOID + ); + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ); + extern EFI_BOOT_MODE mBootMode; VOID diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 1c56ba275835..696d833bdb6d 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -34,6 +34,12 @@ Platform.c Platform.h +[Sources.IA32, Sources.EBC] + IntelTdxNull.c + +[Sources.X64] + IntelTdx.c + [Packages] EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec @@ -44,6 +50,7 @@ [Guids] gEfiMemoryTypeInformationGuid + gUefiOvmfPkgTdxPlatformGuid [LibraryClasses] BaseLib @@ -64,6 +71,9 @@ PcdLib VmgExitLib +[LibraryClasses.X64] + TdxLib + [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize @@ -109,6 +119,8 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures + gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed + gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask [FixedPcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase -- 2.29.2.windows.2