diff options
author | Jiaxin Wu <jiaxin.wu@intel.com> | 2023-04-06 20:42:04 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2023-05-31 04:48:36 +0000 |
commit | 56ad09ba75bef5f095a1a48e365d65195ba45d10 (patch) | |
tree | 63ed588f8dbdd5911230ead2d98a383d4c6de8d4 /UefiCpuPkg | |
parent | b4d3b7797347c37b68bd9b9b6de0e75d9f447b14 (diff) | |
download | edk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.zip edk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.tar.gz edk2-56ad09ba75bef5f095a1a48e365d65195ba45d10.tar.bz2 |
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>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.h | 1 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 1 | ||||
-rw-r--r-- | 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 0649c48..1b9a94e 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 7444bdb..865be56 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 a471f08..b7ddb00 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);
|