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 1b9d591754c7..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 }, @@ -115,6 +112,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = { "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo "PersisMem", // EfiGcdMemoryTypePersistent "MoreRelia", // EfiGcdMemoryTypeMoreReliable + "Unaccepte", // EfiGcdMemoryTypeUnaccepted "Unknown " // EfiGcdMemoryTypeMaximum }; @@ -2563,6 +2561,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/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 a749ffd6e32e..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 @@ -61,6 +62,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 +85,7 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = { { EfiMemoryMappedIOPortSpace, 0 }, { EfiPalCode, 0 }, { EfiPersistentMemory, 0 }, + { EfiGcdMemoryTypeUnaccepted, 0 }, { EfiMaxMemoryType, 0 } }; // @@ -386,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. @@ -1440,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), @@ -1453,6 +1617,7 @@ CoreAllocatePages ( ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory, EFI_PAGES_TO_SIZE (NumberOfPages)); } + return Status; } @@ -1912,6 +2077,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. @@ -2001,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/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..d2af3a81d590 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. @@ -250,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 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/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/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/Library/TdxStartupLib/Hob.c b/OvmfPkg/Library/TdxStartupLib/Hob.c index 321e4aeb4935..1f211ec0eea5 100644 --- a/OvmfPkg/Library/TdxStartupLib/Hob.c +++ b/OvmfPkg/Library/TdxStartupLib/Hob.c @@ -15,10 +15,45 @@ #include #include #include +#include #include #include #include "TdxStartupInternal.h" +#define MEGABYTE_SHIFT 20 + +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 ( @@ -280,17 +315,24 @@ 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 = GetAcceptSize (); + DEBUG ((DEBUG_INFO, "Total accept size: 0x%x\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 +353,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 +411,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..035cd1725bc2 100644 --- a/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf +++ b/OvmfPkg/Library/TdxStartupLib/TdxStartupLib.inf @@ -60,6 +60,7 @@ MemoryAllocationLib TdvfPlatformLib PrePiLib + QemuFwCfgLib [Guids] gEfiHobMemoryAllocModuleGuid @@ -84,13 +85,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/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; } 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/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 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.