X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FCpuDxe%2FCpuPageTable.c;h=ae93f3f5534f446ae2f066922c50c83e61acb20f;hp=ab664b47d605cb6ade8b2fe3450c4821600d5e72;hb=c1cab54ce57c2608b8b3ea051c7041f036f21153;hpb=01eb3f39bbcc5b6474d69cff3922be8eb1856636 diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c index ab664b47d6..ae93f3f553 100644 --- a/UefiCpuPkg/CpuDxe/CpuPageTable.c +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c @@ -23,6 +23,8 @@ #include #include #include + +#include "CpuDxe.h" #include "CpuPageTable.h" /// @@ -634,10 +636,10 @@ ConvertMemoryPageAttributes ( switch(CurrentPagingContext.MachineType) { case IMAGE_FILE_MACHINE_I386: if (CurrentPagingContext.ContextData.Ia32.PageTableBase == 0) { - DEBUG ((DEBUG_ERROR, "PageTable is 0!\n")); if (Attributes == 0) { return EFI_SUCCESS; } else { + DEBUG ((DEBUG_ERROR, "PageTable is 0!\n")); return EFI_UNSUPPORTED; } } @@ -767,6 +769,103 @@ AssignMemoryPageAttributes ( return Status; } +/** + Update GCD memory space attributes according to current page table setup. +**/ +VOID +RefreshGcdMemoryAttributesFromPaging ( + VOID + ) +{ + EFI_STATUS Status; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext; + PAGE_ATTRIBUTE PageAttribute; + UINT64 *PageEntry; + UINT64 PageLength; + UINT64 MemorySpaceLength; + UINT64 Length; + UINT64 BaseAddress; + UINT64 PageStartAddress; + UINT64 Attributes; + UINT64 Capabilities; + BOOLEAN DoUpdate; + UINTN Index; + + // + // Assuming that memory space map returned is sorted already; otherwise sort + // them in the order of lowest address to highest address. + // + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + ASSERT_EFI_ERROR (Status); + + GetCurrentPagingContext (&PagingContext); + + BaseAddress = 0; + PageLength = 0; + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + continue; + } + + if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) { + // + // Current memory space starts at a new page. Resetting PageLength will + // trigger a retrieval of page attributes at new address. + // + PageLength = 0; + } else { + // + // In case current memory space is not adjacent to last one + // + PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress); + } + + // Sync real page attributes to GCD + BaseAddress = MemorySpaceMap[Index].BaseAddress; + MemorySpaceLength = MemorySpaceMap[Index].Length; + while (MemorySpaceLength > 0) { + if (PageLength == 0) { + PageEntry = GetPageTableEntry (&PagingContext, BaseAddress, &PageAttribute); + if (PageEntry == NULL) { + break; + } + + // + // Note current memory space might start in the middle of a page + // + PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute); + PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress); + Attributes = GetAttributesFromPageEntry (PageEntry); + + if (Attributes != (MemorySpaceMap[Index].Attributes & EFI_MEMORY_PAGETYPE_MASK)) { + DoUpdate = TRUE; + Attributes |= (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_PAGETYPE_MASK); + Capabilities = Attributes | MemorySpaceMap[Index].Capabilities; + } else { + DoUpdate = FALSE; + } + } + + Length = MIN (PageLength, MemorySpaceLength); + if (DoUpdate) { + gDS->SetMemorySpaceCapabilities (BaseAddress, Length, Capabilities); + gDS->SetMemorySpaceAttributes (BaseAddress, Length, Attributes); + DEBUG ((DEBUG_INFO, "Update memory space attribute: [%02d] %016lx - %016lx (%08lx -> %08lx)\r\n", + Index, BaseAddress, BaseAddress + Length - 1, + MemorySpaceMap[Index].Attributes, Attributes)); + } + + PageLength -= Length; + MemorySpaceLength -= Length; + BaseAddress += Length; + } + } + + FreePool (MemorySpaceMap); +} + /** Initialize the Page Table lib. **/