X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FPage.c;h=a142c79ee2cabd0faea99a54ce79f7637177b6f3;hp=a28552934f6baba5d2402b241c23edfd60e3e917;hb=9a701955a55d094e93c3613a3ae462660551d592;hpb=ff0c6d6617833573e9de0eec7287a90247365b98 diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index a28552934f..a142c79ee2 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1,7 +1,7 @@ /** @file UEFI Memory page management functions. -Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -15,8 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "DxeMain.h" #include "Imem.h" -#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) - // // Entry for tracking the memory regions for each memory type to coalesce similar memory types // @@ -204,7 +202,7 @@ CoreAddRange ( // If we are in EFI 1.10 compatability mode no event groups will be // found and nothing will happen we we call this function. These events // will get signaled but since a lock is held around the call to this - // function the notificaiton events will only be called after this funciton + // function the notificaiton events will only be called after this function // returns and the lock is released. // CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid); @@ -287,12 +285,14 @@ AllocateMemoryMapEntry ( // // The list is empty, to allocate one page to refuel the list // - FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION); - if(FreeDescriptorEntries != NULL) { + FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION_GRANULARITY), + DEFAULT_PAGE_ALLOCATION_GRANULARITY); + if (FreeDescriptorEntries != NULL) { // // Enque the free memmory map entries into the list // - for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) { + for (Index = 0; Index < DEFAULT_PAGE_ALLOCATION_GRANULARITY / sizeof(MEMORY_MAP); Index++) { FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE; InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link); } @@ -553,6 +553,9 @@ CoreAddMemoryDescriptor ( CoreFreeMemoryMapStack (); CoreReleaseMemoryLock (); + ApplyMemoryProtectionPolicy (EfiMaxMemoryType, Type, Start, + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT)); + // // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type // @@ -725,7 +728,7 @@ CoreConvertPagesEx ( ASSERT_LOCKED (&gMemoryLock); ASSERT ( (ChangingType == FALSE) || (ChangingAttributes == FALSE) ); - if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start > (Start + NumberOfBytes))) { + if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) { return EFI_INVALID_PARAMETER; } @@ -751,6 +754,17 @@ CoreConvertPagesEx ( return EFI_NOT_FOUND; } + // + // If we are converting the type of the range from EfiConventionalMemory to + // another type, we have to ensure that the entire range is covered by a + // single entry. + // + if (ChangingType && (NewType != EfiConventionalMemory)) { + if (Entry->End < End) { + DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: range %lx - %lx covers multiple entries\n", Start, End)); + return EFI_NOT_FOUND; + } + } // // Convert range to the end, or to the end of the descriptor // if that's all we've got @@ -774,7 +788,12 @@ CoreConvertPagesEx ( // Debug code - verify conversion is allowed // if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) { - DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types\n")); + DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types, ")); + if (Entry->Type == EfiConventionalMemory) { + DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to free have been freed\n")); + } else { + DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to allocate have been allocated\n")); + } return EFI_NOT_FOUND; } @@ -1201,6 +1220,8 @@ CoreInternalAllocatePages ( { EFI_STATUS Status; UINT64 Start; + UINT64 NumberOfBytes; + UINT64 End; UINT64 MaxAddress; UINTN Alignment; @@ -1217,14 +1238,14 @@ CoreInternalAllocatePages ( return EFI_INVALID_PARAMETER; } - Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY; if (MemoryType == EfiACPIReclaimMemory || MemoryType == EfiACPIMemoryNVS || MemoryType == EfiRuntimeServicesCode || MemoryType == EfiRuntimeServicesData) { - Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY; } if (Type == AllocateAddress) { @@ -1246,6 +1267,30 @@ CoreInternalAllocatePages ( // MaxAddress = MAX_ADDRESS; + // + // Check for Type AllocateAddress, + // if NumberOfPages is 0 or + // if (NumberOfPages << EFI_PAGE_SHIFT) is above MAX_ADDRESS or + // if (Start + NumberOfBytes) rolls over 0 or + // if Start is above MAX_ADDRESS or + // if End is above MAX_ADDRESS, + // return EFI_NOT_FOUND. + // + if (Type == AllocateAddress) { + if ((NumberOfPages == 0) || + (NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT))) { + return EFI_NOT_FOUND; + } + NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT); + End = Start + NumberOfBytes - 1; + + if ((Start >= End) || + (Start > MaxAddress) || + (End > MaxAddress)) { + return EFI_NOT_FOUND; + } + } + if (Type == AllocateMaxAddress) { MaxAddress = Start; } @@ -1309,7 +1354,17 @@ CoreAllocatePages ( Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) *Memory, + NULL + ); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); + ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory, + EFI_PAGES_TO_SIZE (NumberOfPages)); } return Status; } @@ -1319,6 +1374,7 @@ CoreAllocatePages ( @param Memory Base address of memory being freed @param NumberOfPages The number of pages to free + @param MemoryType Pointer to memory type @retval EFI_NOT_FOUND Could not find the entry that covers the range @retval EFI_INVALID_PARAMETER Address not aligned @@ -1329,7 +1385,8 @@ EFI_STATUS EFIAPI CoreInternalFreePages ( IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NumberOfPages + IN UINTN NumberOfPages, + OUT EFI_MEMORY_TYPE *MemoryType OPTIONAL ) { EFI_STATUS Status; @@ -1357,7 +1414,7 @@ CoreInternalFreePages ( goto Done; } - Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY; ASSERT (Entry != NULL); if (Entry->Type == EfiACPIReclaimMemory || @@ -1365,7 +1422,7 @@ CoreInternalFreePages ( Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) { - Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY; } @@ -1377,6 +1434,10 @@ CoreInternalFreePages ( NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1; NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1); + if (MemoryType != NULL) { + *MemoryType = Entry->Type; + } + Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory); if (EFI_ERROR (Status)) { @@ -1406,11 +1467,22 @@ CoreFreePages ( IN UINTN NumberOfPages ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_MEMORY_TYPE MemoryType; - Status = CoreInternalFreePages (Memory, NumberOfPages); + Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, (EFI_MEMORY_TYPE) 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) Memory, + NULL + ); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); + ApplyMemoryProtectionPolicy (MemoryType, EfiConventionalMemory, Memory, + EFI_PAGES_TO_SIZE (NumberOfPages)); } return Status; } @@ -1543,6 +1615,7 @@ CoreGetMemoryMap ( LIST_ENTRY *Link; MEMORY_MAP *Entry; EFI_GCD_MAP_ENTRY *GcdMapEntry; + EFI_GCD_MAP_ENTRY MergeGcdMapEntry; EFI_MEMORY_TYPE Type; EFI_MEMORY_DESCRIPTOR *MemoryMapStart; @@ -1654,25 +1727,49 @@ CoreGetMemoryMap ( MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); } - for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) { - GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); - if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || - ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && - ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) { + + ZeroMem (&MergeGcdMapEntry, sizeof (MergeGcdMapEntry)); + GcdMapEntry = NULL; + for (Link = mGcdMemorySpaceMap.ForwardLink; ; Link = Link->ForwardLink) { + if (Link != &mGcdMemorySpaceMap) { + // + // Merge adjacent same type and attribute GCD memory range + // + GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if ((MergeGcdMapEntry.Capabilities == GcdMapEntry->Capabilities) && + (MergeGcdMapEntry.Attributes == GcdMapEntry->Attributes) && + (MergeGcdMapEntry.GcdMemoryType == GcdMapEntry->GcdMemoryType) && + (MergeGcdMapEntry.GcdIoType == GcdMapEntry->GcdIoType)) { + MergeGcdMapEntry.EndAddress = GcdMapEntry->EndAddress; + continue; + } + } + + if ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) || + ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && + ((MergeGcdMapEntry.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) { + // + // 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 Reserved and runtime MMIO GCD entries // - MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress; + MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress; MemoryMap->VirtualStart = 0; - MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT); - MemoryMap->Attribute = (GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO) | - (GcdMapEntry->Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO | + MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = (MergeGcdMapEntry.Attributes & ~EFI_MEMORY_PORT_IO) | + (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)); - if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) { + if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) { MemoryMap->Type = EfiReservedMemoryType; - } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { - if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) { + } else if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { + if ((MergeGcdMapEntry.Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) { MemoryMap->Type = EfiMemoryMappedIOPortSpace; } else { MemoryMap->Type = EfiMemoryMappedIO; @@ -1686,15 +1783,22 @@ CoreGetMemoryMap ( MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); } - if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistentMemory) { + if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypePersistentMemory) { + // + // 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 Persistent GCD entries // - MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress; + MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress; MemoryMap->VirtualStart = 0; - MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT); - MemoryMap->Attribute = GcdMapEntry->Attributes | EFI_MEMORY_NV | - (GcdMapEntry->Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO | + MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = MergeGcdMapEntry.Attributes | EFI_MEMORY_NV | + (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 = EfiPersistentMemory; @@ -1704,6 +1808,18 @@ CoreGetMemoryMap ( // MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); } + if (Link == &mGcdMemorySpaceMap) { + // + // break loop when arrive at head. + // + break; + } + if (GcdMapEntry != NULL) { + // + // Copy new GCD map entry for the following GCD range merge + // + CopyMem (&MergeGcdMapEntry, GcdMapEntry, sizeof (MergeGcdMapEntry)); + } } // @@ -1825,12 +1941,12 @@ CoreTerminateMemoryMap ( if (mMemoryTypeStatistics[Entry->Type].Runtime) { ASSERT (Entry->Type != EfiACPIReclaimMemory); ASSERT (Entry->Type != EfiACPIMemoryNVS); - if ((Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) { + if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); Status = EFI_INVALID_PARAMETER; goto Done; } - if (((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) { + if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); Status = EFI_INVALID_PARAMETER; goto Done;