[edk2-devel] [PATCH v3 2/5] UefiCpuPkg/CpuMpPei: Conditionally enable PAE paging in 32bit mode

Wu, Jiaxin posted 5 patches 1 year, 3 months ago
[edk2-devel] [PATCH v3 2/5] UefiCpuPkg/CpuMpPei: Conditionally enable PAE paging in 32bit mode
Posted by Wu, Jiaxin 1 year, 3 months ago
Some security features depend on the page table enabling. So, This
patch is to enable paging if it is not enabled (32bit mode)"

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Zeng Star <star.zeng@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
---
 UefiCpuPkg/CpuMpPei/CpuMpPei.h   |   1 +
 UefiCpuPkg/CpuMpPei/CpuMpPei.inf |   1 +
 UefiCpuPkg/CpuMpPei/CpuPaging.c  | 202 ++++++++++++++-------------------------
 3 files changed, 75 insertions(+), 129 deletions(-)

diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
index 0649c48d14..1b9a94e18f 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
@@ -26,10 +26,11 @@
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/CpuExceptionHandlerLib.h>
 #include <Library/MpInitLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/CpuPageTableLib.h>
 
 extern EFI_PEI_PPI_DESCRIPTOR  mPeiCpuMpPpiDesc;
 
 /**
   This service retrieves the number of logical processor in the platform
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
index 7444bdb968..865be5627e 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
@@ -44,10 +44,11 @@
   CpuExceptionHandlerLib
   MpInitLib
   BaseMemoryLib
   CpuLib
   MemoryAllocationLib
+  CpuPageTableLib
 
 [Guids]
   gEdkiiMigratedFvInfoGuid                                             ## SOMETIMES_CONSUMES     ## HOB
 
 [Ppis]
diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c
index a471f089c8..976a912741 100644
--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c
+++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c
@@ -115,42 +115,10 @@ AllocatePageTableMemory (
   }
 
   return Address;
 }
 
-/**
-  Get the address width supported by current processor.
-
-  @retval 32      If processor is in 32-bit mode.
-  @retval 36-48   If processor is in 64-bit mode.
-
-**/
-UINTN
-GetPhysicalAddressWidth (
-  VOID
-  )
-{
-  UINT32  RegEax;
-
-  if (sizeof (UINTN) == 4) {
-    return 32;
-  }
-
-  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
-  if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
-    AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
-    RegEax &= 0xFF;
-    if (RegEax > 48) {
-      return 48;
-    }
-
-    return (UINTN)RegEax;
-  }
-
-  return 36;
-}
-
 /**
   Get the type of top level page table.
 
   @retval Page512G  PML4 paging.
   @retval Page1G    PAE paging.
@@ -381,120 +349,84 @@ ConvertMemoryPageAttributes (
 
   return RETURN_SUCCESS;
 }
 
 /**
-  Get maximum size of page memory supported by current processor.
-
-  @param[in]   TopLevelType     The type of top level page entry.
-
-  @retval Page1G     If processor supports 1G page and PML4.
-  @retval Page2M     For all other situations.
-
-**/
-PAGE_ATTRIBUTE
-GetMaxMemoryPage (
-  IN  PAGE_ATTRIBUTE  TopLevelType
-  )
-{
-  UINT32  RegEax;
-  UINT32  RegEdx;
-
-  if (TopLevelType == Page512G) {
-    AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
-    if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
-      AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
-      if ((RegEdx & BIT26) != 0) {
-        return Page1G;
-      }
-    }
-  }
-
-  return Page2M;
-}
-
-/**
-  Create PML4 or PAE page table.
+  Enable PAE Page Table.
 
-  @return The address of page table.
+  @retval   EFI_SUCCESS           The PAE Page Table was enabled successfully.
+  @retval   EFI_OUT_OF_RESOURCES  The PAE Page Table could not be enabled due to lack of available memory.
 
 **/
