/** @file\r
Page table management support.\r
\r
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
#include <Library/SynchronizationLib.h>\r
#include <Library/PrintLib.h>\r
#include <Protocol/SmmBase2.h>\r
-#include <Register/Cpuid.h>\r
-#include <Register/Msr.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <Register/Intel/Msr.h>\r
\r
#include "CpuDxe.h"\r
#include "CpuPageTable.h"\r
\r
-///\r
-/// Paging registers\r
-///\r
-#define CR0_WP BIT16\r
-#define CR0_PG BIT31\r
-#define CR4_PSE BIT4\r
-#define CR4_PAE BIT5\r
-\r
///\r
/// Page Table Entry\r
///\r
UINT32 RegEax;\r
CPUID_EXTENDED_CPU_SIG_EDX RegEdx;\r
MSR_IA32_EFER_REGISTER MsrEfer;\r
+ IA32_CR4 Cr4;\r
+ IA32_CR0 Cr0;\r
+ UINT32 *Attributes;\r
+ UINTN *PageTableBase;\r
\r
//\r
// Don't retrieve current paging context from processor if in SMM mode.\r
} else {\r
mPagingContext.MachineType = IMAGE_FILE_MACHINE_I386;\r
}\r
- if ((AsmReadCr0 () & CR0_PG) != 0) {\r
- mPagingContext.ContextData.X64.PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
+\r
+ GetPagingDetails (&mPagingContext.ContextData, &PageTableBase, &Attributes);\r
+\r
+ Cr0.UintN = AsmReadCr0 ();\r
+ Cr4.UintN = AsmReadCr4 ();\r
+\r
+ if (Cr0.Bits.PG != 0) {\r
+ *PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
} else {\r
- mPagingContext.ContextData.X64.PageTableBase = 0;\r
+ *PageTableBase = 0;\r
}\r
-\r
- if ((AsmReadCr4 () & CR4_PSE) != 0) {\r
- mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;\r
+ if (Cr0.Bits.WP != 0) {\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
+ }\r
+ if (Cr4.Bits.PSE != 0) {\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;\r
}\r
- if ((AsmReadCr4 () & CR4_PAE) != 0) {\r
- mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;\r
+ if (Cr4.Bits.PAE != 0) {\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;\r
}\r
- if ((AsmReadCr0 () & CR0_WP) != 0) {\r
- mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
+ if (Cr4.Bits.LA57 != 0) {\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL;\r
}\r
\r
AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
MsrEfer.Uint64 = AsmReadMsr64(MSR_CORE_IA32_EFER);\r
if (MsrEfer.Bits.NXE != 0) {\r
// XD activated\r
- mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;\r
}\r
}\r
\r
if (RegEdx.Bits.Page1GB != 0) {\r
- mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;\r
+ *Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;\r
}\r
}\r
}\r
UINTN Index2;\r
UINTN Index3;\r
UINTN Index4;\r
+ UINTN Index5;\r
UINT64 *L1PageTable;\r
UINT64 *L2PageTable;\r
UINT64 *L3PageTable;\r
UINT64 *L4PageTable;\r
+ UINT64 *L5PageTable;\r
UINT64 AddressEncMask;\r
\r
ASSERT (PagingContext != NULL);\r
\r
+ Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK;\r
Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;\r
Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;\r
Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;\r
AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
\r
if (PagingContext->MachineType == IMAGE_FILE_MACHINE_X64) {\r
- L4PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+ if ((PagingContext->ContextData.X64.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL) != 0) {\r
+ L5PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+ if (L5PageTable[Index5] == 0) {\r
+ *PageAttribute = PageNone;\r
+ return NULL;\r
+ }\r
+\r
+ L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
+ } else {\r
+ L4PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+ }\r
if (L4PageTable[Index4] == 0) {\r
*PageAttribute = PageNone;\r
return NULL;\r
{\r
UINT64 CurrentPageEntry;\r
UINT64 NewPageEntry;\r
+ UINT32 *PageAttributes;\r
\r
CurrentPageEntry = *PageEntry;\r
NewPageEntry = CurrentPageEntry;\r
break;\r
}\r
}\r
- if ((PagingContext->ContextData.Ia32.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED) != 0) {\r
+\r
+ GetPagingDetails (&PagingContext->ContextData, NULL, &PageAttributes);\r
+\r
+ if ((*PageAttributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED) != 0) {\r
if ((Attributes & EFI_MEMORY_XP) != 0) {\r
switch (PageAction) {\r
case PageActionAssign:\r
VOID\r
)\r
{\r
+ IA32_CR0 Cr0;\r
//\r
// To avoid unforseen consequences, don't touch paging settings in SMM mode\r
// in this driver.\r
//\r
if (!IsInSmm ()) {\r
- return ((AsmReadCr0 () & CR0_WP) != 0);\r
+ Cr0.UintN = AsmReadCr0 ();\r
+ return (BOOLEAN) (Cr0.Bits.WP != 0);\r
}\r
return FALSE;\r
}\r
VOID\r
)\r
{\r
+ IA32_CR0 Cr0;\r
//\r
// To avoid unforseen consequences, don't touch paging settings in SMM mode\r
// in this driver.\r
//\r
if (!IsInSmm ()) {\r
- AsmWriteCr0 (AsmReadCr0 () & ~CR0_WP);\r
+ Cr0.UintN = AsmReadCr0 ();\r
+ Cr0.Bits.WP = 0;\r
+ AsmWriteCr0 (Cr0.UintN);\r
}\r
}\r
\r
VOID\r
)\r
{\r
+ IA32_CR0 Cr0;\r
//\r
// To avoid unforseen consequences, don't touch paging settings in SMM mode\r
// in this driver.\r
//\r
if (!IsInSmm ()) {\r
- AsmWriteCr0 (AsmReadCr0 () | CR0_WP);\r
+ Cr0.UintN = AsmReadCr0 ();\r
+ Cr0.Bits.WP = 1;\r
+ AsmWriteCr0 (Cr0.UintN);\r
}\r
}\r
\r
}\r
\r
//\r
- // Below logic is to check 2M/4K page to make sure we donot waist memory.\r
+ // Below logic is to check 2M/4K page to make sure we do not waste memory.\r
//\r
Status = EFI_SUCCESS;\r
while (Length != 0) {\r
\r
Caller should make sure BaseAddress and Length is at page boundary.\r
\r
- Caller need guarentee the TPL <= TPL_NOTIFY, if there is split page request.\r
+ Caller need guarantee the TPL <= TPL_NOTIFY, if there is split page request.\r
\r
@param[in] PagingContext The paging context. NULL means get page table from current CPU context.\r
@param[in] BaseAddress The physical address that is the start address of a memory region.\r
);\r
if (EFI_ERROR (Status)) {\r
//\r
- // If we cannot udpate the capabilities, we cannot update its\r
+ // If we cannot update the capabilities, we cannot update its\r
// attributes either. So just simply skip current block of memory.\r
//\r
DEBUG ((\r
)\r
{\r
PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext;\r
+ UINT32 *Attributes;\r
+ UINTN *PageTableBase;\r
\r
GetCurrentPagingContext (&CurrentPagingContext);\r
\r
+ GetPagingDetails (&CurrentPagingContext.ContextData, &PageTableBase, &Attributes);\r
+\r
//\r
// Reserve memory of page tables for future uses, if paging is enabled.\r
//\r
- if (CurrentPagingContext.ContextData.X64.PageTableBase != 0 &&\r
- (CurrentPagingContext.ContextData.Ia32.Attributes &\r
- PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE) != 0) {\r
+ if ((*PageTableBase != 0) &&\r
+ (*Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE) != 0) {\r
DisableReadOnlyPageWriteProtect ();\r
InitializePageTablePool (1);\r
EnableReadOnlyPageWriteProtect ();\r
ASSERT (mLastPFEntryPointer != NULL);\r
}\r
\r
- DEBUG ((DEBUG_INFO, "CurrentPagingContext:\n", CurrentPagingContext.MachineType));\r
+ DEBUG ((DEBUG_INFO, "CurrentPagingContext:\n"));\r
DEBUG ((DEBUG_INFO, " MachineType - 0x%x\n", CurrentPagingContext.MachineType));\r
- DEBUG ((DEBUG_INFO, " PageTableBase - 0x%x\n", CurrentPagingContext.ContextData.X64.PageTableBase));\r
- DEBUG ((DEBUG_INFO, " Attributes - 0x%x\n", CurrentPagingContext.ContextData.X64.Attributes));\r
+ DEBUG ((DEBUG_INFO, " PageTableBase - 0x%Lx\n", (UINT64)*PageTableBase));\r
+ DEBUG ((DEBUG_INFO, " Attributes - 0x%x\n", *Attributes));\r
\r
return ;\r
}\r