From 11418892567a83b2952a1c59766095c4b19d59d6 Mon Sep 17 00:00:00 2001 From: Jiaqi Gao Date: Wed, 21 Apr 2021 14:23:59 +0800 Subject: [PATCH 1/5] OvmfPkg/Library/TdxStartupLib: Add lazy memory accept to the TDVF. Add unaccepted memory type to several structures and macro definitions to indicate the unaccepted memory. SEC Phase: Modify the Hob process function to partially accept memory. Modify the Hob transfer function to build different types of system memory Hobs for DXE phase, system memory is split to type of system memory and unaccepted memory. DXE Phase: Add case of unaccepted memory in the GCD memory service process and memory map. --- MdeModulePkg/Core/Dxe/Gcd/Gcd.c | 4 + MdeModulePkg/Core/Dxe/Mem/Page.c | 28 ++++ MdePkg/Include/Pi/PiDxeCis.h | 1 + MdePkg/Include/Pi/PiHob.h | 3 +- MdePkg/Include/Uefi/UefiMultiPhase.h | 5 + OvmfPkg/Library/TdxStartupLib/Hob.c | 147 +++++++++++++----- .../Library/TdxStartupLib/TdxStartupLib.inf | 13 +- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/OvmfPkgX64.dsc | 5 +- .../UefiShellDebug1CommandsLib/MemMap.c | 6 + 10 files changed, 170 insertions(+), 43 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index 1b9d591754c7..f20106dfecda 100644 --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c @@ -115,6 +115,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = { "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo "PersisMem", // EfiGcdMemoryTypePersistent "MoreRelia", // EfiGcdMemoryTypeMoreReliable + "Unaccepte", // EfiGcdMemoryTypeUnaccepted "Unknown " // EfiGcdMemoryTypeMaximum }; @@ -2563,6 +2564,9 @@ CoreInitializeGcdServices ( case EFI_RESOURCE_MEMORY_RESERVED: GcdMemoryType = EfiGcdMemoryTypeReserved; break; + case EFI_RESOURCE_MEMORY_UNACCEPTED: + GcdMemoryType = EfiGcdMemoryTypeUnaccepted; + break; case EFI_RESOURCE_IO: GcdIoType = EfiGcdIoTypeIo; break; diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index a749ffd6e32e..1ac579c65fba 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -61,6 +61,7 @@ EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = { { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiPersistentMemory + { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiUnacceptedMemory { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType }; @@ -83,6 +84,7 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = { { EfiMemoryMappedIOPortSpace, 0 }, { EfiPalCode, 0 }, { EfiPersistentMemory, 0 }, + { EfiGcdMemoryTypeUnaccepted, 0 }, { EfiMaxMemoryType, 0 } }; // @@ -1912,6 +1914,32 @@ CoreGetMemoryMap ( // MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); } + + if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeUnaccepted) { + // + // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR, + // it will be recorded as page PhysicalStart and NumberOfPages. + // + ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0); + ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0); + + // + // Create EFI_MEMORY_DESCRIPTOR for every Unaccepted GCD entries + // + MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress; + MemoryMap->VirtualStart = 0; + MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = MergeGcdMapEntry.Attributes | + (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO | + EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB)); + MemoryMap->Type = EfiUnacceptedMemory; + + // + // Check to see if the new Memory Map Descriptor can be merged with an + // existing descriptor if they are adjacent and have the same attributes + // + MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); + } if (Link == &mGcdMemorySpaceMap) { // // break loop when arrive at head. diff --git a/MdePkg/Include/Pi/PiDxeCis.h b/MdePkg/Include/Pi/PiDxeCis.h index 1682211d92af..c600e00dbc76 100644 --- a/MdePkg/Include/Pi/PiDxeCis.h +++ b/MdePkg/Include/Pi/PiDxeCis.h @@ -56,6 +56,7 @@ typedef enum { /// system. If all memory has the same reliability, then this bit is not used. /// EfiGcdMemoryTypeMoreReliable, + EfiGcdMemoryTypeUnaccepted, EfiGcdMemoryTypeMaximum } EFI_GCD_MEMORY_TYPE; diff --git a/MdePkg/Include/Pi/PiHob.h b/MdePkg/Include/Pi/PiHob.h index 62c07742a688..dd0830d3a004 100644 --- a/MdePkg/Include/Pi/PiHob.h +++ b/MdePkg/Include/Pi/PiHob.h @@ -234,7 +234,8 @@ typedef UINT32 EFI_RESOURCE_TYPE; #define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004 #define EFI_RESOURCE_MEMORY_RESERVED 0x00000005 #define EFI_RESOURCE_IO_RESERVED 0x00000006 -#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000007 +#define EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007 +#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000008 /// /// A type of recount attribute type. diff --git a/MdePkg/Include/Uefi/UefiMultiPhase.h b/MdePkg/Include/Uefi/UefiMultiPhase.h index 50e4d700a62f..16b33f37040c 100644 --- a/MdePkg/Include/Uefi/UefiMultiPhase.h +++ b/MdePkg/Include/Uefi/UefiMultiPhase.h @@ -103,6 +103,11 @@ typedef enum { /// however it happens to also support byte-addressable non-volatility. /// EfiPersistentMemory, + /// + /// A memory region that describes system memory that has not been accepted + /// by a corresponding call to the underlying isolation architecture. + /// + EfiUnacceptedMemory, EfiMaxMemoryType } EFI_MEMORY_TYPE; diff --git a/OvmfPkg/Library/TdxStartupLib/Hob.c b/OvmfPkg/Library/TdxStartupLib/Hob.c index 321e4aeb4935..4c5c8646f2ef 100644 --- a/OvmfPkg/Library/TdxStartupLib/Hob.c +++ b/OvmfPkg/Library/TdxStartupLib/Hob.c @@ -19,6 +19,10 @@ #include #include "TdxStartupInternal.h" +#define MEGABYTE_SHIFT 20 + +UINT64 mTdxAcceptMemSize = 0; + VOID EFIAPI DEBUG_HOBLIST ( @@ -280,17 +284,34 @@ ProcessHobList ( { EFI_PEI_HOB_POINTERS Hob; EFI_PHYSICAL_ADDRESS PhysicalEnd; - EFI_PHYSICAL_ADDRESS PhysicalStart; - UINT64 Length; - EFI_HOB_RESOURCE_DESCRIPTOR *LowMemoryResource = NULL; + UINT64 ResourceLength; + UINT64 AccumulateAccepted; + EFI_PHYSICAL_ADDRESS LowMemoryStart; + UINT64 LowMemoryLength; ASSERT (VmmHobList != NULL); + + AccumulateAccepted = 0; Hob.Raw = (UINT8 *) VmmHobList; + LowMemoryLength = 0; + + mTdxAcceptMemSize = FixedPcdGet64(PcdTdxAcceptPartialMemorySize); + + // + // If specified accept size is equal to or less than zero, accept all of the memory. + // Else transfer the size in megabyte to the number in byte. + // + if (mTdxAcceptMemSize <= 0) { + mTdxAcceptMemSize = ~(UINT64) 0; + } else { + mTdxAcceptMemSize <<= MEGABYTE_SHIFT; + } + DEBUG ((DEBUG_INFO, "mTdxAcceptMemSize: 0x%llx\n", mTdxAcceptMemSize)); // // Parse the HOB list until end of list or matching type is found. // - while (!END_OF_HOB_LIST (Hob)) { + while (!END_OF_HOB_LIST (Hob) && AccumulateAccepted < mTdxAcceptMemSize) { if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType)); @@ -311,43 +332,49 @@ ProcessHobList ( DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner)); PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength; - + ResourceLength = Hob.ResourceDescriptor->ResourceLength; + + if (AccumulateAccepted + ResourceLength > mTdxAcceptMemSize) { + // + // If the memory can't be accepted completely, accept the part of it to meet the + // TDX_PARTIAL_ACCEPTED_MEM_SIZE. + // + ResourceLength = mTdxAcceptMemSize - AccumulateAccepted; + PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + ResourceLength; + } if (PhysicalEnd <= BASE_4GB) { - if ((LowMemoryResource == NULL) || (Hob.ResourceDescriptor->ResourceLength > LowMemoryResource->ResourceLength)) { - LowMemoryResource = Hob.ResourceDescriptor; + if (ResourceLength > LowMemoryLength) { + LowMemoryStart = Hob.ResourceDescriptor->PhysicalStart; + LowMemoryLength = ResourceLength; } } - + DEBUG ((DEBUG_INFO, "Accept Start and End: %x, %x\n", Hob.ResourceDescriptor->PhysicalStart, PhysicalEnd)); MpAcceptMemoryResourceRange ( Hob.ResourceDescriptor->PhysicalStart, PhysicalEnd); + + AccumulateAccepted += PhysicalEnd - Hob.ResourceDescriptor->PhysicalStart; } } Hob.Raw = GET_NEXT_HOB (Hob); } - ASSERT (LowMemoryResource != NULL); - - PhysicalStart = LowMemoryResource->PhysicalStart; - Length = LowMemoryResource->ResourceLength; - // // HobLib doesn't like HobStart at address 0 so adjust is needed // - if (PhysicalStart == 0) { - PhysicalStart += EFI_PAGE_SIZE; - Length -= EFI_PAGE_SIZE; + if (LowMemoryStart == 0) { + LowMemoryStart += EFI_PAGE_SIZE; + LowMemoryLength -= EFI_PAGE_SIZE; } - HobConstructor ( - (VOID *) PhysicalStart, - Length, - (VOID *) PhysicalStart, - (VOID *) (PhysicalStart + Length) + (VOID *) LowMemoryStart, + LowMemoryLength, + (VOID *) LowMemoryStart, + (VOID *) (LowMemoryStart + LowMemoryLength) ); - PrePeiSetHobList ((VOID *)(UINT64)PhysicalStart); + PrePeiSetHobList ((VOID *)(UINT64)LowMemoryStart); } /** @@ -363,28 +390,78 @@ TransferHobList ( ) { EFI_PEI_HOB_POINTERS Hob; + EFI_RESOURCE_TYPE ResourceType; EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; - EFI_PHYSICAL_ADDRESS PhysicalEnd; + EFI_PHYSICAL_ADDRESS PhysicalStart; + UINT64 ResourceLength; + UINT64 AccumulateAccepted; + + Hob.Raw = (UINT8 *) VmmHobList; + AccumulateAccepted = 0; - Hob.Raw = (UINT8 *) VmmHobList; 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; + ResourceLength = Hob.ResourceDescriptor->ResourceLength; + ResourceType = Hob.ResourceDescriptor->ResourceType; + PhysicalStart = Hob.ResourceDescriptor->PhysicalStart; + + if (ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED; + + // + // Set type of systme memory less than TDX_PARTIAL_ACCEPTED_MEM_SIZE to + // EFI_RESOURCE_SYSTEM_MEMORY and set other to EFI_RESOURCE_MEMORY_UNACCEPTED. + // + if (AccumulateAccepted >= mTdxAcceptMemSize) { + ResourceType = EFI_RESOURCE_MEMORY_UNACCEPTED; + ResourceAttribute &= ~(EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_ENCRYPTED); + } else { + // + // Judge if the whole memory is accepted. + // + if (AccumulateAccepted + ResourceLength <= mTdxAcceptMemSize) { + AccumulateAccepted += ResourceLength; + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_TESTED; + if (PhysicalStart + ResourceLength <= BASE_4GB) { + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_ENCRYPTED; + } + } else { + // + // Set the resouce type, attribute and memory range of the the accepted part + // of the memory. + // + ResourceType = EFI_RESOURCE_SYSTEM_MEMORY; + ResourceLength = mTdxAcceptMemSize - AccumulateAccepted; + + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_TESTED; + if (PhysicalStart + ResourceLength <= BASE_4GB) { + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_ENCRYPTED; + } + BuildResourceDescriptorHob ( + ResourceType, + ResourceAttribute, + PhysicalStart, + ResourceLength); + AccumulateAccepted += ResourceLength; + + // + // Transfer the other part to the unaccepted memory. + // + PhysicalStart = PhysicalStart + ResourceLength; + ResourceLength = Hob.ResourceDescriptor->ResourceLength - ResourceLength; + ResourceType = EFI_RESOURCE_MEMORY_UNACCEPTED; + ResourceAttribute &= ~(EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_ENCRYPTED); + } + } } + BuildResourceDescriptorHob ( - Hob.ResourceDescriptor->ResourceType, + ResourceType, ResourceAttribute, - Hob.ResourceDescriptor->PhysicalStart, - Hob.ResourceDescriptor->ResourceLength); + PhysicalStart, + ResourceLength); break; case EFI_HOB_TYPE_MEMORY_ALLOCATION: BuildMemoryAllocationHob ( diff --git a/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf b/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf index b76411d92759..b62e54f85bb2 100644 --- a/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf +++ b/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf @@ -84,13 +84,14 @@ gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize gUefiOvmfPkgTokenSpaceGuid.PcdUseTdxEmulation gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageChunkSize - gUefiOvmfPkgTokenSpaceGuid.PcdTdxSetNxForStack - gUefiOvmfPkgTokenSpaceGuid.PcdTdxPteMemoryEncryptionAddressOrMask + gUefiOvmfPkgTokenSpaceGuid.PcdTdxSetNxForStack + gUefiOvmfPkgTokenSpaceGuid.PcdTdxPteMemoryEncryptionAddressOrMask + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPartialMemorySize - // - // TODO check these PCDs' impact on Ovmf - // - gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## CONSUMES + // + // TODO check these PCDs' impact on Ovmf + // + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 41491e21c5ea..7372f49a361c 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -342,6 +342,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdTdxSetNxForStack|FALSE|BOOLEAN|0x5b gUefiOvmfPkgTokenSpaceGuid.PcdTdxPteMemoryEncryptionAddressOrMask|0|UINT64|0x5c + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPartialMemorySize|0|UINT64|0x5d [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index d5d78e7cde6b..4a994ee31f52 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -41,6 +41,8 @@ DEFINE TDX_IGNORE_VE_HLT = FALSE DEFINE TDX_EMULATION_ENABLE = FALSE DEFINE TDX_SUPPORT = TRUE + DEFINE TDX_MEM_PARTIAL_ACCEPT = 0 + # Network definition # DEFINE NETWORK_TLS_ENABLE = FALSE @@ -606,7 +608,8 @@ !endif # 32M gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageChunkSize|0x2000000 - + # Accept memory size. + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPartialMemorySize|$(TDX_MEM_PARTIAL_ACCEPT) # Noexec settings for DXE. # TDX doesn't allow us to change EFER so make sure these are disabled gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000000 diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c index ea651802cb68..0e2fe991f274 100644 --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c @@ -26,6 +26,7 @@ STATIC CONST CHAR16 NameEfiACPIMemoryNVS[] = L"ACPIMemoryNVS"; STATIC CONST CHAR16 NameEfiMemoryMappedIO[] = L"MemoryMappedIO"; STATIC CONST CHAR16 NameEfiMemoryMappedIOPortSpace[] = L"MemoryMappedIOPortSpace"; STATIC CONST CHAR16 NameEfiPalCode[] = L"PalCode"; +STATIC CONST CHAR16 NameEfiUnacceptedMemory[] = L"Unaccepted"; // // Need short names for some memory types @@ -300,6 +301,11 @@ ShellCommandRunMemMap ( TotalPages += Walker->NumberOfPages; PalCodePages += Walker->NumberOfPages; break; + case EfiUnacceptedMemory: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiUnacceptedMemory, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + TotalPages += Walker->NumberOfPages; + PalCodePages += Walker->NumberOfPages; + break; default: // // Shell Spec defines the SFO format. From d8356ca7f9f22c0be45f1128941afb8df1028cbb Mon Sep 17 00:00:00 2001 From: Jiaqi Gao Date: Fri, 30 Jul 2021 17:08:44 +0800 Subject: [PATCH 2/5] OvmfPkg: Calculate the memory size need to be accepted. Kernel/Initrd image size maybe significant so we cannot decide the memory size to be accepted at build-time. In SEC, we read the size of kernel/initrd image from QEMU and accept memory used for them additionally. --- OvmfPkg/Library/TdxStartupLib/Hob.c | 45 ++++++++++++++----- .../Library/TdxStartupLib/TdxStartupLib.inf | 1 + 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/OvmfPkg/Library/TdxStartupLib/Hob.c b/OvmfPkg/Library/TdxStartupLib/Hob.c index 4c5c8646f2ef..1f211ec0eea5 100644 --- a/OvmfPkg/Library/TdxStartupLib/Hob.c +++ b/OvmfPkg/Library/TdxStartupLib/Hob.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "TdxStartupInternal.h" @@ -23,6 +24,36 @@ UINT64 mTdxAcceptMemSize = 0; +UINTN +GetAcceptSize () +{ + UINTN AcceptSize; + AcceptSize = FixedPcdGet64 (PcdTdxAcceptPartialMemorySize); + + // + // If specified accept size is equal to or less than zero, accept all of the memory. + // Else transfer the size in megabyte to the number in byte. + // + if (AcceptSize <= 0) { + AcceptSize = ~(UINT64) 0; + return AcceptSize; + } else { + AcceptSize <<= MEGABYTE_SHIFT; + } + + QemuFwCfgSelectItem (QemuFwCfgItemKernelSize); + AcceptSize += (UINTN) QemuFwCfgRead32 (); + QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize); + AcceptSize += (UINTN) QemuFwCfgRead32 (); + QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize); + AcceptSize += (UINTN) QemuFwCfgRead32 (); + QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize); + AcceptSize += (UINTN) QemuFwCfgRead32 (); + + AcceptSize = (AcceptSize + EFI_PAGE_MASK) & (~EFI_PAGE_MASK); + return AcceptSize; +} + VOID EFIAPI DEBUG_HOBLIST ( @@ -295,19 +326,9 @@ ProcessHobList ( Hob.Raw = (UINT8 *) VmmHobList; LowMemoryLength = 0; - mTdxAcceptMemSize = FixedPcdGet64(PcdTdxAcceptPartialMemorySize); - - // - // If specified accept size is equal to or less than zero, accept all of the memory. - // Else transfer the size in megabyte to the number in byte. - // - if (mTdxAcceptMemSize <= 0) { - mTdxAcceptMemSize = ~(UINT64) 0; - } else { - mTdxAcceptMemSize <<= MEGABYTE_SHIFT; - } - DEBUG ((DEBUG_INFO, "mTdxAcceptMemSize: 0x%llx\n", mTdxAcceptMemSize)); + mTdxAcceptMemSize = GetAcceptSize (); + DEBUG ((DEBUG_INFO, "Total accept size: 0x%x\n", mTdxAcceptMemSize)); // // Parse the HOB list until end of list or matching type is found. // diff --git a/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf b/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf index b62e54f85bb2..035cd1725bc2 100644 --- a/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf +++ b/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf @@ -60,6 +60,7 @@ MemoryAllocationLib TdvfPlatformLib PrePiLib + QemuFwCfgLib [Guids] gEfiHobMemoryAllocModuleGuid From 45974892883847f9c0397ca8efcc86a0318b2c6e Mon Sep 17 00:00:00 2001 From: Jiaqi Gao Date: Mon, 30 Aug 2021 18:33:24 +0800 Subject: [PATCH 3/5] OvmfPkg: Define EfiMemoryAcceptProtocol to accept memory dynamically. Memory usage may exceed the amount accepted at the begining (SEC), TDVF need to accept memory dynamically when OUT_OF_RESOURCE occurs. EfiMemoryAcceptProtocol is defined in MdePkg and there's an implementation in the TdxDxe for Intel TDX memory acceptance. When DXE memory service need more memory to be accepted, it can call the interface installed by TdxDxe. Signed-off-by: Jiaqi Gao --- MdePkg/Include/Protocol/MemoryAccept.h | 41 ++++++++++++++++++++++++++ MdePkg/MdePkg.dec | 3 ++ OvmfPkg/TdxDxe/TdxDxe.c | 34 ++++++++++++++++++++- OvmfPkg/TdxDxe/TdxDxe.inf | 3 ++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 MdePkg/Include/Protocol/MemoryAccept.h diff --git a/MdePkg/Include/Protocol/MemoryAccept.h b/MdePkg/Include/Protocol/MemoryAccept.h new file mode 100644 index 000000000000..b3f237082956 --- /dev/null +++ b/MdePkg/Include/Protocol/MemoryAccept.h @@ -0,0 +1,41 @@ +/** @file + The file provides the protocol to provide interface to accept memory. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ +**/ + +#ifndef __MEMORY_ACCEPT_H___ +#define __MEMORY_ACCEPT_H___ + +#define EFI_MEMORY_ACCEPT_PROTOCOL_GUID \ + { 0x38c74800, 0x5590, 0x4db4, { 0xa0, 0xf3, 0x67, 0x5d, 0x9b, 0x8e, 0x80, 0x26 } }; + +typedef struct _EFI_MEMORY_ACCEPT_PROTOCOL EFI_MEMORY_ACCEPT_PROTOCOL; + +/** + + + @param This A pointer to a MEMORY_ACCEPT_PROTOCOL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACCEPT_MEMORY)( + IN EFI_MEMORY_ACCEPT_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINTN Size +); + +/// +/// The MEMORY_ACCEPT_PROTOCOL provides the ability for memory services +/// to accept memory. +/// +struct _EFI_MEMORY_ACCEPT_PROTOCOL { + EFI_ACCEPT_MEMORY AcceptMemory; +}; + +extern EFI_GUID gEfiMemoryAcceptProtocolGuid; + +#endif + diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 888d92086a49..d6b6f23220e8 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -986,6 +986,9 @@ ## Include/Protocol/Tdx.h gTdTcg2ProtocolGuid = {0x96751a3d, 0x72f4, 0x41a6, {0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b}} + ## Include/Protocol/MemoryAccept.h + gEfiMemoryAcceptProtocolGuid = { 0x38c74800, 0x5590, 0x4db4, { 0xa0, 0xf3, 0x67, 0x5d, 0x9b, 0x8e, 0x80, 0x26 } } + ## Include/Protocol/Pcd.h gPcdProtocolGuid = { 0x11B34006, 0xD85B, 0x4D0A, { 0xA2, 0x90, 0xD5, 0xA5, 0x71, 0x31, 0x0E, 0xF7 }} diff --git a/OvmfPkg/TdxDxe/TdxDxe.c b/OvmfPkg/TdxDxe/TdxDxe.c index cec3aea7670b..1ad4d1351de9 100644 --- a/OvmfPkg/TdxDxe/TdxDxe.c +++ b/OvmfPkg/TdxDxe/TdxDxe.c @@ -24,11 +24,35 @@ #include #include #include +#include #include #include #include #include +EFI_HANDLE mTdxDxeHandle = NULL; + +EFI_STATUS +EFIAPI +TdxMemoryAccept ( + IN EFI_MEMORY_ACCEPT_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINTN Size + ) +{ + + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "Tdx Accept start address: 0x%lx, size: 0x%lx\n", StartAddress, Size)); + Status = TdAcceptPages (StartAddress, Size / SIZE_4KB, SIZE_4KB); + + return Status; +} + +EFI_MEMORY_ACCEPT_PROTOCOL mMemoryAcceptProtocol = { + TdxMemoryAccept +}; + /** Location of resource hob matching type and starting address @@ -124,6 +148,7 @@ TdxDxeEntryPoint ( EFI_HOB_GUID_TYPE *GuidHob; UINT32 CpuMaxLogicalProcessorNumber; TD_RETURN_DATA TdReturnData; + // EFI_PHYSICAL_ADDRESS TestAddress; GuidHob = GetFirstGuidHob(&gUefiOvmfPkgTdxPlatformGuid); @@ -132,7 +157,14 @@ TdxDxeEntryPoint ( } PlatformInfo = (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob); - + + Status = gBS->InstallProtocolInterface (&mTdxDxeHandle, + &gEfiMemoryAcceptProtocolGuid, EFI_NATIVE_INTERFACE, + &mMemoryAcceptProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Install EfiMemoryAcceptProtocol failed.\n")); + } + // // Call TDINFO to get actual number of cpus in domain // diff --git a/OvmfPkg/TdxDxe/TdxDxe.inf b/OvmfPkg/TdxDxe/TdxDxe.inf index c8f78cdf4f15..3d4d98e4fac9 100644 --- a/OvmfPkg/TdxDxe/TdxDxe.inf +++ b/OvmfPkg/TdxDxe/TdxDxe.inf @@ -39,6 +39,9 @@ [Depex] TRUE +[Protocols] + gEfiMemoryAcceptProtocolGuid + [Guids] gUefiOvmfPkgTdxPlatformGuid ## CONSUMES From 5c11ffed77bab42016679e9308b33fbe0020f16b Mon Sep 17 00:00:00 2001 From: Jiaqi Gao Date: Mon, 30 Aug 2021 18:42:14 +0800 Subject: [PATCH 4/5] MdeModulePkg: Update CoreAllocatePages() to accept memory dynamically. When CoreAllocatePages()/CoreAllocatePool() meets error of EFI_OUT_OF_RESOURCES, locate the EfiMemoryAcceptProtocol and accept extra memory. Firstly, find the unaccpeted memory region with enough size in GCD entries. Then locate the EfiMemoryAcceptProtocol and accept the memory. Finally, update the GCD memory and gMemoryMap entries. After updating the memory infomation, CoreInternalAllocatePages()/ CoreInternalAllocatePool() will be recalled to allocate pages/pool. To do (existing issue): 1. CoreAddMemorySpace() should not be called directly in AcceptMemoryResource() until gMemoryMap is updated because it will try to allocate another piece of memory for GCD map entry. 2. AcceptMemoryResource() is called in both CoreAllocatePool() and CoreAllocatePages(). Refine this by changing FindFreePages() and the CoreConvertPagesEx() to handle *AllocateAddress* case. Signed-off-by: Jiaqi Gao --- MdeModulePkg/Core/Dxe/DxeMain.inf | 2 + MdeModulePkg/Core/Dxe/Gcd/Gcd.c | 3 - MdeModulePkg/Core/Dxe/Mem/Imem.h | 6 ++ MdeModulePkg/Core/Dxe/Mem/Page.c | 164 +++++++++++++++++++++++++++++- MdeModulePkg/Core/Dxe/Mem/Pool.c | 10 ++ MdePkg/Include/Pi/PiHob.h | 4 + 6 files changed, 185 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index fb2218e062c4..9cd50cf240c5 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -171,6 +171,8 @@ gEfiCapsuleArchProtocolGuid ## CONSUMES gEfiWatchdogTimerArchProtocolGuid ## CONSUMES + gEfiMemoryAcceptProtocolGuid ## CONSUMES + [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index f20106dfecda..6d06923cf1eb 100644 --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c @@ -82,9 +82,6 @@ EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = { NULL, NULL }; -// TD -#define EFI_RESOURCE_ATTRIBUTE_ENCRYPTED 0x04000000 - GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = { { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE }, diff --git a/MdeModulePkg/Core/Dxe/Mem/Imem.h b/MdeModulePkg/Core/Dxe/Mem/Imem.h index 090f3f089f4a..e0f238137e58 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Imem.h +++ b/MdeModulePkg/Core/Dxe/Mem/Imem.h @@ -69,6 +69,12 @@ CoreAllocatePoolPages ( ); +EFI_STATUS +AcceptMemoryResource ( + IN EFI_ALLOCATE_TYPE Type, + IN UINTN AcceptSize, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); /** Internal function. Frees pool pages allocated via AllocatePoolPages () diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 1ac579c65fba..464f7749d893 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "DxeMain.h" #include "Imem.h" #include "HeapGuard.h" +#include // // Entry for tracking the memory regions for each memory type to coalesce similar memory types @@ -388,6 +389,156 @@ CoreFreeMemoryMapStack ( mFreeMapStack -= 1; } +EFI_STATUS +AcceptMemoryResource ( + IN EFI_ALLOCATE_TYPE Type, + IN UINTN AcceptSize, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *GcdEntry; + EFI_GCD_MAP_ENTRY UnacceptedEntry; + EFI_MEMORY_ACCEPT_PROTOCOL *MemoryAcceptProtocol; + UINTN Start; + UINTN End; + EFI_STATUS Status; + + AcceptSize = (AcceptSize + SIZE_32MB - 1) & ~(SIZE_32MB - 1); + + if (AcceptSize == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol (&gEfiMemoryAcceptProtocolGuid, NULL, (VOID **)&MemoryAcceptProtocol); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Type == AllocateAddress) { + Start = *Memory; + End = *Memory + AcceptSize; + } + + if (Type == AllocateMaxAddress) { + + if (*Memory < EFI_PAGE_MASK) { + return EFI_INVALID_PARAMETER; + } + + if ((*Memory & EFI_PAGE_MASK) != EFI_PAGE_MASK) { + // + // Change MaxAddress to be 1 page lower + // + *Memory -= EFI_PAGE_SIZE; + + // + // Set MaxAddress to a page boundary + // + *Memory &= ~(UINT64)EFI_PAGE_MASK; + + // + // Set MaxAddress to end of the page + // + *Memory |= EFI_PAGE_MASK; + } + } + + // + // Traverse the mGcdMemorySpaceMap to find out the unaccepted + // memory entry with enough size. + // + Link = mGcdMemorySpaceMap.ForwardLink; + while (Link != &mGcdMemorySpaceMap) { + GcdEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (GcdEntry->GcdMemoryType == EfiGcdMemoryTypeUnaccepted) { + + if (Type == AllocateMaxAddress) { + if (GcdEntry->BaseAddress + AcceptSize - 1 > *Memory) { + continue; + } + } else if (Type == AllocateAddress) { + if (GcdEntry->BaseAddress > *Memory || GcdEntry->EndAddress < *Memory + AcceptSize - 1) { + continue; + } + } + + UnacceptedEntry = *GcdEntry; + + // + // Remove the target memory space from GCD. + // + if (AcceptSize <= UnacceptedEntry.EndAddress - UnacceptedEntry.BaseAddress + 1) { + CoreRemoveMemorySpace (GcdEntry->BaseAddress, UnacceptedEntry.EndAddress - UnacceptedEntry.BaseAddress + 1); + + if (Type != AllocateAddress) { + Start = GcdEntry->BaseAddress; + End = GcdEntry->BaseAddress + AcceptSize - 1; + } + break; + } + } + Link = Link->ForwardLink; + } + + if (Link == &mGcdMemorySpaceMap) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Accept the memory using the interface provide by the protocol. + // + Status = MemoryAcceptProtocol->AcceptMemory (MemoryAcceptProtocol, Start, AcceptSize); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Fix me! CoreAddMemorySpace() should not be called in the allocation process + // because it will allocate memory for GCD map entry. + // + + // + // Add the remain lower part of unaccepted memory to the + // Gcd memory space and memory map. + // + if (Start > UnacceptedEntry.BaseAddress) { + CoreAddMemorySpace ( + EfiGcdMemoryTypeUnaccepted, + UnacceptedEntry.BaseAddress, + Start - UnacceptedEntry.BaseAddress, + UnacceptedEntry.Capabilities + ); + } + + // + // Update accepted part of the memory entry to type of EfiGcdMemoryTypeSystemMemory + // and add the range to the memory map. + // + CoreAddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + Start, + AcceptSize, + EFI_MEMORY_RUNTIME | EFI_MEMORY_CPU_CRYPTO | EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP + ); + + // + // Add the remain higher part of unaccepted memory to the + // Gcd memory space and memory map. + // + if (UnacceptedEntry.EndAddress > End) { + CoreAddMemorySpace ( + EfiGcdMemoryTypeUnaccepted, + End + 1, + UnacceptedEntry.EndAddress - End, + UnacceptedEntry.Capabilities + ); + } + + return EFI_SUCCESS; +} + /** Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable. @@ -1442,6 +1593,17 @@ CoreAllocatePages ( NeedGuard = IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding; Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory, NeedGuard); + + if (Status == EFI_OUT_OF_RESOURCES) { + Status = AcceptMemoryResource (Type, NumberOfPages << EFI_PAGE_SHIFT, Memory); + if (!EFI_ERROR (Status)) { + Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory, + NeedGuard); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + if (!EFI_ERROR (Status)) { CoreUpdateProfile ( (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), @@ -1455,6 +1617,7 @@ CoreAllocatePages ( ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory, EFI_PAGES_TO_SIZE (NumberOfPages)); } + return Status; } @@ -2029,7 +2192,6 @@ CoreAllocatePoolPages ( ) { UINT64 Start; - // // Find the pages to convert // diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index 734fc94bf612..0881c0ab4acc 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -276,6 +276,16 @@ CoreAllocatePool ( EFI_STATUS Status; Status = CoreInternalAllocatePool (PoolType, Size, Buffer); + + if (Status == EFI_OUT_OF_RESOURCES) { + Status = AcceptMemoryResource (AllocateAnyPages, Size, NULL); + if (!EFI_ERROR (Status)) { + Status = CoreInternalAllocatePool (PoolType, Size, Buffer); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + if (!EFI_ERROR (Status)) { CoreUpdateProfile ( (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), diff --git a/MdePkg/Include/Pi/PiHob.h b/MdePkg/Include/Pi/PiHob.h index dd0830d3a004..d2af3a81d590 100644 --- a/MdePkg/Include/Pi/PiHob.h +++ b/MdePkg/Include/Pi/PiHob.h @@ -251,6 +251,10 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; #define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 #define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 #define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 + + +// TD +#define EFI_RESOURCE_ATTRIBUTE_ENCRYPTED 0x04000000 // // This is typically used as memory cacheability attribute today. // NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED From 28d63bdc477addea8ffb1ab3c94f9907a87991c4 Mon Sep 17 00:00:00 2001 From: Jiaqi Gao Date: Mon, 30 Aug 2021 18:52:15 +0800 Subject: [PATCH 5/5] OvmfPkg: Fix the issue in IO #VE handler From: tianocore/edk2-staging@a25c007 --- OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c b/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c index 43e4384cdb6a..16ad824e0e03 100644 --- a/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c +++ b/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c @@ -112,16 +112,18 @@ IoExit( Val = 0; if (Write == TRUE) { CopyMem (&Val, (VOID *) Regs->Rsi, Size); + Regs->Rsi += Size; } - Regs->Rsi += Size; + Status = TdVmCall(EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val)); if (Status != 0) { break; } if (Write == FALSE) { CopyMem ((VOID *) Regs->Rdi, &Val, Size); + Regs->Rdi += Size; } - Regs->Rdi += Size; + if (Veinfo->ExitQualification.Io.Rep) { Regs->Rcx -= 1; }