summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2023-04-06 20:42:04 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-05-31 04:48:36 +0000
commit56ad09ba75bef5f095a1a48e365d65195ba45d10 (patch)
tree63ed588f8dbdd5911230ead2d98a383d4c6de8d4
parentb4d3b7797347c37b68bd9b9b6de0e75d9f447b14 (diff)
downloadedk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.tar.gz
edk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.tar.bz2
edk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.zip
UefiCpuPkg/CpuMpPei: Conditionally enable PAE paging in 32bit mode
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> Reviewed-by: Ray Ni <ray.ni@intel.com>
-rw-r--r--UefiCpuPkg/CpuMpPei/CpuMpPei.h1
-rw-r--r--UefiCpuPkg/CpuMpPei/CpuMpPei.inf1
-rw-r--r--UefiCpuPkg/CpuMpPei/CpuPaging.c202
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
@@ -28,6 +28,7 @@
#include <Library/MpInitLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/CpuPageTableLib.h>
extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc;
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
@@ -46,6 +46,7 @@
BaseMemoryLib
CpuLib
MemoryAllocationLib
+ CpuPageTableLib
[Guids]
gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB
diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c
index a471f089c8..b7ddb0005b 100644
--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c
+++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c
@@ -118,38 +118,6 @@ AllocatePageTableMemory (
}
/**
- 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.
@@ -383,116 +351,80 @@ ConvertMemoryPageAttributes (
}
/**
- 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;
}
/**
@@ -624,6 +556,7 @@ MemoryDiscoveredPpiNotifyCallback (
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
@@ -637,8 +570,19 @@ MemoryDiscoveredPpiNotifyCallback (
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);