#include <Library/DebugLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Protocol/MpService.h>\r
+\r
+#include "CpuDxe.h"\r
#include "CpuPageTable.h"\r
\r
///\r
return Status;\r
}\r
\r
+/**\r
+ Update GCD memory space attributes according to current page table setup.\r
+**/\r
+VOID\r
+RefreshGcdMemoryAttributesFromPaging (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+ PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext;\r
+ PAGE_ATTRIBUTE PageAttribute;\r
+ UINT64 *PageEntry;\r
+ UINT64 PageLength;\r
+ UINT64 MemorySpaceLength;\r
+ UINT64 Length;\r
+ UINT64 BaseAddress;\r
+ UINT64 PageStartAddress;\r
+ UINT64 Attributes;\r
+ UINT64 Capabilities;\r
+ BOOLEAN DoUpdate;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Assuming that memory space map returned is sorted already; otherwise sort\r
+ // them in the order of lowest address to highest address.\r
+ //\r
+ Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ GetCurrentPagingContext (&PagingContext);\r
+\r
+ BaseAddress = 0;\r
+ PageLength = 0;\r
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+ continue;\r
+ }\r
+\r
+ if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress + PageLength)) {\r
+ //\r
+ // Current memory space starts at a new page. Resetting PageLength will\r
+ // trigger a retrieval of page attributes at new address.\r
+ //\r
+ PageLength = 0;\r
+ } else {\r
+ //\r
+ // In case current memory space is not adjacent to last one\r
+ //\r
+ PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);\r
+ }\r
+\r
+ // Sync real page attributes to GCD\r
+ BaseAddress = MemorySpaceMap[Index].BaseAddress;\r
+ MemorySpaceLength = MemorySpaceMap[Index].Length;\r
+ while (MemorySpaceLength > 0) {\r
+ if (PageLength == 0) {\r
+ PageEntry = GetPageTableEntry (&PagingContext, BaseAddress, &PageAttribute);\r
+ if (PageEntry == NULL) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Note current memory space might start in the middle of a page\r
+ //\r
+ PageStartAddress = (*PageEntry) & (UINT64)PageAttributeToMask(PageAttribute);\r
+ PageLength = PageAttributeToLength (PageAttribute) - (BaseAddress - PageStartAddress);\r
+ Attributes = GetAttributesFromPageEntry (PageEntry);\r
+\r
+ if (Attributes != (MemorySpaceMap[Index].Attributes & EFI_MEMORY_PAGETYPE_MASK)) {\r
+ DoUpdate = TRUE;\r
+ Attributes |= (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_PAGETYPE_MASK);\r
+ Capabilities = Attributes | MemorySpaceMap[Index].Capabilities;\r
+ } else {\r
+ DoUpdate = FALSE;\r
+ }\r
+ }\r
+\r
+ Length = MIN (PageLength, MemorySpaceLength);\r
+ if (DoUpdate) {\r
+ gDS->SetMemorySpaceCapabilities (BaseAddress, Length, Capabilities);\r
+ gDS->SetMemorySpaceAttributes (BaseAddress, Length, Attributes);\r
+ DEBUG ((DEBUG_INFO, "Update memory space attribute: [%02d] %016lx - %016lx (%08lx -> %08lx)\r\n",\r
+ Index, BaseAddress, BaseAddress + Length - 1,\r
+ MemorySpaceMap[Index].Attributes, Attributes));\r
+ }\r
+\r
+ PageLength -= Length;\r
+ MemorySpaceLength -= Length;\r
+ BaseAddress += Length;\r
+ }\r
+ }\r
+\r
+ FreePool (MemorySpaceMap);\r
+}\r
+\r
/**\r
Initialize the Page Table lib.\r
**/\r