Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OvmfPkg/Library/TdxStartupLib: Add lazy memory accept to the TDVF. #9

Open
wants to merge 5 commits into
base: tdvf_dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions MdeModulePkg/Core/Dxe/DxeMain.inf
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@
gEfiCapsuleArchProtocolGuid ## CONSUMES
gEfiWatchdogTimerArchProtocolGuid ## CONSUMES

gEfiMemoryAcceptProtocolGuid ## CONSUMES

[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES
Expand Down
7 changes: 4 additions & 3 deletions MdeModulePkg/Core/Dxe/Gcd/Gcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -115,6 +112,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {
"MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
"PersisMem", // EfiGcdMemoryTypePersistent
"MoreRelia", // EfiGcdMemoryTypeMoreReliable
"Unaccepte", // EfiGcdMemoryTypeUnaccepted
"Unknown " // EfiGcdMemoryTypeMaximum
};

Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions MdeModulePkg/Core/Dxe/Mem/Imem.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
Expand Down
192 changes: 191 additions & 1 deletion MdeModulePkg/Core/Dxe/Mem/Page.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h"
#include "Imem.h"
#include "HeapGuard.h"
#include <Protocol/MemoryAccept.h>

//
// Entry for tracking the memory regions for each memory type to coalesce similar memory types
Expand Down Expand Up @@ -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
};

Expand All @@ -83,6 +85,7 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
{ EfiMemoryMappedIOPortSpace, 0 },
{ EfiPalCode, 0 },
{ EfiPersistentMemory, 0 },
{ EfiGcdMemoryTypeUnaccepted, 0 },
{ EfiMaxMemoryType, 0 }
};
//
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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),
Expand All @@ -1453,6 +1617,7 @@ CoreAllocatePages (
ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory,
EFI_PAGES_TO_SIZE (NumberOfPages));
}

return Status;
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -2001,7 +2192,6 @@ CoreAllocatePoolPages (
)
{
UINT64 Start;

//
// Find the pages to convert
//
Expand Down
10 changes: 10 additions & 0 deletions MdeModulePkg/Core/Dxe/Mem/Pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions MdePkg/Include/Pi/PiDxeCis.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 6 additions & 1 deletion MdePkg/Include/Pi/PiHob.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
41 changes: 41 additions & 0 deletions MdePkg/Include/Protocol/MemoryAccept.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/** @file
The file provides the protocol to provide interface to accept memory.

Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

**/

#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

5 changes: 5 additions & 0 deletions MdePkg/Include/Uefi/UefiMultiPhase.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading