public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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


  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