TianoCore EDK2 master
|
#include <Base.h>
#include <Uefi.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/SerialPortLib.h>
#include <Library/SynchronizationLib.h>
#include <Library/PrintLib.h>
#include <Protocol/SmmBase2.h>
#include <Register/Intel/Cpuid.h>
#include <Register/Intel/Msr.h>
#include "CpuDxe.h"
#include "CpuPageTable.h"
Go to the source code of this file.
Data Structures | |
struct | PAGE_ATTRIBUTE_TABLE |
Macros | |
#define | IA32_PG_P BIT0 |
#define | IA32_PG_RW BIT1 |
#define | IA32_PG_U BIT2 |
#define | IA32_PG_WT BIT3 |
#define | IA32_PG_CD BIT4 |
#define | IA32_PG_A BIT5 |
#define | IA32_PG_D BIT6 |
#define | IA32_PG_PS BIT7 |
#define | IA32_PG_PAT_2M BIT12 |
#define | IA32_PG_PAT_4K IA32_PG_PS |
#define | IA32_PG_PMNT BIT62 |
#define | IA32_PG_NX BIT63 |
#define | PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P) |
#define | PAGE_ATTRIBUTE_BITS_POST_SPLIT (IA32_PG_RW | IA32_PG_P) |
#define | IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P) |
#define | PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS) |
#define | PAGING_4K_MASK 0xFFF |
#define | PAGING_2M_MASK 0x1FFFFF |
#define | PAGING_1G_MASK 0x3FFFFFFF |
#define | PAGING_PAE_INDEX_MASK 0x1FF |
#define | PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull |
#define | PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull |
#define | PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull |
#define | MAX_PF_ENTRY_COUNT 10 |
#define | MAX_DEBUG_MESSAGE_LENGTH 0x100 |
#define | IA32_PF_EC_ID BIT4 |
Enumerations | |
enum | PAGE_ATTRIBUTE { PageNone , Page4K , Page2M , Page1G , PageNone , Page4K , Page2M , Page1G } |
enum | PAGE_ACTION { PageActionAssign , PageActionSet , PageActionClear } |
Functions | |
BOOLEAN | IsInSmm (VOID) |
VOID | GetCurrentPagingContext (IN OUT PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext) |
UINTN | PageAttributeToLength (IN PAGE_ATTRIBUTE PageAttribute) |
UINTN | PageAttributeToMask (IN PAGE_ATTRIBUTE PageAttribute) |
VOID * | GetPageTableEntry (IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext, IN PHYSICAL_ADDRESS Address, OUT PAGE_ATTRIBUTE *PageAttribute) |
UINT64 | GetAttributesFromPageEntry (IN UINT64 *PageEntry) |
VOID | ConvertPageEntryAttribute (IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext, IN UINT64 *PageEntry, IN UINT64 Attributes, IN PAGE_ACTION PageAction, OUT BOOLEAN *IsModified) |
PAGE_ATTRIBUTE | NeedSplitPage (IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 *PageEntry, IN PAGE_ATTRIBUTE PageAttribute) |
RETURN_STATUS | SplitPage (IN UINT64 *PageEntry, IN PAGE_ATTRIBUTE PageAttribute, IN PAGE_ATTRIBUTE SplitAttribute, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc) |
BOOLEAN | IsReadOnlyPageWriteProtected (VOID) |
VOID | DisableReadOnlyPageWriteProtect (VOID) |
VOID | EnableReadOnlyPageWriteProtect (VOID) |
RETURN_STATUS | ConvertMemoryPageAttributes (IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN PAGE_ACTION PageAction, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL, OUT BOOLEAN *IsSplitted OPTIONAL, OUT BOOLEAN *IsModified OPTIONAL) |
RETURN_STATUS EFIAPI | AssignMemoryPageAttributes (IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext OPTIONAL, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL) |
BOOLEAN | IsExecuteDisableEnabled (VOID) |
VOID | RefreshGcdMemoryAttributesFromPaging (VOID) |
BOOLEAN | InitializePageTablePool (IN UINTN PoolPages) |
VOID *EFIAPI | AllocatePageTableMemory (IN UINTN Pages) |
VOID EFIAPI | DebugExceptionHandler (IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext) |
VOID EFIAPI | PageFaultExceptionHandler (IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext) |
VOID | InitializePageTableLib (VOID) |
Variables | |
PAGE_ATTRIBUTE_TABLE | mPageAttributeTable [] |
PAGE_TABLE_POOL * | mPageTablePool = NULL |
BOOLEAN | mPageTablePoolLock = FALSE |
PAGE_TABLE_LIB_PAGING_CONTEXT | mPagingContext |
EFI_SMM_BASE2_PROTOCOL * | mSmmBase2 = NULL |
UINTN * | mPFEntryCount |
UINT64 *(* | mLastPFEntryPointer )[MAX_PF_ENTRY_COUNT] |
Page table management support.
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
Definition in file CpuPageTable.c.
#define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P) |
Definition at line 47 of file CpuPageTable.c.
#define IA32_PF_EC_ID BIT4 |
Definition at line 63 of file CpuPageTable.c.
#define IA32_PG_A BIT5 |
Definition at line 32 of file CpuPageTable.c.
#define IA32_PG_CD BIT4 |
Definition at line 31 of file CpuPageTable.c.
#define IA32_PG_D BIT6 |
Definition at line 33 of file CpuPageTable.c.
#define IA32_PG_NX BIT63 |
Definition at line 38 of file CpuPageTable.c.
#define IA32_PG_P BIT0 |
Page Table Entry
Definition at line 27 of file CpuPageTable.c.
#define IA32_PG_PAT_2M BIT12 |
Definition at line 35 of file CpuPageTable.c.
#define IA32_PG_PAT_4K IA32_PG_PS |
Definition at line 36 of file CpuPageTable.c.
#define IA32_PG_PMNT BIT62 |
Definition at line 37 of file CpuPageTable.c.
#define IA32_PG_PS BIT7 |
Definition at line 34 of file CpuPageTable.c.
#define IA32_PG_RW BIT1 |
Definition at line 28 of file CpuPageTable.c.
#define IA32_PG_U BIT2 |
Definition at line 29 of file CpuPageTable.c.
#define IA32_PG_WT BIT3 |
Definition at line 30 of file CpuPageTable.c.
#define MAX_DEBUG_MESSAGE_LENGTH 0x100 |
Definition at line 62 of file CpuPageTable.c.
#define MAX_PF_ENTRY_COUNT 10 |
Definition at line 61 of file CpuPageTable.c.
#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P) |
Definition at line 40 of file CpuPageTable.c.
#define PAGE_ATTRIBUTE_BITS_POST_SPLIT (IA32_PG_RW | IA32_PG_P) |
Definition at line 41 of file CpuPageTable.c.
#define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS) |
Definition at line 49 of file CpuPageTable.c.
#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull |
Definition at line 59 of file CpuPageTable.c.
#define PAGING_1G_MASK 0x3FFFFFFF |
Definition at line 53 of file CpuPageTable.c.
#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull |
Definition at line 58 of file CpuPageTable.c.
#define PAGING_2M_MASK 0x1FFFFF |
Definition at line 52 of file CpuPageTable.c.
#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull |
Definition at line 57 of file CpuPageTable.c.
#define PAGING_4K_MASK 0xFFF |
Definition at line 51 of file CpuPageTable.c.
#define PAGING_PAE_INDEX_MASK 0x1FF |
Definition at line 55 of file CpuPageTable.c.
enum PAGE_ACTION |
Definition at line 78 of file CpuPageTable.c.
enum PAGE_ATTRIBUTE |
Definition at line 65 of file CpuPageTable.c.
This API provides a way to allocate memory for page table.
This API can be called more than once to allocate memory for page tables.
Allocates the number of 4KB pages and returns a pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.
If Pages is 0, then NULL is returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
Pages | The number of 4 KB pages to allocate. |
Definition at line 1210 of file CpuPageTable.c.
RETURN_STATUS EFIAPI AssignMemoryPageAttributes | ( | IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext | OPTIONAL, |
IN PHYSICAL_ADDRESS | BaseAddress, | ||
IN UINT64 | Length, | ||
IN UINT64 | Attributes, | ||
IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc | OPTIONAL | ||
) |
This function assigns the page attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes.
Caller should make sure BaseAddress and Length is at page boundary.
Caller need guarantee the TPL <= TPL_NOTIFY, if there is split page request.
[in] | PagingContext | The paging context. NULL means get page table from current CPU context. |
[in] | BaseAddress | The physical address that is the start address of a memory region. |
[in] | Length | The size in bytes of the memory region. |
[in] | Attributes | The bit mask of attributes to set for the memory region. |
[in] | AllocatePagesFunc | If page split is needed, this function is used to allocate more pages. NULL mean page split is unsupported. |
RETURN_SUCCESS | The attributes were cleared for the memory region. |
RETURN_ACCESS_DENIED | The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. |
RETURN_INVALID_PARAMETER | Length is zero. Attributes specified an illegal combination of attributes that cannot be set together. |
RETURN_OUT_OF_RESOURCES | There are not enough system resources to modify the attributes of the memory resource range. |
RETURN_UNSUPPORTED | The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. |
Definition at line 912 of file CpuPageTable.c.
RETURN_STATUS ConvertMemoryPageAttributes | ( | IN PAGE_TABLE_LIB_PAGING_CONTEXT *PagingContext | OPTIONAL, |
IN PHYSICAL_ADDRESS | BaseAddress, | ||
IN UINT64 | Length, | ||
IN UINT64 | Attributes, | ||
IN PAGE_ACTION | PageAction, | ||
IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc | OPTIONAL, | ||
OUT BOOLEAN *IsSplitted | OPTIONAL, | ||
OUT BOOLEAN *IsModified | OPTIONAL | ||
) |
This function modifies the page attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes.
Caller should make sure BaseAddress and Length is at page boundary.
[in] | PagingContext | The paging context. NULL means get page table from current CPU context. |
[in] | BaseAddress | The physical address that is the start address of a memory region. |
[in] | Length | The size in bytes of the memory region. |
[in] | Attributes | The bit mask of attributes to modify for the memory region. |
[in] | PageAction | The page action. |
[in] | AllocatePagesFunc | If page split is needed, this function is used to allocate more pages. NULL mean page split is unsupported. |
[out] | IsSplitted | TRUE means page table splitted. FALSE means page table not splitted. |
[out] | IsModified | TRUE means page table modified. FALSE means page table not modified. |
RETURN_SUCCESS | The attributes were modified for the memory region. |
RETURN_ACCESS_DENIED | The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. |
RETURN_INVALID_PARAMETER | Length is zero. Attributes specified an illegal combination of attributes that cannot be set together. |
RETURN_OUT_OF_RESOURCES | There are not enough system resources to modify the attributes of the memory resource range. |
RETURN_UNSUPPORTED | The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. |
Definition at line 719 of file CpuPageTable.c.
VOID ConvertPageEntryAttribute | ( | IN PAGE_TABLE_LIB_PAGING_CONTEXT * | PagingContext, |
IN UINT64 * | PageEntry, | ||
IN UINT64 | Attributes, | ||
IN PAGE_ACTION | PageAction, | ||
OUT BOOLEAN * | IsModified | ||
) |
Modify memory attributes of page entry.
[in] | PagingContext | The paging context. |
[in] | PageEntry | The page entry. |
[in] | Attributes | The bit mask of attributes to modify for the memory region. |
[in] | PageAction | The page action. |
[out] | IsModified | TRUE means page table modified. FALSE means page table not modified. |
Definition at line 414 of file CpuPageTable.c.
VOID EFIAPI DebugExceptionHandler | ( | IN EFI_EXCEPTION_TYPE | ExceptionType, |
IN EFI_SYSTEM_CONTEXT | SystemContext | ||
) |
Special handler for #DB exception, which will restore the page attributes (not-present). It should work with #PF handler which will set pages to 'present'.
ExceptionType | Exception type. |
SystemContext | Pointer to EFI_SYSTEM_CONTEXT. |
Definition at line 1250 of file CpuPageTable.c.
VOID DisableReadOnlyPageWriteProtect | ( | VOID | ) |
Disable Write Protect on pages marked as read-only.
Definition at line 651 of file CpuPageTable.c.
VOID EnableReadOnlyPageWriteProtect | ( | VOID | ) |
Enable Write Protect on pages marked as read-only.
Definition at line 672 of file CpuPageTable.c.
UINT64 GetAttributesFromPageEntry | ( | IN UINT64 * | PageEntry | ) |
Return memory attributes of page entry.
[in] | PageEntry | The page entry. |
Definition at line 382 of file CpuPageTable.c.
VOID GetCurrentPagingContext | ( | IN OUT PAGE_TABLE_LIB_PAGING_CONTEXT * | PagingContext | ) |
Return current paging context.
[in,out] | PagingContext | The paging context. |
Definition at line 151 of file CpuPageTable.c.
VOID * GetPageTableEntry | ( | IN PAGE_TABLE_LIB_PAGING_CONTEXT * | PagingContext, |
IN PHYSICAL_ADDRESS | Address, | ||
OUT PAGE_ATTRIBUTE * | PageAttribute | ||
) |
Return page table entry to match the address.
[in] | PagingContext | The paging context. |
[in] | Address | The address to be checked. |
[out] | PageAttributes | The page attribute of the page entry. |
Definition at line 283 of file CpuPageTable.c.
VOID InitializePageTableLib | ( | VOID | ) |
Initialize the Page Table lib.
Definition at line 1401 of file CpuPageTable.c.
Initialize a buffer pool for page table use only.
To reduce the potential split operation on page table, the pages reserved for page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGES and at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always initialized with number of pages greater than or equal to the given PoolPages.
Once the pages in the pool are used up, this method should be called again to reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. Usually this won't happen often in practice.
[in] | PoolPages | The least page number of the pool to be created. |
TRUE | The pool is initialized successfully. |
FALSE | The memory is out of resource. |
Definition at line 1117 of file CpuPageTable.c.
BOOLEAN IsExecuteDisableEnabled | ( | VOID | ) |
Check if Execute Disable feature is enabled or not.
Definition at line 946 of file CpuPageTable.c.
BOOLEAN IsInSmm | ( | VOID | ) |
Check if current execution environment is in SMM mode or not, via EFI_SMM_BASE2_PROTOCOL.
This is necessary because of the fact that MdePkg\Library\SmmMemoryAllocationLib supports to free memory outside SMRAM. The library will call gBS->FreePool() or gBS->FreePages() and then SetMemorySpaceAttributes interface in turn to change memory paging attributes during free operation, if some memory related features are enabled (like Heap Guard).
This means that SetMemorySpaceAttributes() has chance to run in SMM mode. This will cause incorrect result because SMM mode always loads its own page tables, which are usually different from DXE. This function can be used to detect such situation and help to avoid further misoperations.
TRUE | In SMM mode. |
FALSE | Not in SMM mode. |
Definition at line 120 of file CpuPageTable.c.
BOOLEAN IsReadOnlyPageWriteProtected | ( | VOID | ) |
Check the WP status in CR0 register. This bit is used to lock or unlock write access to pages marked as read-only.
TRUE | Write protection is enabled. |
FALSE | Write protection is disabled. |
Definition at line 629 of file CpuPageTable.c.
PAGE_ATTRIBUTE NeedSplitPage | ( | IN PHYSICAL_ADDRESS | BaseAddress, |
IN UINT64 | Length, | ||
IN UINT64 * | PageEntry, | ||
IN PAGE_ATTRIBUTE | PageAttribute | ||
) |
This function returns if there is need to split page entry.
[in] | BaseAddress | The base address to be checked. |
[in] | Length | The length to be checked. |
[in] | PageEntry | The page entry to be checked. |
[in] | PageAttribute | The page attribute of the page entry. |
SplitAttributes | on if there is need to split page entry. |
Definition at line 516 of file CpuPageTable.c.
Return length according to page attributes.
[in] | PageAttributes | The page attribute of the page entry. |
Definition at line 235 of file CpuPageTable.c.
Return address mask according to page attributes.
[in] | PageAttributes | The page attribute of the page entry. |
Definition at line 258 of file CpuPageTable.c.
VOID EFIAPI PageFaultExceptionHandler | ( | IN EFI_EXCEPTION_TYPE | ExceptionType, |
IN EFI_SYSTEM_CONTEXT | SystemContext | ||
) |
Special handler for #PF exception, which will set the pages which caused #PF to be 'present'. The attribute of those pages should be restored in the subsequent #DB handler.
ExceptionType | Exception type. |
SystemContext | Pointer to EFI_SYSTEM_CONTEXT. |
Definition at line 1310 of file CpuPageTable.c.
VOID RefreshGcdMemoryAttributesFromPaging | ( | VOID | ) |
Update GCD memory space attributes according to current page table setup.
Definition at line 960 of file CpuPageTable.c.
RETURN_STATUS SplitPage | ( | IN UINT64 * | PageEntry, |
IN PAGE_ATTRIBUTE | PageAttribute, | ||
IN PAGE_ATTRIBUTE | SplitAttribute, | ||
IN PAGE_TABLE_LIB_ALLOCATE_PAGES | AllocatePagesFunc | ||
) |
This function splits one page entry to small page entries.
[in] | PageEntry | The page entry to be splitted. |
[in] | PageAttribute | The page attribute of the page entry. |
[in] | SplitAttribute | How to split the page entry. |
[in] | AllocatePagesFunc | If page split is needed, this function is used to allocate more pages. |
RETURN_SUCCESS | The page entry is splitted. |
RETURN_UNSUPPORTED | The page entry does not support to be splitted. |
RETURN_OUT_OF_RESOURCES | No resource to split page entry. |
Definition at line 551 of file CpuPageTable.c.
UINT64*(* mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT] |
Definition at line 99 of file CpuPageTable.c.
PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] |
Definition at line 84 of file CpuPageTable.c.
PAGE_TABLE_POOL* mPageTablePool = NULL |
Definition at line 90 of file CpuPageTable.c.
BOOLEAN mPageTablePoolLock = FALSE |
Definition at line 91 of file CpuPageTable.c.
PAGE_TABLE_LIB_PAGING_CONTEXT mPagingContext |
Definition at line 92 of file CpuPageTable.c.
UINTN* mPFEntryCount |
Definition at line 98 of file CpuPageTable.c.
EFI_SMM_BASE2_PROTOCOL* mSmmBase2 = NULL |
Definition at line 93 of file CpuPageTable.c.