-UINTN
-CreatePageTable (
+EFI_STATUS
+EnablePaePageTable (
   VOID
   )
 {
-  RETURN_STATUS         Status;
-  UINTN                 PhysicalAddressBits;
-  UINTN                 NumberOfEntries;
-  PAGE_ATTRIBUTE        TopLevelPageAttr;
-  UINTN                 PageTable;
-  PAGE_ATTRIBUTE        MaxMemoryPage;
-  UINTN                 Index;
-  UINT64                AddressEncMask;
-  UINT64                *PageEntry;
-  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+  EFI_STATUS   Status;
+
+  UINTN               PageTable;
+  VOID                *Buffer;
+  UINTN               BufferSize;
+  IA32_MAP_ATTRIBUTE  MapAttribute;
+  IA32_MAP_ATTRIBUTE  MapMask;
+
+  PageTable                   = 0;
+  Buffer                      = NULL;
+  BufferSize                  = 0;
+  MapAttribute.Uint64         = 0;
+  MapMask.Uint64              = MAX_UINT64;
+  MapAttribute.Bits.Present   = 1;
+  MapAttribute.Bits.ReadWrite = 1;
 
-  TopLevelPageAttr    = (PAGE_ATTRIBUTE)GetPageTableTopLevelType ();
-  PhysicalAddressBits = GetPhysicalAddressWidth ();
-  NumberOfEntries     = (UINTN)1 << (PhysicalAddressBits -
-                                     mPageAttributeTable[TopLevelPageAttr].AddressBitOffset);
-
-  PageTable = (UINTN)AllocatePageTableMemory (1);
-  if (PageTable == 0) {
-    return 0;
+  //
+  // 1:1 map 4GB in 32bit mode
+  //
+  Status = PageTableMap (&PageTable, PagingPae, 0, &BufferSize, 0, SIZE_4GB, &MapAttribute, &MapMask, NULL);
+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    return Status;
   }
 
-  AddressEncMask  = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask);
-  AddressEncMask &= mPageAttributeTable[TopLevelPageAttr].AddressMask;
-  MaxMemoryPage   = GetMaxMemoryPage (TopLevelPageAttr);
-  PageEntry       = (UINT64 *)PageTable;
-
-  PhysicalAddress = 0;
-  for (Index = 0; Index < NumberOfEntries; ++Index) {
-    *PageEntry = PhysicalAddress | AddressEncMask | PAGE_ATTRIBUTE_BITS;
+  //
+  // Allocate required Buffer.
+  //
+  Buffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (BufferSize));
+  ASSERT (Buffer != NULL);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
-    //
-    // Split the top page table down to the maximum page size supported
-    //
-    if (MaxMemoryPage < TopLevelPageAttr) {
-      Status = SplitPage (PageEntry, TopLevelPageAttr, MaxMemoryPage, TRUE);
-      ASSERT_EFI_ERROR (Status);
-    }
+  Status = PageTableMap (&PageTable, PagingPae, Buffer, &BufferSize, 0, SIZE_4GB, &MapAttribute, &MapMask, NULL);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status) || (PageTable == 0)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
-    if (TopLevelPageAttr == Page1G) {
-      //
-      // PDPTE[2:1] (PAE Paging) must be 0. SplitPage() might change them to 1.
-      //
-      *PageEntry &= ~(UINT64)(IA32_PG_RW | IA32_PG_U);
-    }
+  //
+  // Write the Pagetable to CR3.
+  //
+  AsmWriteCr3 (PageTable);
 
-    PageEntry       += 1;
-    PhysicalAddress += mPageAttributeTable[TopLevelPageAttr].Length;
-  }
+  //
+  // Enable CR4.PAE
+  //
+  AsmWriteCr4 (AsmReadCr4 () | BIT5);
 
-  return PageTable;
-}
+  //
+  // Enable CR0.PG
+  //
+  AsmWriteCr0 (AsmReadCr0 () | BIT31);
 
-/**
-  Setup page tables and make them work.
+  DEBUG ((
+    DEBUG_INFO,
+    "EnablePaePageTable: Created PageTable = 0x%x, BufferSize = %x\n",
+    PageTable,
+    BufferSize
+    ));
 
-**/
-VOID
-EnablePaging (
-  VOID
-  )
-{
-  UINTN  PageTable;
-
-  PageTable = CreatePageTable ();
-  ASSERT (PageTable != 0);
-  if (PageTable != 0) {
-    AsmWriteCr3 (PageTable);
-    AsmWriteCr4 (AsmReadCr4 () | BIT5);   // CR4.PAE
-    AsmWriteCr0 (AsmReadCr0 () | BIT31);  // CR0.PG
-  }
+  return Status;
 }
 
 /**
   Get the base address of current AP's stack.
 
@@ -622,10 +554,11 @@ MemoryDiscoveredPpiNotifyCallback (
 {
   EFI_STATUS              Status;
   BOOLEAN                 InitStackGuard;
   EDKII_MIGRATED_FV_INFO  *MigratedFvInfo;
   EFI_PEI_HOB_POINTERS    Hob;
+  IA32_CR0                Cr0;
 
   //
   // Paging must be setup first. Otherwise the exception TSS setup during MP
   // initialization later will not contain paging information and then fail
   // the task switch (for the sake of stack switch).
@@ -635,12 +568,23 @@ MemoryDiscoveredPpiNotifyCallback (
   if (IsIa32PaeSupported ()) {
     Hob.Raw        = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
     InitStackGuard = PcdGetBool (PcdCpuStackGuard);
   }
 
-  if (InitStackGuard || (Hob.Raw != NULL)) {
-    EnablePaging ();
+  //
+  // Some security features depend on the page table enabling. So, here
+  // is to enable paging if it is not enabled (only in 32bit mode).
+  //
+  Cr0.UintN = AsmReadCr0 ();
+  if ((Cr0.Bits.PG == 0) && (InitStackGuard || (Hob.Raw != NULL))) {
+    ASSERT (sizeof (UINTN) == sizeof (UINT32));
+
+    Status = EnablePaePageTable ();
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "MemoryDiscoveredPpiNotifyCallback: Failed to enable PAE page table: %r.\n", Status));
+      CpuDeadLoop ();
+    }
   }
 
   Status = InitializeCpuMpWorker ((CONST EFI_PEI_SERVICES **)PeiServices);
   ASSERT_EFI_ERROR (Status);
 
-- 
2.16.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#104841): https://edk2.groups.io/g/devel/message/104841
Mute This Topic: https://groups.io/mt/98895182/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-