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.d...@intel.com> Cc: Ray Ni <ray...@intel.com> Cc: Zeng Star <star.z...@intel.com> Cc: Gerd Hoffmann <kra...@redhat.com> Cc: Rahul Kumar <rahul1.ku...@intel.com> Signed-off-by: Jiaxin Wu <jiaxin...@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/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-