diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index 1b9d591754c71..f20106dfecdaa 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 a749ffd6e32ef..1ac579c65fba4 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 1682211d92af9..c600e00dbc76d 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 62c07742a688e..dd0830d3a0049 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 50e4d700a62f5..16b33f37040c4 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 321e4aeb49355..5d10364354f41 100644 --- a/OvmfPkg/Library/TdxStartupLib/Hob.c +++ b/OvmfPkg/Library/TdxStartupLib/Hob.c @@ -19,6 +19,8 @@ #include #include "TdxStartupInternal.h" +UINT64 mTdxAcceptMemSize = 0; + VOID EFIAPI DEBUG_HOBLIST ( @@ -280,17 +282,27 @@ 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 (mTdxAcceptMemSize <= 0) { + mTdxAcceptMemSize = UINT64_MAX; + } + 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 +323,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 +381,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 b76411d927595..b62e54f85bb28 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 41491e21c5ea8..7372f49a361c9 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 d5d78e7cde6bb..4a994ee31f52d 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 ea651802cb687..0e2fe991f2747 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.