On 08/05/19 23:57, Krzysztof Rusocki wrote:
> From: Damian Nikodem <damian.niko...@intel.com>
> 
> Reclaim may free page table pages that are required to handle current page
> fault. This causes a page leak, and, after sufficent number of specific
> page fault+reclaim pairs, we run out of reclaimable pages and hit:
> 
> ASSERT (MinAcc != (UINT64)-1);
> 
> To remedy, prevent pages essential to handling current page fault:
> (1) from being considered as reclaim candidates (first reclaim phase)
> (2) from being freed as part of "branch cleanup" (second reclaim phase)
> 
> Signed-off-by: Damian Nikodem <damian.niko...@intel.com>
> Cc: Eric Dong <eric.d...@intel.com>
> Cc: Ray Ni <ray...@intel.com>
> Cc: Jian J Wang <jian.j.w...@intel.com>
> Cc: Laszlo Ersek <ler...@redhat.com>
> Cc: Krzysztof Rusocki <krzysztof.ruso...@intel.com>
> 
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c 
> b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> index a3b62f7787..f11323f439 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> @@ -543,6 +543,11 @@ ReclaimPages (
>    UINT64                       *ReleasePageAddress;
>    IA32_CR4                     Cr4;
>    BOOLEAN                      Enable5LevelPaging;
> +  UINT64                       PFAddress;
> +  UINT64                       PFAddressPml5Index;
> +  UINT64                       PFAddressPml4Index;
> +  UINT64                       PFAddressPdptIndex;
> +  UINT64                       PFAddressPdtIndex;
>  
>    Pml4 = NULL;
>    Pdpt = NULL;
> @@ -554,6 +559,11 @@ ReclaimPages (
>    MinPdt  = (UINTN)-1;
>    Acc     = 0;
>    ReleasePageAddress = 0;
> +  PFAddress = AsmReadCr2 ();
> +  PFAddressPml5Index = BitFieldRead64 (PFAddress, 48, 48 + 8);
> +  PFAddressPml4Index = BitFieldRead64 (PFAddress, 39, 39 + 8);
> +  PFAddressPdptIndex = BitFieldRead64 (PFAddress, 30, 30 + 8);
> +  PFAddressPdtIndex = BitFieldRead64 (PFAddress, 21, 21 + 8);
>  
>    Cr4.UintN = AsmReadCr4 ();
>    Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);
> @@ -628,40 +638,46 @@ ReclaimPages (
>                // we will find the entry has the smallest access record value
>                //
>                PDPTEIgnore = TRUE;
> -              Acc = GetAndUpdateAccNum (Pdt + PdtIndex);
> +              if (PdtIndex != PFAddressPdtIndex || PdptIndex != 
> PFAddressPdptIndex ||
> +                  Pml4Index != PFAddressPml4Index || Pml5Index != 
> PFAddressPml5Index) {
> +                Acc = GetAndUpdateAccNum (Pdt + PdtIndex);
> +                if (Acc < MinAcc) {
> +                  //
> +                  // If the PD entry has the smallest access record value,
> +                  // save the Page address to be released
> +                  //
> +                  MinAcc  = Acc;
> +                  MinPml5 = Pml5Index;
> +                  MinPml4 = Pml4Index;
> +                  MinPdpt = PdptIndex;
> +                  MinPdt  = PdtIndex;
> +                  ReleasePageAddress = Pdt + PdtIndex;
> +                }
> +              }
> +            }
> +          }
> +          if (!PDPTEIgnore) {
> +            //
> +            // If this PDPT entry has no PDT entries pointer to 4 KByte 
> pages,
> +            // it should only has the entries point to 2 MByte Pages
> +            //
> +            if (PdptIndex != PFAddressPdptIndex || Pml4Index != 
> PFAddressPml4Index ||
> +                Pml5Index != PFAddressPml5Index) {
> +              Acc = GetAndUpdateAccNum (Pdpt + PdptIndex);
>                if (Acc < MinAcc) {
>                  //
> -                // If the PD entry has the smallest access record value,
> +                // If the PDPT entry has the smallest access record value,
>                  // save the Page address to be released
>                  //
>                  MinAcc  = Acc;
>                  MinPml5 = Pml5Index;
>                  MinPml4 = Pml4Index;
>                  MinPdpt = PdptIndex;
> -                MinPdt  = PdtIndex;
> -                ReleasePageAddress = Pdt + PdtIndex;
> +                MinPdt  = (UINTN)-1;
> +                ReleasePageAddress = Pdpt + PdptIndex;
>                }
>              }
>            }
> -          if (!PDPTEIgnore) {
> -            //
> -            // If this PDPT entry has no PDT entries pointer to 4 KByte 
> pages,
> -            // it should only has the entries point to 2 MByte Pages
> -            //
> -            Acc = GetAndUpdateAccNum (Pdpt + PdptIndex);
> -            if (Acc < MinAcc) {
> -              //
> -              // If the PDPT entry has the smallest access record value,
> -              // save the Page address to be released
> -              //
> -              MinAcc  = Acc;
> -              MinPml5 = Pml5Index;
> -              MinPml4 = Pml4Index;
> -              MinPdpt = PdptIndex;
> -              MinPdt  = (UINTN)-1;
> -              ReleasePageAddress = Pdpt + PdptIndex;
> -            }
> -          }
>          }
>        }
>        if (!PML4EIgnore) {
> @@ -669,18 +685,20 @@ ReclaimPages (
>          // If PML4 entry has no the PDPT entry pointer to 2 MByte pages,
>          // it should only has the entries point to 1 GByte Pages
>          //
> -        Acc = GetAndUpdateAccNum (Pml4 + Pml4Index);
> -        if (Acc < MinAcc) {
> -          //
> -          // If the PML4 entry has the smallest access record value,
> -          // save the Page address to be released
> -          //
> -          MinAcc  = Acc;
> -          MinPml5 = Pml5Index;
> -          MinPml4 = Pml4Index;
> -          MinPdpt = (UINTN)-1;
> -          MinPdt  = (UINTN)-1;
> -          ReleasePageAddress = Pml4 + Pml4Index;
> +        if (Pml4Index != PFAddressPml4Index || Pml5Index != 
> PFAddressPml5Index) {
> +          Acc = GetAndUpdateAccNum (Pml4 + Pml4Index);
> +          if (Acc < MinAcc) {
> +            //
> +            // If the PML4 entry has the smallest access record value,
> +            // save the Page address to be released
> +            //
> +            MinAcc  = Acc;
> +            MinPml5 = Pml5Index;
> +            MinPml4 = Pml4Index;
> +            MinPdpt = (UINTN)-1;
> +            MinPdt  = (UINTN)-1;
> +            ReleasePageAddress = Pml4 + Pml4Index;
> +          }
>          }
>        }
>      }
> @@ -708,7 +726,8 @@ ReclaimPages (
>        Pml4 = (UINT64 *) (UINTN) (Pml5[MinPml5] & gPhyMask);
>        Pdpt = (UINT64*)(UINTN)(Pml4[MinPml4] & ~mAddressEncMask & gPhyMask);
>        SubEntriesNum = GetSubEntriesNum(Pdpt + MinPdpt);
> -      if (SubEntriesNum == 0) {
> +      if (SubEntriesNum == 0 &&
> +          (MinPdpt != PFAddressPdptIndex || MinPml4 != PFAddressPml4Index || 
> MinPml5 != PFAddressPml5Index)) {
>          //
>          // Release the empty Page Directory table if there was no more 4 
> KByte Page Table entry
>          // clear the Page directory entry
> @@ -724,7 +743,7 @@ ReclaimPages (
>        //
>        // Update the sub-entries filed in PDPT entry and exit
>        //
> -      SetSubEntriesNum (Pdpt + MinPdpt, SubEntriesNum - 1);
> +      SetSubEntriesNum (Pdpt + MinPdpt, (SubEntriesNum - 1) & 0x1FF);
>        break;
>      }
>      if (MinPdpt != (UINTN)-1) {
> @@ -732,7 +751,7 @@ ReclaimPages (
>        // One 2MB Page Table is released or Page Directory table is released, 
> check the PML4 entry
>        //
>        SubEntriesNum = GetSubEntriesNum (Pml4 + MinPml4);
> -      if (SubEntriesNum == 0) {
> +      if (SubEntriesNum == 0 && (MinPml4 != PFAddressPml4Index || MinPml5 != 
> PFAddressPml5Index)) {
>          //
>          // Release the empty PML4 table if there was no more 1G KByte Page 
> Table entry
>          // clear the Page directory entry
> @@ -745,7 +764,7 @@ ReclaimPages (
>        //
>        // Update the sub-entries filed in PML4 entry and exit
>        //
> -      SetSubEntriesNum (Pml4 + MinPml4, SubEntriesNum - 1);
> +      SetSubEntriesNum (Pml4 + MinPml4, (SubEntriesNum - 1) & 0x1FF);
>        break;
>      }
>      //
> @@ -918,7 +937,7 @@ SmiDefaultPFHandler (
>      PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & gPhyMask & ~((1ull 
> << EndBit) - 1)) |
>                           PageAttribute | IA32_PG_A | PAGE_ATTRIBUTE_BITS;
>      if (UpperEntry != NULL) {
> -      SetSubEntriesNum (UpperEntry, GetSubEntriesNum (UpperEntry) + 1);
> +      SetSubEntriesNum (UpperEntry, (GetSubEntriesNum (UpperEntry) + 1) & 
> 0x1FF);
>      }
>      //
>      // Get the next page address if we need to create more page tables
> --------------------------------------------------------------------
> 
> Intel Technology Poland sp. z o.o.
> ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII 
> Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 
> 957-07-52-316 | Kapital zakladowy 200.000 PLN.
> 
> Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i 
> moze zawierac informacje poufne. W razie przypadkowego otrzymania tej 
> wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; 
> jakiekolwiek
> przegladanie lub rozpowszechnianie jest zabronione.
> This e-mail and any attachments may contain confidential material for the 
> sole use of the intended recipient(s). If you are not the intended recipient, 
> please contact the sender and delete all copies; any review or distribution by
> others is strictly prohibited.
> 

got no capacity left for this; please go ahead with the reviews you
already got

thanks
Laszlo

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45021): https://edk2.groups.io/g/devel/message/45021
Mute This Topic: https://groups.io/mt/32737146/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to