From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.158273.1673839420189274937 for ; Sun, 15 Jan 2023 19:23:40 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lichao@loongson.cn) Received: from loongson.cn (unknown [10.40.24.149]) by gateway (Coremail) with SMTP id _____8Bx7eo7w8RjVswBAA--.5648S3; Mon, 16 Jan 2023 11:23:39 +0800 (CST) Received: from [10.40.24.149] (unknown [10.40.24.149]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Dxrb46w8RjHQYaAA--.53666S3; Mon, 16 Jan 2023 11:23:38 +0800 (CST) Message-ID: Date: Mon, 16 Jan 2023 11:23:38 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Subject: Re: [edk2-devel] [edk2-platforms][PATCH V4 7/8] Platform/Loongson: Optimize the huge page and page entry conversion. To: devel@edk2.groups.io, lixianglai@loongson.cn Cc: Ard Biesheuvel , Bibo Mao , Leif Lindholm , Liming Gao , Michael D Kinney References: From: "Chao Li" In-Reply-To: X-CM-TRANSID: AQAAf8Dxrb46w8RjHQYaAA--.53666S3 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQANCGPD7O0FrAAAsM X-Coremail-Antispam: 1Uk129KBjvJXoW3Gr1ftr1UZF17GFyUCF15urg_yoWxGrW3pr 9xCayxK3yUtrZrXFWkXwsI9r4kCr98Wa48Jr47tw1Fk3s8Xwn3uryqkr10qr47JFWfta1U Xay3tw47CFZ5X37anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUUbaxYFVCjjxCrM7AC8VAFwI0_Jr0_ Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AEw4v_JrI_Jryl8cAvFV AK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2 z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr 1UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxI r21l57IF6xkI12xvs2x26I8E6xACxx1lYx0E2Ix0cI8IcVAFwI0_Jw0_WrylYx0Ex4A2js IE14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvEwIxGrwCjr7xvwVCIw2I0 I7xG6c02F41lc7I2V7IY0VAS07AlzVAYIcxG8wCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4 IE7xkEbVWUJVW8JwCFI7km07C267AKxVW8ZVWrXwC20s026c02F40E14v26r106r1rMI8I 3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIx AIcVC0I7IYx2IY67AKxVW5JVW7JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAI cVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2js IEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07j8pnQUUUUU= Content-Type: multipart/alternative; boundary="------------3N4CUkYRQmDzA8SEf9Gg041m" --------------3N4CUkYRQmDzA8SEf9Gg041m Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Reviewed-by: Chao Li Thanks, Chao 在 2023/1/13 11:17, xianglai 写道: > Optimize the process of converting huge pages > to page table entries. > > Cc: Ard Biesheuvel > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > --- > .../Library/MmuLib/MmuLibCore.c | 109 +++++++++++++----- > .../LoongArchQemuPkg/Library/MmuLib/page.h | 3 + > 2 files changed, 82 insertions(+), 30 deletions(-) > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c > index 9e2bd3344a..dac38c63f2 100644 > --- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c > @@ -449,6 +449,29 @@ GetPteAddress ( > return PteOffset (Pmd, Address); > } > > +/** > + Gets the Attributes of Huge Page. > + > + @param Pmd A pointer to the page middle directory. > + > + @retval Value of Attributes. > +**/ > +UINTN > +GetHugePageAttributes ( > + IN PMD *Pmd > + ) > +{ > + UINTN Attributes; > + UINTN GlobalFlag; > + UINTN HugeVal = PMD_VAL(*Pmd); > + > + Attributes = HugeVal & (~HUGEP_PAGE_MASK); > + GlobalFlag = ((Attributes & (1 << PAGE_HGLOBAL_SHIFT)) >> PAGE_HGLOBAL_SHIFT) << PAGE_GLOBAL_SHIFT; > + Attributes &= ~(1 << PAGE_HGLOBAL_SHIFT); > + Attributes |= GlobalFlag; > + return Attributes; > +} > + > /** > Establishes a page table entry based on the specified memory region. > > @@ -477,13 +500,13 @@ MemoryMapPteRange ( > return EFI_OUT_OF_RESOURCES; > } > > + DEBUG ((DEBUG_VERBOSE, > + "%a %d Address %p End %p Attributes %llx\n", > + __func__, __LINE__, Address, End, Attributes)); > + > do { > UpDate = FALSE; > PteVal = MAKE_PTE (Address, Attributes); > - DEBUG ((DEBUG_VERBOSE, > - "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p PTE_INDEX %p MAKE_PTE %p\n", > - __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Address), PMD_INDEX (Address), > - PTE_INDEX (Address), PteVal)); > > if ((!pte_none (*Pte)) && > (PTE_VAL(*Pte) != PTE_VAL(PteVal))) > @@ -500,6 +523,55 @@ MemoryMapPteRange ( > return EFI_SUCCESS; > } > > +/** > + Convert Huge Page to Page. > + > + @param Pmd A pointer to the page middle directory. > + @param Address The memory space start address. > + @param End The end address of the memory space. > + @param Attributes Memory space Attributes. > + > + @retval EFI_SUCCESS The page table entry was created successfully. > + @retval EFI_OUT_OF_RESOURCES Page table entry establishment failed due to resource exhaustion. > +**/ > +EFI_STATUS > +ConvertHugePageToPage ( > + IN PMD *Pmd, > + IN UINTN Address, > + IN UINTN End, > + IN UINTN Attributes > + ) > +{ > + UINTN OldAttributes; > + UINTN HugePageEnd; > + UINTN HugePageStart; > + EFI_STATUS Status; > + > + if ((pmd_none (*Pmd)) || > + (!IS_HUGE_PAGE (Pmd->PmdVal))) > + { > + Status |= MemoryMapPteRange (Pmd, Address, End, Attributes); > + } else { > + OldAttributes = GetHugePageAttributes(Pmd); > + SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte)); > + HugePageStart = Address & PMD_MASK; > + HugePageEnd = HugePageStart + HUGE_PAGE_SIZE; > + ASSERT (HugePageEnd >= End); > + > + if (Address > HugePageStart) { > + Status |= MemoryMapPteRange (Pmd, HugePageStart, Address, OldAttributes); > + } > + > + Status |= MemoryMapPteRange (Pmd, Address, End, Attributes); > + > + if (End < HugePageEnd) { > + Status |= MemoryMapPteRange (Pmd, End, HugePageEnd, OldAttributes); > + } > + } > + > + return Status; > +} > + > /** > Establishes a page middle directory based on the specified memory region. > > @@ -520,10 +592,7 @@ MemoryMapPmdRange ( > ) > { > PMD *Pmd; > - PTE *Pte; > UINTN Next; > - UINTN AddressStart_HugePage; > - UINTN AddressEnd_HugePage; > > Pmd = PmdAllocGet (Pud, Address); > if (!Pmd) { > @@ -534,7 +603,7 @@ MemoryMapPmdRange ( > Next = PMD_ADDRESS_END (Address, End); > if (((Address & (~PMD_MASK)) == 0) && > ((Next & (~PMD_MASK)) == 0) && > - (pmd_none (*Pmd))) > + (pmd_none (*Pmd) || IS_HUGE_PAGE (Pmd->PmdVal))) > { > DEBUG ((DEBUG_VERBOSE, > "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_HUGE_PTE %p\n", > @@ -543,28 +612,7 @@ MemoryMapPmdRange ( > > SetPmd (Pmd, (PTE *)MAKE_HUGE_PTE (Address, Attributes)); > } else { > - if ((pmd_none (*Pmd)) || > - ((!pmd_none (*Pmd)) && > - (!IS_HUGE_PAGE (Pmd->PmdVal)))) > - { > - if (MemoryMapPteRange (Pmd, Address, Next, Attributes)) { > - return EFI_OUT_OF_RESOURCES; > - } > - } else { > - SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte)); > - AddressStart_HugePage = Address & PMD_MASK; > - AddressEnd_HugePage = AddressStart_HugePage + HUGE_PAGE_SIZE; > - if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_HugePage, Attributes)) { > - return EFI_OUT_OF_RESOURCES; > - } > - Pte = GetPteAddress (AddressStart_HugePage); > - if (Pte == NULL) { > - continue ; > - } > - if (AddressEnd_HugePage > End) { > - Next = End; > - } > - } > + ConvertHugePageToPage (Pmd, Address, Next, Attributes); > } > } while (Pmd++, Address = Next, Address != End); > > @@ -788,6 +836,7 @@ LoongArchSetMemoryAttributes ( > Attributes = EfiAttributeToLoongArchAttribute (Attributes); > DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddress , Length, Attributes)); > MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes); > + DEBUG ((DEBUG_VERBOSE, "%a %d end.\n", __func__, __LINE__)); > > return EFI_SUCCESS; > } > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h > index 84c7c13919..927aeb018d 100644 > --- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h > @@ -42,6 +42,9 @@ > #define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SHIFT)) - 1) & \ > (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1)) > > +#define HUGEP_PAGE_MASK (~(((UINTN)(1) << (PMD_SHIFT)) - 1) & \ > + (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1)) > + > typedef struct { UINTN PgdVal; } PGD; > typedef struct { UINTN PudVal; } PUD; > typedef struct { UINTN PmdVal; } PMD; --------------3N4CUkYRQmDzA8SEf9Gg041m Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Reviewed-by: Chao Li <lichao@loongson.cn>


Thanks,
Chao
在 2023/1/13 11:17, xianglai 写道:
Optimize the process of converting huge pages
 to page table entries.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
 .../Library/MmuLib/MmuLibCore.c               | 109 +++++++++++++-----
 .../LoongArchQemuPkg/Library/MmuLib/page.h    |   3 +
 2 files changed, 82 insertions(+), 30 deletions(-)

diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
index 9e2bd3344a..dac38c63f2 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
@@ -449,6 +449,29 @@ GetPteAddress (
   return PteOffset (Pmd, Address);
 }
 
+/**
+  Gets the Attributes of Huge Page.
+
+  @param  Pmd  A pointer to the page middle directory.
+
+  @retval     Value of Attributes.
+**/
+UINTN
+GetHugePageAttributes (
+  IN  PMD *Pmd
+  )
+{
+  UINTN Attributes;
+  UINTN GlobalFlag;
+  UINTN HugeVal = PMD_VAL(*Pmd);
+
+  Attributes = HugeVal & (~HUGEP_PAGE_MASK);
+  GlobalFlag = ((Attributes & (1 << PAGE_HGLOBAL_SHIFT)) >> PAGE_HGLOBAL_SHIFT) << PAGE_GLOBAL_SHIFT;
+  Attributes &= ~(1 << PAGE_HGLOBAL_SHIFT);
+  Attributes |= GlobalFlag;
+  return Attributes;
+}
+
 /**
   Establishes a page table entry based on the specified memory region.
 
@@ -477,13 +500,13 @@ MemoryMapPteRange (
     return EFI_OUT_OF_RESOURCES;
   }
 
+  DEBUG ((DEBUG_VERBOSE,
+    "%a %d Address %p End %p  Attributes %llx\n",
+    __func__, __LINE__,  Address, End, Attributes));
+
   do {
     UpDate = FALSE;
     PteVal = MAKE_PTE (Address, Attributes);
-    DEBUG ((DEBUG_VERBOSE,
-      "%a %d Address %p  PGD_INDEX %p PUD_INDEX   %p PMD_INDEX  %p PTE_INDEX  %p MAKE_PTE  %p\n",
-      __func__, __LINE__,  Address, PGD_INDEX (Address), PUD_INDEX (Address), PMD_INDEX (Address),
-      PTE_INDEX (Address), PteVal));
 
     if ((!pte_none (*Pte)) &&
         (PTE_VAL(*Pte) != PTE_VAL(PteVal)))
@@ -500,6 +523,55 @@ MemoryMapPteRange (
   return EFI_SUCCESS;
 }
 
+/**
+  Convert Huge Page to Page.
+
+  @param  Pmd  A pointer to the page middle directory.
+  @param  Address  The memory space start address.
+  @param  End  The end address of the memory space.
+  @param  Attributes  Memory space Attributes.
+
+  @retval  EFI_SUCCESS   The page table entry was created successfully.
+  @retval  EFI_OUT_OF_RESOURCES  Page table entry establishment failed due to resource exhaustion.
+**/
+EFI_STATUS
+ConvertHugePageToPage (
+  IN  PMD *Pmd,
+  IN UINTN Address,
+  IN UINTN End,
+  IN UINTN Attributes
+  )
+{
+  UINTN OldAttributes;
+  UINTN HugePageEnd;
+  UINTN HugePageStart;
+  EFI_STATUS Status;
+
+  if ((pmd_none (*Pmd)) ||
+      (!IS_HUGE_PAGE (Pmd->PmdVal)))
+  {
+    Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+  } else {
+    OldAttributes = GetHugePageAttributes(Pmd);
+    SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));
+    HugePageStart = Address & PMD_MASK;
+    HugePageEnd = HugePageStart + HUGE_PAGE_SIZE;
+    ASSERT (HugePageEnd >= End);
+
+    if (Address > HugePageStart) {
+      Status |= MemoryMapPteRange (Pmd, HugePageStart, Address, OldAttributes);
+    }
+
+    Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+
+    if (End < HugePageEnd) {
+      Status |= MemoryMapPteRange (Pmd, End, HugePageEnd, OldAttributes);
+    }
+  }
+
+  return Status;
+}
+
 /**
   Establishes a page middle directory based on the specified memory region.
 
@@ -520,10 +592,7 @@ MemoryMapPmdRange (
   )
 {
   PMD *Pmd;
-  PTE *Pte;
   UINTN Next;
-  UINTN AddressStart_HugePage;
-  UINTN AddressEnd_HugePage;
 
   Pmd = PmdAllocGet (Pud, Address);
   if (!Pmd) {
@@ -534,7 +603,7 @@ MemoryMapPmdRange (
     Next = PMD_ADDRESS_END (Address, End);
     if (((Address & (~PMD_MASK)) == 0) &&
         ((Next &  (~PMD_MASK)) == 0) &&
-        (pmd_none (*Pmd)))
+        (pmd_none (*Pmd) || IS_HUGE_PAGE (Pmd->PmdVal)))
     {
       DEBUG ((DEBUG_VERBOSE,
         "%a %d Address %p  PGD_INDEX %p PUD_INDEX   %p PMD_INDEX  %p MAKE_HUGE_PTE  %p\n",
@@ -543,28 +612,7 @@ MemoryMapPmdRange (
 
       SetPmd (Pmd, (PTE *)MAKE_HUGE_PTE (Address, Attributes));
     } else {
-       if ((pmd_none (*Pmd)) ||
-          ((!pmd_none (*Pmd)) &&
-           (!IS_HUGE_PAGE (Pmd->PmdVal))))
-       {
-         if (MemoryMapPteRange (Pmd, Address, Next, Attributes)) {
-           return EFI_OUT_OF_RESOURCES;
-         }
-       } else {
-         SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));
-         AddressStart_HugePage = Address & PMD_MASK;
-         AddressEnd_HugePage = AddressStart_HugePage + HUGE_PAGE_SIZE;
-         if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_HugePage, Attributes)) {
-           return EFI_OUT_OF_RESOURCES;
-         }
-         Pte = GetPteAddress (AddressStart_HugePage);
-         if (Pte == NULL) {
-           continue ;
-         }
-         if (AddressEnd_HugePage > End) {
-           Next = End;
-         }
-       }
+      ConvertHugePageToPage (Pmd, Address, Next, Attributes);
     }
   } while (Pmd++, Address = Next, Address != End);
 
@@ -788,6 +836,7 @@ LoongArchSetMemoryAttributes (
   Attributes = EfiAttributeToLoongArchAttribute (Attributes);
   DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddress , Length, Attributes));
   MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes);
+  DEBUG ((DEBUG_VERBOSE, "%a %d end.\n", __func__, __LINE__));
 
   return EFI_SUCCESS;
 }
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
index 84c7c13919..927aeb018d 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
@@ -42,6 +42,9 @@
 #define PFN_MASK                            (~(((UINTN)(1) << (EFI_PAGE_SHIFT)) - 1) & \
                                              (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
 
+#define HUGEP_PAGE_MASK                     (~(((UINTN)(1) << (PMD_SHIFT)) - 1) & \
+                                             (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
+
 typedef struct { UINTN PgdVal; } PGD;
 typedef struct { UINTN PudVal; } PUD;
 typedef struct { UINTN PmdVal; } PMD;
--------------3N4CUkYRQmDzA8SEf9Gg041m--