[edk2-devel] [edk2-platforms][PATCH V1 4/4] Platform/Loongson: Fixed the bug during page table creation.

xianglai lixianglai at loongson.cn
Wed Jan 4 03:10:35 UTC 2023


1.Open the NULL pointer protection policy.
2.Fixed the bug of converting huge page to page entry.
3.Adjust the access level of page entry.
4.Optimize the existence of page entry judgment functions.

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

diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
index b932e3d568..42f92745be 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,61 @@ 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 AddressEnd_HugePage;
+  UINTN AddressStart_HugePage;
+  EFI_STATUS Status;
+
+  if ((pmd_none (*Pmd)) ||
+      ((!pmd_none (*Pmd)) &&
+       (!IS_HUGE_PAGE (Pmd->PmdVal))))
+  {
+    Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+  } else {
+    OldAttributes = GetHugePageAttributes(Pmd);
+    SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));
+    AddressStart_HugePage = Address & PMD_MASK;
+    AddressEnd_HugePage = AddressStart_HugePage + HUGE_PAGE_SIZE;
+    if (End >= AddressEnd_HugePage) {
+      if (Address > AddressStart_HugePage) {
+        Status |= MemoryMapPteRange (Pmd, AddressStart_HugePage, Address, OldAttributes);
+        Status |= MemoryMapPteRange (Pmd, Address, AddressEnd_HugePage, Attributes);
+      } else {
+        Status |= MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_HugePage, Attributes);
+      }
+    } else {
+      if (Address > AddressStart_HugePage) {
+        Status |= MemoryMapPteRange (Pmd, AddressStart_HugePage, Address, OldAttributes);
+        Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+      } else {
+        Status |= MemoryMapPteRange (Pmd, AddressStart_HugePage, End, Attributes);
+      }
+      Status |= MemoryMapPteRange (Pmd, End, AddressEnd_HugePage, OldAttributes);
+    }
+  }
+
+  return Status;
+}
+
 /**
   Establishes a page middle directory based on the specified memory region.
 
@@ -520,10 +598,7 @@ MemoryMapPmdRange (
   )
 {
   PMD *Pmd;
-  PTE *Pte;
   UINTN Next;
-  UINTN AddressStart_HugePage;
-  UINTN AddressEnd_HugePage;
 
   Pmd = PmdAllocGet (Pud, Address);
   if (!Pmd) {
@@ -543,28 +618,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);
 
@@ -671,7 +725,7 @@ EfiAttributeToLoongArchAttribute (
   IN UINTN  EfiAttributes
   )
 {
-  UINTN  LoongArchAttributes = PAGE_VALID | PAGE_DIRTY | CACHE_CC | PAGE_USER | PAGE_GLOBAL;
+  UINTN  LoongArchAttributes = PAGE_VALID | PAGE_DIRTY | CACHE_CC | PLV_KERNEL | PAGE_GLOBAL;
   switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
     case EFI_MEMORY_UC:
       LoongArchAttributes |= CACHE_SUC;
@@ -687,10 +741,16 @@ EfiAttributeToLoongArchAttribute (
   }
 
   // Write protection attributes
-  if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
+  if (((EfiAttributes & EFI_MEMORY_RO) != 0) ||
+      ((EfiAttributes & EFI_MEMORY_WP) != 0))
+  {
     LoongArchAttributes &= ~PAGE_DIRTY;
   }
 
+  if (EfiAttributes & EFI_MEMORY_RP) {
+    LoongArchAttributes |= PAGE_NO_READ;
+  }
+
   //eXecute protection attribute
   if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
     LoongArchAttributes |= PAGE_NO_EXEC;
@@ -788,6 +848,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/MmuLibCorePei.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c
index 32a7fc0beb..491b75552c 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c
@@ -21,6 +21,7 @@
 #include <Library/QemuFwCfgLib.h>
 #include "MmuLibCore.h"
 #include <Library/CacheMaintenanceLib.h>
+#include <Library/MmuLib.h>
 
 /**
   Return the Virtual Memory Map of your platform
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
index 6ab07e7900..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;
@@ -275,6 +278,6 @@ pte_none (
   IN PTE pte
   )
 {
-  return (!(PTE_VAL(pte) & (~PAGE_GLOBAL)));
+  return (!(PTE_VAL(pte) & (~PAGE_VALID)));
 }
 #endif // PAGE_H_
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
index 650042662d..45be8d146d 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
@@ -365,6 +365,8 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize         | 0x40000
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize       | 0x40000
 
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask   | 1
+
 ################################################################################
 #
 # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#97902): https://edk2.groups.io/g/devel/message/97902
Mute This Topic: https://groups.io/mt/96044050/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list