From: "duntan" <dun.tan@intel.com>
To: devel@edk2.groups.io
Cc: Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
Rahul Kumar <rahul1.kumar@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: [Patch V5 20/22] UefiCpuPkg/CpuPageTableLib: Enable PAE paging
Date: Fri, 24 Mar 2023 14:00:18 +0800 [thread overview]
Message-ID: <20230324060020.940-21-dun.tan@intel.com> (raw)
In-Reply-To: <20230324060020.940-1-dun.tan@intel.com>
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>
Cc: 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>
---
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h | 2 ++
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-----
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c | 25 +++++++++++++++++++++----
3 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
index 2c67ecb469..8c4d43be89 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTable.h
@@ -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 2430f1b37c..7cdba0d77f 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..f6d7b9bb4c 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableParse.c
@@ -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;
--
2.31.1.windows.1
next prev parent reply other threads:[~2023-03-24 6:01 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-24 5:59 [Patch V5 00/22] Fix issues in CpuPageTableLib duntan
2023-03-24 5:59 ` [Patch V5 01/22] UefiCpuPkg/CpuPageTableLib: Remove unneeded 'if' condition duntan
2023-03-24 6:00 ` [Patch V5 02/22] UefiCpuPkg/CpuPageTableLib: Add check for input Length duntan
2023-03-24 6:00 ` [Patch V5 03/22] UefiCpuPkg/CpuPageTableLib:Initialize some LocalVariable at beginning duntan
2023-03-24 6:00 ` [Patch V5 04/22] UefiCpuPkg/CpuPageTableLib: Fix the non-1:1 mapping issue duntan
2023-03-24 6:00 ` [Patch V5 05/22] UefiCpuPkg/CpuPageTableLib:Clear PageSize bit(Bit7) for non-leaf duntan
2023-03-24 6:00 ` [Patch V5 06/22] UefiCpuPkg/CpuPageTableLib: Fix issue when splitting leaf entry duntan
2023-03-24 6:00 ` [Patch V5 07/22] UefiCpuPkg/MpInitLib: Add code to initialize MapMask duntan
2023-03-24 6:00 ` [Patch V5 08/22] UefiCpuPkg/CpuPageTableLib:Add check for Mask and Attr duntan
2023-03-24 8:06 ` Ni, Ray
2023-03-24 6:00 ` [Patch V5 09/22] UefiCpuPkg/CpuPageTableLib: Add manual test to check " duntan
2023-03-24 8:06 ` Ni, Ray
2023-03-24 6:00 ` [Patch V5 10/22] UefiCpuPkg/CpuPageTableLib:Modify RandomBoolean() in RandomTest duntan
2023-03-24 6:00 ` [Patch V5 11/22] UefiCpuPkg/CpuPageTableLib: Add LastMapEntry pointer duntan
2023-03-24 8:07 ` Ni, Ray
2023-03-24 6:00 ` [Patch V5 12/22] UefiCpuPkg/CpuPageTableLib:Modify RandomTest to check Mask/Attr duntan
2023-03-24 8:07 ` Ni, Ray
2023-03-24 6:00 ` [Patch V5 13/22] UefiCpuPkg/CpuPageTableLib: Enable non-1:1 mapping in random test duntan
2023-03-24 6:00 ` [Patch V5 14/22] UefiCpuPkg/CpuPageTableLib: Add OUTPUT IsModified parameter duntan
2023-03-24 8:08 ` Ni, Ray
2023-03-24 6:00 ` [Patch V5 15/22] UefiCpuPkg/CpuPageTableLib: Modify RandomTest to check IsModified duntan
2023-03-24 6:00 ` [Patch V5 16/22] UefiCpuPkg: Fix IA32 build failure in CpuPageTableLib.inf duntan
2023-03-24 6:00 ` [Patch V5 17/22] UefiCpuPkg: Modify UnitTest code since tested API is changed duntan
2023-03-24 6:00 ` [Patch V5 18/22] UefiCpuPkg/CpuPageTableLib: Add check for page table creation duntan
2023-03-24 6:00 ` [Patch V5 19/22] UefiCpuPkg: Combine branch for non-present and leaf ParentEntry duntan
2023-03-24 8:09 ` Ni, Ray
2023-03-24 6:00 ` duntan [this message]
2023-03-24 8:10 ` [Patch V5 20/22] UefiCpuPkg/CpuPageTableLib: Enable PAE paging Ni, Ray
2023-03-24 6:00 ` [Patch V5 21/22] UefiCpuPkg/CpuPageTableLib: Add RandomTest for " duntan
2023-03-24 6:00 ` [Patch V5 22/22] UefiCpuPkg/CpuPageTableLib: Reduce the number of random tests duntan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230324060020.940-21-dun.tan@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox