From: "Ni, Ray" <ray.ni@intel.com>
To: "Tan, Dun" <dun.tan@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Dong, Eric" <eric.dong@intel.com>,
"Kumar, Rahul R" <rahul.r.kumar@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [Patch V5 20/22] UefiCpuPkg/CpuPageTableLib: Enable PAE paging
Date: Fri, 24 Mar 2023 08:10:01 +0000 [thread overview]
Message-ID: <MN6PR11MB82446761B617FAE9D0B75BA78C849@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20230324060020.940-21-dun.tan@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
> -----Original Message-----
> From: Tan, Dun <dun.tan@intel.com>
> Sent: Friday, March 24, 2023 2:00 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; Kumar,
> Rahul R <rahul.r.kumar@intel.com>; Gerd Hoffmann <kraxel@redhat.com>
> Subject: [Patch V5 20/22] 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>
> 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 8:10 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 ` [Patch V5 20/22] UefiCpuPkg/CpuPageTableLib: Enable PAE paging duntan
2023-03-24 8:10 ` Ni, Ray [this message]
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=MN6PR11MB82446761B617FAE9D0B75BA78C849@MN6PR11MB8244.namprd11.prod.outlook.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