summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h4
-rw-r--r--UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c53
-rw-r--r--UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c27
3 files changed, 73 insertions, 11 deletions
diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
index 2c67ecb469..24da0ffb30 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
@@ -1,7 +1,7 @@
/** @file
Internal header for CpuPageTableLib.
- 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
**/
@@ -20,6 +20,8 @@
#define REGION_LENGTH(l) LShiftU64 (1, (l) * 9 + 3)
+#define MAX_PAE_PDPTE_NUM 4
+
typedef enum {
Pte = 1,
Pde = 2,
diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
index 0d576ce39a..eff02619fa 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
@@ -671,15 +671,17 @@ PageTableMap (
IA32_PAGE_LEVEL MaxLeafLevel;
IA32_MAP_ATTRIBUTE ParentAttribute;
BOOLEAN LocalIsModified;
+ UINTN Index;
+ IA32_PAGING_ENTRY *PagingEntry;
+ UINT8 BufferInStack[SIZE_4KB - 1 + MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY)];
if (Length == 0) {
return RETURN_SUCCESS;
}
- if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {
+ if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
//
// 32bit paging is never supported.
- // PAE paging will be supported later.
//
return RETURN_UNSUPPORTED;
}
@@ -716,17 +718,32 @@ PageTableMap (
MaxLeafLevel = (IA32_PAGE_LEVEL)(UINT8)PagingMode;
MaxLevel = (IA32_PAGE_LEVEL)(UINT8)(PagingMode >> 8);
- MaxLinearAddress = LShiftU64 (1, 12 + MaxLevel * 9);
+ MaxLinearAddress = (PagingMode == PagingPae) ? LShiftU64 (1, 32) : LShiftU64 (1, 12 + MaxLevel * 9);
if ((LinearAddress > MaxLinearAddress) || (Length > MaxLinearAddress - LinearAddress)) {
//
- // Maximum linear address is (1 << 48) or (1 << 57)
+ // Maximum linear address is (1 << 32), (1 << 48) or (1 << 57)
//
return RETURN_INVALID_PARAMETER;
}
TopPagingEntry.Uintn = *PageTable;
if (TopPagingEntry.Uintn != 0) {
+ if (PagingMode == PagingPae) {
+ //
+ // Create 4 temporary PDPTE at a 4k-aligned address.
+ // Copy the original PDPTE content and set ReadWrite, UserSupervisor to 1, set Nx to 0.
+ //
+ TopPagingEntry.Uintn = ALIGN_VALUE ((UINTN)BufferInStack, BASE_4KB);
+ PagingEntry = (IA32_PAGING_ENTRY *)(TopPagingEntry.Uintn);
+ CopyMem (PagingEntry, (VOID *)(*PageTable), MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY));
+ for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
+ PagingEntry[Index].Pnle.Bits.ReadWrite = 1;
+ PagingEntry[Index].Pnle.Bits.UserSupervisor = 1;
+ PagingEntry[Index].Pnle.Bits.Nx = 0;
+ }
+ }
+
TopPagingEntry.Pce.Present = 1;
TopPagingEntry.Pce.ReadWrite = 1;
TopPagingEntry.Pce.UserSupervisor = 1;
@@ -801,7 +818,33 @@ PageTableMap (
);
if (!RETURN_ERROR (Status)) {
- *PageTable = (UINTN)(TopPagingEntry.Uintn & IA32_PE_BASE_ADDRESS_MASK_40);
+ PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)(TopPagingEntry.Uintn & IA32_PE_BASE_ADDRESS_MASK_40);
+
+ if (PagingMode == PagingPae) {
+ //
+ // These MustBeZero fields are treated as RW and other attributes by the common map logic. So they might be set to 1.
+ //
+ for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
+ PagingEntry[Index].PdptePae.Bits.MustBeZero = 0;
+ PagingEntry[Index].PdptePae.Bits.MustBeZero2 = 0;
+ PagingEntry[Index].PdptePae.Bits.MustBeZero3 = 0;
+ }
+
+ if (*PageTable != 0) {
+ //
+ // Copy temp PDPTE to original PDPTE.
+ //
+ CopyMem ((VOID *)(*PageTable), PagingEntry, MAX_PAE_PDPTE_NUM * sizeof (IA32_PAGING_ENTRY));
+ }
+ }
+
+ if (*PageTable == 0) {
+ //
+ // Do not assign the *PageTable when it's an existing page table.
+ // If it's an existing PAE page table, PagingEntry is the temp buffer in stack.
+ //
+ *PageTable = (UINTN)PagingEntry;
+ }
}
return Status;
diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
index 65490751ab..37466e4e10 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
@@ -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;