UefiCpuPkg/CpuPageTableLib: Enable PAE paging
Modify CpuPageTableLib code to enable PAE paging. In PageTableMap() API: When creating new PAE page table, after creating page table, set all MustBeZero fields of 4 PDPTE to 0. The MustBeZero fields are treated as RW and other attributes by the common map logic. So they might be set to 1. When updating exsiting PAE page table, the special steps are: 1.Prepare 4K-aligned 32bytes memory in stack for 4 temp PDPTE. 2.Copy original 4 PDPTE to the 4 temp PDPTE and set the RW, UserSupervisor to 1 and set Nx of 4 temp PDPTE to 0. 4.After updating the page table, set the MustBeZero fields of 4 temp PDPTE to 0. 5.Copy the temp PDPTE to original PDPTE. In PageTableParse() API, also create 4 temp PDPTE in stack. Copy original 4 PDPTE to the 4 temp PDPTE. Then set the RW, UserSupervisor to 1 and set Nx of 4 temp PDPTE to 0. Finally use the address of temp PDPTE as the page table address. Signed-off-by: Dun Tan <dun.tan@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Tested-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
This library implements CpuPageTableLib that are generic for IA32 family CPU.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
@@ -158,6 +158,7 @@ VOID
|
||||
PageTableLibParsePnle (
|
||||
IN UINT64 PageTableBaseAddress,
|
||||
IN UINTN Level,
|
||||
IN UINTN MaxLevel,
|
||||
IN UINT64 RegionStart,
|
||||
IN IA32_MAP_ATTRIBUTE *ParentMapAttribute,
|
||||
IN OUT IA32_MAP_ENTRY *Map,
|
||||
@@ -171,13 +172,15 @@ PageTableLibParsePnle (
|
||||
UINTN Index;
|
||||
IA32_MAP_ATTRIBUTE MapAttribute;
|
||||
UINT64 RegionLength;
|
||||
UINTN PagingEntryNumber;
|
||||
|
||||
ASSERT (OneEntry != NULL);
|
||||
|
||||
PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTableBaseAddress;
|
||||
RegionLength = REGION_LENGTH (Level);
|
||||
PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTableBaseAddress;
|
||||
RegionLength = REGION_LENGTH (Level);
|
||||
PagingEntryNumber = ((MaxLevel == 3) && (Level == 3)) ? MAX_PAE_PDPTE_NUM : 512;
|
||||
|
||||
for (Index = 0; Index < 512; Index++, RegionStart += RegionLength) {
|
||||
for (Index = 0; Index < PagingEntryNumber; Index++, RegionStart += RegionLength) {
|
||||
if (PagingEntry[Index].Pce.Present == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -228,6 +231,7 @@ PageTableLibParsePnle (
|
||||
PageTableLibParsePnle (
|
||||
IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry[Index].Pnle),
|
||||
Level - 1,
|
||||
MaxLevel,
|
||||
RegionStart,
|
||||
&MapAttribute,
|
||||
Map,
|
||||
@@ -269,6 +273,8 @@ PageTableParse (
|
||||
IA32_MAP_ENTRY *LastEntry;
|
||||
IA32_MAP_ENTRY OneEntry;
|
||||
UINTN MaxLevel;
|
||||
UINTN Index;
|
||||
IA32_PAGING_ENTRY BufferInStack[MAX_PAE_PDPTE_NUM];
|
||||
|
||||
if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
|
||||
//
|
||||
@@ -290,6 +296,17 @@ PageTableParse (
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
if (PagingMode == PagingPae) {
|
||||
CopyMem (BufferInStack, (VOID *)PageTable, sizeof (BufferInStack));
|
||||
for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
|
||||
BufferInStack[Index].Pnle.Bits.ReadWrite = 1;
|
||||
BufferInStack[Index].Pnle.Bits.UserSupervisor = 1;
|
||||
BufferInStack[Index].Pnle.Bits.Nx = 0;
|
||||
}
|
||||
|
||||
PageTable = (UINTN)BufferInStack;
|
||||
}
|
||||
|
||||
//
|
||||
// Page table layout is as below:
|
||||
//
|
||||
@@ -319,7 +336,7 @@ PageTableParse (
|
||||
MapCapacity = *MapCount;
|
||||
*MapCount = 0;
|
||||
LastEntry = NULL;
|
||||
PageTableLibParsePnle ((UINT64)PageTable, MaxLevel, 0, &NopAttribute, Map, MapCount, MapCapacity, &LastEntry, &OneEntry);
|
||||
PageTableLibParsePnle ((UINT64)PageTable, MaxLevel, MaxLevel, 0, &NopAttribute, Map, MapCount, MapCapacity, &LastEntry, &OneEntry);
|
||||
|
||||
if (*MapCount > MapCapacity) {
|
||||
return RETURN_BUFFER_TOO_SMALL;
|
||||
|
Reference in New Issue
Block a user